C# 如何设置所有者绘制控件的初始颜色 脚本
具有Windows窗体C# 如何设置所有者绘制控件的初始颜色 脚本,c#,.net,winforms,C#,.net,Winforms,具有Windows窗体窗体派生窗体,其中包含面板派生控件: 表单将获得黑色背景颜色集: public MyForm() { InitializeComponent(); base.BackColor = Color.Black; } 并且面板控制被配置为双缓冲等,如所述,并且: 实际绘图是在MyPanel中的这些覆盖内完成的: protected override void OnPaintBackground(PaintEventArgs e) { e.Graphi
窗体
派生窗体,其中包含面板
派生控件:
表单将获得黑色背景颜色集:
public MyForm()
{
InitializeComponent();
base.BackColor = Color.Black;
}
并且面板控制被配置为双缓冲等,如所述,并且:
实际绘图是在MyPanel
中的这些覆盖内完成的:
protected override void OnPaintBackground(PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);
}
错误行为
偶尔,当表单最初显示时,在实际调用我自己的绘图代码之前,我的所有者绘制的面板很快被绘制为白色:
调用我的绘图代码后,所有内容都正确绘制,我再也无法复制白色背景:
即使调整窗口和面板的大小也不会使其闪烁为白色
实施错误行为
如果我在窗体的事件处理程序中设置睡眠,我可以强制执行面板的初始白色绘制:
private void MyForm_Shown(object sender, EventArgs e)
{
Thread.Sleep(1000);
}
在调用我的所有者绘制的油漆代码之前,面板以白色显示1000毫秒
我的问题
在拥有所有者绘制/自定义绘制的面板时,如何避免初始白色显示
我的目标是让控件从一开始就“知道”其初始背景色(在我的示例中为黑色),而不是在最初显示之后
一些想法
我尝试过玩各种各样的东西,包括游戏,但没有明显的成功
我最初的想法是提供一些,但在深入研究之后,我仍然不知道这是否可行,是否会有所帮助
全部代码
为了安全起见,以下是我的全部代码
MyForm.cs:
public partial class MyForm : Form
{
public MyForm()
{
InitializeComponent();
base.BackColor = Color.Black;
}
private void MyForm_Shown(object sender, EventArgs e)
{
Thread.Sleep(1000);
}
}
MyPanel.cs:
public class MyPanel : Panel
{
public MyPanel()
{
base.DoubleBuffered = true;
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
UpdateStyles();
}
protected override void OnPaintBackground(PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);
}
}
问题在于表单的背景,而不是面板的背景。窗体将在面板所在的位置有一个剪辑区域,直到它知道面板将自己绘制,因此最初不会绘制黑色。这是在windows窗体框架代码中完成的。能否将相同的样式应用于面板的父窗体?复制此样式的唯一方法是使父窗体消息队列保持忙碌。插入线程睡眠(1000)显示的事件中的code>将阻止在窗体上立即绘制任何控件,在窗体休眠时将其剪切区域保留为白色。例如,您可以将面板的可见性设置为false
,并将其重新设置为true
,作为显示的事件中的最后一行。我不确定为什么它看起来是白色的。可能这只是内部容器中缺少颜色或VisualStyleRenderer操作的结果Form.OnPaint
调用base.OnPaint()
,其中base是ContainerControl
,它调用ScrollableControl
,它调用Control
,而这不是公共对象。也许Hans知道背后的原因。评论“如果你不想要默认的Windows行为,你必须将event.Handled
设置为true”很有趣,但显然为时已晚。另一个很有希望的方法是遵循文档中的100%透明形式,它可以避免大部分背景绘制,如果幸运的话,默认情况下也可以使用白色(因为透明并不意味着不能在onpaintbackground中绘制不透明矩形)如果将allpaintingwmpaint
设置为false
它将以黑色开始。我不确定这是否会破坏您的双缓冲目标,但您可以尝试一下,或许可以在重写的WndProc()
中显式忽略WM_ERASEBKGND(第一个除外)。否则,我怀疑注册一个新类是一种方法,覆盖默认的背景颜色,否则就是“控制”。正如您所指出的,这是可行的,但相当痛苦()。
public class MyPanel : Panel
{
public MyPanel()
{
base.DoubleBuffered = true;
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
UpdateStyles();
}
protected override void OnPaintBackground(PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);
}
}