C# 使用alpha覆盖组件,当其下的控件重绘时重绘
我创建了一个自定义控件,我想用它在表单的一部分上按需覆盖状态信息。根据信息的类型,它应该显示文本并具有背景色。这是仍然不完整的代码C# 使用alpha覆盖组件,当其下的控件重绘时重绘,c#,.net,winforms,alpha,C#,.net,Winforms,Alpha,我创建了一个自定义控件,我想用它在表单的一部分上按需覆盖状态信息。根据信息的类型,它应该显示文本并具有背景色。这是仍然不完整的代码 public partial class StatusPanel : UserControl { public enum PanelStyle { Info, Warning, Error } public PanelStyle Style { get; set; } pub
public partial class StatusPanel : UserControl
{
public enum PanelStyle
{
Info,
Warning,
Error
}
public PanelStyle Style { get; set; }
public StatusPanel()
{
InitializeComponent();
this.imgGreen = new Bitmap(256, 256, PixelFormat.Format32bppArgb);
using(Graphics g = Graphics.FromImage(this.imgGreen))
{
g.Clear(Color.Transparent);
Brush bg = new SolidBrush(Color.FromArgb(200, Color.Green));
g.FillRectangle(bg, 0, 0, 256, 256);
}
this.imgYellow = new Bitmap(256, 256, PixelFormat.Format32bppArgb);
using(Graphics g = Graphics.FromImage(this.imgYellow))
{
g.Clear(Color.Transparent);
Brush bg = new SolidBrush(Color.FromArgb(10, Color.Yellow));
g.FillRectangle(bg, 0, 0, 256, 256);
}
}
protected readonly Font font = new Font("Arial", 12.0F);
protected readonly Brush textBrush = new SolidBrush(Color.Black);
protected readonly Image imgGreen;
protected readonly Image imgYellow;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
return cp;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
// do not draw background
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
Image img = GetImage();
e.Graphics.DrawImage(img, 0, 0, this.Width, this.Height);
e.Graphics.DrawString("ABC", this.font, this.textBrush, 1.0F, 1.0F);
}
protected Image GetImage()
{
return (this.Style == PanelStyle.Info) ? this.imgGreen : this.imgYellow;
}
}
这个很好用。但是,当我在窗体上放置一些按钮,并且其中一个控件位于这些按钮前面时,当鼠标移动到按钮上时,这些按钮将“过度绘制”,高亮效果将重新绘制它们
如何通知我的组件它需要重新绘制,因为基础控件已重新绘制?向
Parent.control
下的所有控件注册绘制处理程序,并为注册绘制处理程序的Parent.ControlAdded
注册处理程序
大概是这样的:
private void myDummyUserControl_Load(object sender, EventArgs e)
{
var uc = (DummyUserControl)sender;
uc.Parent.ControlAdded += new ControlEventHandler(Parent_ControlAdded);
foreach (Control c in uc.Parent.Controls)
{
if (uc == c)
continue;
c.Paint += new PaintEventHandler(c_Paint);
}
}
void c_Paint(object sender, PaintEventArgs e)
{
//checks & paint stuff here
}
void Parent_ControlAdded(object sender, ControlEventArgs e)
{
e.Control.Paint += new PaintEventHandler(c_Paint);
}
//编辑
不确定是否需要使用递归来遍历子控件树,是否也需要在这些子控件上添加处理程序 向
Parent.Control
下的所有控件注册一个绘制处理程序,并为注册绘制处理程序的Parent.ControlAdded
注册一个处理程序
大概是这样的:
private void myDummyUserControl_Load(object sender, EventArgs e)
{
var uc = (DummyUserControl)sender;
uc.Parent.ControlAdded += new ControlEventHandler(Parent_ControlAdded);
foreach (Control c in uc.Parent.Controls)
{
if (uc == c)
continue;
c.Paint += new PaintEventHandler(c_Paint);
}
}
void c_Paint(object sender, PaintEventArgs e)
{
//checks & paint stuff here
}
void Parent_ControlAdded(object sender, ControlEventArgs e)
{
e.Control.Paint += new PaintEventHandler(c_Paint);
}
//编辑
不确定是否需要使用递归来遍历子控件树,是否也需要在这些子控件上添加处理程序 你的意思是说,当所有其他组件被绘制时,告诉我的状态面板重新绘制?可能需要手动检查组件边界是否重叠?基本上是的。当然,您可以通过注册EventHandler进行重新定位或调整大小,并基于重叠检查注册或取消注册绘制处理程序,使这一点变得更复杂boundaries@DarkSquirrel42好的,当我在其他控件的绘制事件中使我的控件无效时,如果它们相交,这会有所帮助。还有一点闪烁效应。有没有办法在这种情况下使用双缓冲?@Zool抱歉,我从未在.net环境中使用过双缓冲,但为了减少不必要的影响,您可以尝试只重新绘制需要重新绘制的区域。。。请参见PaintEventArgs和GraphicsProperties@DarkSquirrel42问题是我既不知道绘制其他控件的逻辑,也不想。想象一个普通的Winforms.按钮在我的控制下。在它的绘制事件中,我现在检查它是否在我的控制下,如果在我的控制下,我的控件将失效以重新绘制。但我无法阻止按钮自行绘制。事实上,这是必要的,因为我需要一个完整的按钮来正确绘制alpha控件。因此,目前我还不知道如何最大限度地减少这种影响。目前的解决方案可能已经足够好了。否则,我将在将来添加一个新问题。到目前为止非常感谢。那么你的意思是说,当所有其他组件上漆时,告诉我的状态面板重新上漆?可能需要手动检查组件边界是否重叠?基本上是的。当然,您可以通过注册EventHandler进行重新定位或调整大小,并基于重叠检查注册或取消注册绘制处理程序,使这一点变得更复杂boundaries@DarkSquirrel42好的,当我在其他控件的绘制事件中使我的控件无效时,如果它们相交,这会有所帮助。还有一点闪烁效应。有没有办法在这种情况下使用双缓冲?@Zool抱歉,我从未在.net环境中使用过双缓冲,但为了减少不必要的影响,您可以尝试只重新绘制需要重新绘制的区域。。。请参见PaintEventArgs和GraphicsProperties@DarkSquirrel42问题是我既不知道绘制其他控件的逻辑,也不想。想象一个普通的Winforms.按钮在我的控制下。在它的绘制事件中,我现在检查它是否在我的控制下,如果在我的控制下,我的控件将失效以重新绘制。但我无法阻止按钮自行绘制。事实上,这是必要的,因为我需要一个完整的按钮来正确绘制alpha控件。因此,目前我还不知道如何最大限度地减少这种影响。目前的解决方案可能已经足够好了。否则,我将在将来添加一个新问题。谢谢你。