I'm creating a datagridview transparent
//I got the parent background image
Bitmap parentBackGround = new Bitmap(this.Parent.BackgroundImage);
//Set the area i want to create equal to the size of my grid
Rectangle rect = new Rectangle(this.Location.X, this.Location.Y, this.Width, this.Height);
//And draw in the entire grid the area of the background image that is cover with my grid, making a "transparent" effect.
graphics.DrawImage(parentBackGround.Clone(rect, PixelFormat.Format32bppRgb), gridBounds);
When the backgroundimage of the grid's parent is show in an normal layout all work ok, but if the layout is stretch, center or any other, the transparency effent gone, have you any idea to fix it?
why not trying with the TransparencyKey property (Form) Instead?
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.transparencykey.aspx
Well i create a bitmap and copy the background image of the form parent of the grid in it exactly size, and then use only the part it cover my grid.
I inherit from grid and override those methods:
protected override void PaintBackground(Graphics graphics, Rectangle clipBounds, Rectangle gridBounds)
{
base.PaintBackground(graphics, clipBounds, gridBounds);
if (DesignMode) return;
Control tmpParent = Parent;
int locationX = this.Location.X;
int locationY = this.Location.Y;
while (tmpParent.BackgroundImage == null)
{
locationX += tmpParent.Location.X;
locationY += tmpParent.Location.Y;
tmpParent = tmpParent.Parent;
}
Rectangle rectSource = new Rectangle(locationX, locationY, this.Width, this.Height);
Rectangle rectDest = new Rectangle(0, 0, rectSource.Width, rectSource.Height);
Bitmap b = new Bitmap(tmpParent.ClientRectangle.Width, tmpParent.ClientRectangle.Height);
Graphics.FromImage(b).DrawImage(tmpParent.BackgroundImage, tmpParent.ClientRectangle);
graphics.DrawImage(b, rectDest, rectSource, GraphicsUnit.Pixel);
SetCellsTransparent();
}
public void SetCellsTransparent()
{
this.EnableHeadersVisualStyles = false;
this.ColumnHeadersDefaultCellStyle.BackColor = Color.Transparent;
this.RowHeadersDefaultCellStyle.BackColor = Color.Transparent;
foreach (DataGridViewColumn col in this.Columns)
{
col.DefaultCellStyle.BackColor = Color.Transparent;
col.DefaultCellStyle.SelectionBackColor = Color.Transparent;
}
}
Related
I'm trying to extend the C# Button class so that I can color the button, with up to 3 colours, according to the percentages provided. It appears to work apart from the button text is not shown. Please can somebody advise how to display the text?
Also, I'm unsure as to whether Refresh() is the correct method to call in the Setter methods to trigger a redraw with the new percentage provided?
Many thanks.
class TriColorsButton : Button
{
private double percentOfLeftColor, percentOfRightColor;
public TriColorsButton(String text, double percentOfLeftColor, double percentOfRightColor)
{
this.Text = text;
this.percentOfLeftColor = percentOfLeftColor;
this.percentOfRightColor = percentOfRightColor;
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
Brush brush;
RectangleF rectFirst, rectSecond, rectThird;
Color c1, c2, c3;
// create the first rectangle
rectFirst = new RectangleF(0, 0, this.Width, this.Height);
// create the second rectangle
int callWidth = (int)(this.Width * (100 - percentOfRightColor) / 100);
rectSecond = new RectangleF(0, 0, callWidth, this.Height);
// create the third rectangle
int leftWidth = (int)(this.Width * percentOfLeftColor / 100);
rectThird = new RectangleF(0, 0, leftWidth, this.Height);
// create the colors
c1 = Constants.altFoldColor;
c2 = Constants.altCallColor;
c3 = Constants.altRaiseColor;
// create the brush
brush = new SolidBrush(c1);
// fill the segment
pe.Graphics.FillRectangle(brush, rectFirst);
// create the brush
brush = new SolidBrush(c2);
// fill the segment
pe.Graphics.FillRectangle(brush, rectSecond);
// create the brush
brush = new SolidBrush(c3);
// fill the segment
pe.Graphics.FillRectangle(brush, rectThird);
// dispose of the brush
brush.Dispose();
}
public void SetPercentOfLeftColor(double percentOfLeftColor)
{
this.percentOfLeftColor = percentOfLeftColor;
Refresh();
}
public double GetPercentOfLeftColor()
{
return percentOfLeftColor;
}
public void SetPercentOfRightColor(double percentOfRightColor)
{
this.percentOfRightColor = percentOfRightColor;
Refresh();
}
public double GetPercentOfRightColor()
{
return percentOfRightColor;
}
}
Also, although this paints the colors that I want, I lose the original look and feel of a standard button. I'd like to retain the standard button look and feel such as the on-hover highlighting and border of a standard button. How can I achieve this?
EDIT: Upon suggestion I tried to draw a background image for the button instead. This had a strange effect of causing most of my form to go white. It would redraw and look better if I moved the form on screen but other updates wouldn't happen appropriately. This is what I tried:
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
Image bmp = new Bitmap(Width, Height);
using (Graphics g = Graphics.FromImage(bmp))
{
Brush brush;
RectangleF rectFirst, rectSecond, rectThird;
Color c1, c2, c3;
// create the first rectangle
rectFirst = new RectangleF(0, 0, this.Width, this.Height);
// create the second rectangle
int callWidth = (int)(this.Width * (100 - percentOfRightColor) / 100);
rectSecond = new RectangleF(0, 0, callWidth, this.Height);
// create the third rectangle
int leftWidth = (int)(this.Width * percentOfLeftColor / 100);
rectThird = new RectangleF(0, 0, leftWidth, this.Height);
// create the colors
c1 = Constants.altFoldColor;
c2 = Constants.altCallColor;
c3 = Constants.altRaiseColor;
// create the brush
brush = new SolidBrush(c1);
// fill the segment
g.FillRectangle(brush, rectFirst);
// create the brush
brush = new SolidBrush(c2);
// fill the segment
g.FillRectangle(brush, rectSecond);
// create the brush
brush = new SolidBrush(c3);
// fill the segment
g.FillRectangle(brush, rectThird);
// dispose of the brush
brush.Dispose();
}
this.BackgroundImage = bmp;
}
EDIT2: I figured out how to achieve what I wanted. I added a method that draws and sets the background and called it from the constructor. The OnPaint method no longer requires an override:
private void SetBackgroundImage()
{
Image bmp = new Bitmap(Width, Height);
using (Graphics g = Graphics.FromImage(bmp))
{
Brush brush;
RectangleF rectFirst, rectSecond, rectThird;
Color c1, c2, c3;
// create the first rectangle
rectFirst = new RectangleF(0, 0, this.Width, this.Height);
// create the second rectangle
int callWidth = (int)(this.Width * (100 - percentOfRightColor) / 100);
rectSecond = new RectangleF(0, 0, callWidth, this.Height);
// create the third rectangle
int leftWidth = (int)(this.Width * percentOfLeftColor / 100);
rectThird = new RectangleF(0, 0, leftWidth, this.Height);
// create the colors
c1 = Constants.altFoldColor;
c2 = Constants.altCallColor;
c3 = Constants.altRaiseColor;
// create the brush
brush = new SolidBrush(c1);
// fill the segment
g.FillRectangle(brush, rectFirst);
// create the brush
brush = new SolidBrush(c2);
// fill the segment
g.FillRectangle(brush, rectSecond);
// create the brush
brush = new SolidBrush(c3);
// fill the segment
g.FillRectangle(brush, rectThird);
// dispose of the brush
brush.Dispose();
}
this.BackgroundImage = bmp;
}
Overriding OnPaint in windows forms is mostly an all or nothing affair. I.e. if you need custom drawing, you need to draw everything, including the text. In this regard WPF is a bit better since it allows for better modularity.
This should be fairly easy to fix by inserting a call to Graphics.DrawString or TextRendered.DrawText at the end of your OnPaint method, where TextRendered.DrawText should be more consistent with other controls. You might also need some way to ensure sufficient contrast, like adding a drop shadow or a background rectangle. Note that drawing is done in the same order as the calls are made, i.e. later draw calls will be on top of earlier, so your call to base.OnPaint(pe); might be redundant if it is completely overdrawn anyway.
Also, I'm unsure as to whether Refresh() is the correct method to call in the Setter methods to trigger a redraw with the new percentage provided?
I usually use .Invalidate(). If I understand the documentation correctly, the difference is that Invalidate redraws the control at some later time, while Refresh redraws it immediately.
I already made a rounded button and now im trying to create a rounded textbox. I searched some questions but all is in VB and I don't know that language. And converters are weird. So I tried creating a rounded textbox. So I set the UserPaint to true so I can use OnPaint. It works beautifully on my buttons but it glitches out on my textboxes. It has 2 issues:
The font size is always the same size no matter what I set it to.
And when onpaint is called but the text doesn't change it deletes it. That is mostly when I hover my mouse over it.
Code:
class RoundedTextBox : TextBox
{
public Color color = Color.White;
public int borderRadius = 25;
public RoundedTextBox()
{
SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
RectangleF Rect = new RectangleF(0, 0, this.Width, this.Height);
SolidBrush brush = new SolidBrush(color);
GraphicsPath GraphPath = Functions.FillRoundedRectangle(e.Graphics, brush, Rect, borderRadius);
this.Region = new Region(GraphPath);
}
}
How I add my textbox:
RoundedTextBox usernameTextbox = new RoundedTextBox();
usernameTextbox.Location = new Point(14, 217);
usernameTextbox.Font = new Font(usernameTextbox.Font.FontFamily, 20);
usernameTextbox.Size = new Size(282, this.Height);
usernameTextbox.color = Color.White;
usernameTextbox.Name = "usernameTextbox";
usernameTextbox.Text = "test";
textboxes.Add(usernameTextbox);
usernameTextbox.BackColor = Color.White;
usernameTextbox.borderRadius = 20;
this.Controls.Add(usernameTextbox);
Gif of the problem
I want to apply the opacity of a linear gradient to an image, but all I have been able to get is the gradient painted on top of the image.
Following this stackoverflow post, I created a user control that inherits from PictureBox and I overrode the OnPaint method
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
LinearGradientBrush linearGradientBrush = new LinearGradientBrush(
this.ClientRectangle,
Color.FromArgb(255, Color.White),
Color.FromArgb(0, Color.White),
0f);
e.Graphics.FillRectangle(linearGradientBrush, this.ClientRectangle);
}
However, that simply paints the linear gradient on top of the image.
How do I apply the opacity of the linear gradient to the image?
I find examples in XAML (), but not for winforms.
It is not necessary to use a user control and override the OnPaint event. Just create a graphics object from a blank image and do your image manipulation and assign the image to a PicturePox.
First draw the linearGradientBrush to the background and afterwards draw the image over it. Always take care about the sequence of your image operations.
FileInfo inputImageFile = new FileInfo(#"C:\Temp\TheSimpsons.png");
Bitmap inputImage = (Bitmap)Bitmap.FromFile(inputImageFile.FullName);
// create blank bitmap with same size
Bitmap combinedImage = new Bitmap(inputImage.Width, inputImage.Height);
// create graphics object on new blank bitmap
Graphics g = Graphics.FromImage(combinedImage);
// also use the same size for the gradient brush and for the FillRectangle function
LinearGradientBrush linearGradientBrush = new LinearGradientBrush(
new Rectangle(0,0,combinedImage.Width, combinedImage.Height),
Color.FromArgb(255, Color.White), //Color.White,
Color.FromArgb(0, Color.White), // Color.Transparent,
0f);
g.FillRectangle(linearGradientBrush, 0, 0, combinedImage.Width, combinedImage.Height);
g.DrawImage(inputImage, 0,0);
previewPictureBox.Image = combinedImage;
Result with black as the forms background color and the example image with transparency.
EDIT:
I may have misunderstood the intention, and either haven't found an easy way like in WPF, but it is not this much difficult.
FileInfo inputImageFile = new FileInfo(#"C:\Temp\TheSimpsons.png");
Bitmap inputImage = (Bitmap)Bitmap.FromFile(inputImageFile.FullName);
// create blank bitmap
Bitmap adjImage = new Bitmap(inputImage.Width, inputImage.Height);
// create graphics object on new blank bitmap
Graphics g = Graphics.FromImage(adjImage);
LinearGradientBrush linearGradientBrush = new LinearGradientBrush(
new Rectangle(0, 0, adjImage.Width, adjImage.Height),
Color.White,
Color.Transparent,
0f);
Rectangle rect = new Rectangle(0, 0, adjImage.Width, adjImage.Height);
g.FillRectangle(linearGradientBrush, rect);
int x;
int y;
for (x = 0; x < adjImage.Width; ++x)
{
for (y = 0; y < adjImage.Height; ++y)
{
Color inputPixelColor = inputImage.GetPixel(x, y);
Color adjPixelColor = adjImage.GetPixel(x, y);
Color newColor = Color.FromArgb(adjPixelColor.A, inputPixelColor.R, inputPixelColor.G, inputPixelColor.B);
adjImage.SetPixel(x, y, newColor);
}
}
previewPictureBox.Image = adjImage;
I have a ToolStripContainer on a winform. I want to set the BackColor of its ContentPanel to custom gradient color.
How can I set it?
You can create a simple class that inherits from ToolStripContainer and set up BackgroundImage (or anything else) in the its constructor. For example:
class MyToolStripContainer : System.Windows.Forms.ToolStripContainer
{
public MyToolStripContainer()
{
var rect = new Rectangle(0, 0, 300, 300);
using (Bitmap bitmap = new Bitmap(rect.Height, rect.Width))
using (Graphics graphics = Graphics.FromImage(bitmap))
using (LinearGradientBrush brush = new LinearGradientBrush(
rect,
Color.Blue,
Color.Red,
LinearGradientMode.ForwardDiagonal))
{
brush.SetSigmaBellShape(0.5f);
graphics.FillRectangle(brush, rect);
ContentPanel.BackgroundImage = Image.FromHbitmap(bitmap.GetHbitmap());
}
ContentPanel.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
}
}
Not only ToolStripContentPanel, no winform controls supports "Gradient colors" out of the box, but they provide a way to custom painting. That's how we can accomplish the gradient look and feel in winforms.
toolStripContainer1.ContentPanel.Paint += ContentPanel_Paint;//Triggering up the paint event
public void ContentPanel_Paint(object sender, PaintEventArgs e)
{
ToolStripContentPanel panel = (ToolStripContentPanel)sender;
using (var brush = new LinearGradientBrush(panel.ClientRectangle, Color.Gray, Color.Red, 90))
{
e.Graphics.FillRectangle(brush, panel.ClientRectangle);
}
}
I have a UserControl that contains a PictureBox and a Label. The Control loads three different images in PictureBox on different events (fore example onMouseEnter, OnMouseLeave). As the images can have different sizes, I neet to resize the pictureBox and
the control itself. Below is provided the control's OnPaint event but this does not work.
protected override void OnPaint(PaintEventArgs pe)
{
if (pictureBox.Image != null)
{
this.Width = this.pictureBox.Image.Size.Width;
this.Height = this.pictureBox.Image.Size.Height;
CutRoundedRectangle2(pictureBox, cornerRadius);
}
else
{
Bitmap DrawArea = new Bitmap(pictureBox.Size.Width, pictureBox.Size.Height);
Graphics g = Graphics.FromImage(DrawArea);
Pen mypen = new Pen(Color.Black);
pictureBox.Image = DrawArea;
System.Drawing.Pen pen = new Pen(new SolidBrush(this.ForeColor));
g.DrawRectangle(pen, 0, 0, this.Width-1, this.Height-1);
g.Dispose();
}
this.labelText.ocation = new Point((this.pictureBox.Width - this.labelText.Width) / 2,
(this.pictureBox.Height - this.labelText.Height) / 2);
base.OnPaint(pe);
}
The pictureBox SizeMode is set in control's constuctor:
this.pictureBox.SizeMode = PictureBoxSizeMode.AutoSize;
It was long time ago when I worked with WinForms last time, but ...
My first thought is: have you tried set value of parent control's AutoSize property to 'true' and AutoSizeMode to GrowAndShrink and call parent control's Refresh() method when new image is loaded to picture box?
#Alexey, the pictureBox resize event helped!
private void pictureBox_Resize(object sender, EventArgs e)
{
this.Width = this.pictureBox.Image.Size.Width;
this.Height = this.pictureBox.Image.Size.Height;
}