问题
I'm drawing a panel on a bitmap in picturebox using C#. I used below code, which is fine when I don't minimize the Form. When I minimize the Form and again maximize it to the first size, all panels which were drawn by this class, show black background. I found that when I change ControlStyles.Opaque to something else such as "SupportsTransparentBackColor" the problem would be fixed but the panels would not be transparent anymore.
public class ExtendedPanel : Panel
{
private const int WS_EX_TRANSPARENT = 0x00;
public ExtendedPanel()
{
SetStyle(ControlStyles.Opaque, true);
}
private int opacity = 1;
[DefaultValue(1)]
public int Opacity
{
get
{
return this.opacity;
}
set
{
if (value < 0 || value > 100)
throw new ArgumentException("value must be between 0 and 100");
this.opacity = value;
}
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
return cp;
}
}
protected override void OnPaint(PaintEventArgs e)
{
using (var brush = new SolidBrush(Color.FromArgb(this.opacity * 1 / 100, this.BackColor)))
{
e.Graphics.FillRectangle(brush, this.ClientRectangle);
}
base.OnPaint(e);
}
}
回答1:
Reza Aghaei already told you what was actually preventing the Panel transparency to work at all:WS_EX_TRANSPARENT
was set to 0x00
instead of 0x20
.
Some suggestions to improve the appearace of the translucent Panel.
- Test the Panel setting these Styles:
This will prevent any artifact on the Panel when you're moving it both at Desing-Time and Run-Time.
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
this.DoubleBuffered = false;
this.UpdateStyles();
- When setting the opacity value:
Use Refresh()
if it's Desing-Time, this will update the new Opacity
visual immediately. Othrerwise, you'll have to click on the Form to see the changes. At Run-Time, Invalidate()
is enough (usually).
set {
if (value < 0 || value > 255) throw new ArgumentException("value must be between 0 and 255");
this.opacity = value;
if (this.DesignMode) this.FindForm().Refresh();
this.Invalidate();
}
Modified test class:
public class ExtendedPanel : Panel
{
private const int WS_EX_TRANSPARENT = 0x20;
public ExtendedPanel()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
this.DoubleBuffered = false;
this.UpdateStyles();
}
private int opacity = 1;
[DefaultValue(1)]
public int Opacity
{
get => this.opacity;
set {
if (value < 0 || value > 255) throw new ArgumentException("value must be between 0 and 255");
this.opacity = value;
if (this.DesignMode) this.FindForm().Refresh();
this.Invalidate();
}
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
return cp;
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (SolidBrush bgbrush = new SolidBrush(Color.FromArgb(this.opacity, this.BackColor)))
{
e.Graphics.FillRectangle(bgbrush, this.ClientRectangle);
}
}
}
来源:https://stackoverflow.com/questions/54158004/draw-transparent-panel-without-being-black-by-form-minimization