Winforms 使用透明密钥集删除Winform首次显示时的黑色闪烁

Winforms 使用透明密钥集删除Winform首次显示时的黑色闪烁,winforms,transparency,flicker,Winforms,Transparency,Flicker,下面的代码在窗体显示(透明)之前在屏幕上产生黑色闪烁,我想知道我的选项是什么来消除闪烁 Form f = new Form(); f.BackColor = Color.Lime; f.TransparencyKey = f.BackColor; f.StartPosition = FormStartPosition.Manual; f.Bounds = Screen.PrimaryScreen.WorkingArea; f.Show(); 如果我创建一个新

下面的代码在窗体显示(透明)之前在屏幕上产生黑色闪烁,我想知道我的选项是什么来消除闪烁

   Form f = new Form();
   f.BackColor = Color.Lime;
   f.TransparencyKey = f.BackColor;
   f.StartPosition = FormStartPosition.Manual;
   f.Bounds = Screen.PrimaryScreen.WorkingArea;
   f.Show();
如果我创建一个新项目,将窗体的背景设置为Lime,将透明键设置为Lime,然后单击“运行”,则会得到相同的结果

我尝试过的事情:

  • 将不透明度设置为99%——相同的闪烁

  • 强制在OnCreateParams中合成WS_EX_或使用SetWindowLong——相同的闪烁

  • 将窗口显示得更小,或宽度为0,或在屏幕外显示,然后移动到所需的位置--在窗体后面的窗口无法正确重画的情况下,会导致错误的显示问题

  • 设置ControlStyles.不透明、ControlStyles.UserPaint和其他几个ControlStyles组合并覆盖不同的绘制/背景绘制事件--各种结果,相同的闪烁、更差的闪烁或窗体不透明


  • 移动到WPF可能是一个选项,但不是真正寻找“使用WPF”作为答案。

    不透明度设置为0.01

    如果您需要表单(或其部分)可见,请在表单创建完成后重新设置不透明度:

    Form f = new Form { Opacity = 0.01 };
    f.Show();
    f.BeginInvoke( new Action(() => f.Opacity = 0.99 ));
    

    编辑:根据Tergiver的建议更新清洁剂

    不透明度设置为0.01

    如果您需要表单(或其部分)可见,请在表单创建完成后重新设置不透明度:

    Form f = new Form { Opacity = 0.01 };
    f.Show();
    f.BeginInvoke( new Action(() => f.Opacity = 0.99 ));
    

    编辑:按照Tergiver的建议更新了清洁器

    一毫秒的闪烁?或者它是一个长的,1.5秒的闪烁?毫秒,一点也不长。如果我在Visual Studio中设置了断点或某些事件的延迟,我可以看到窗体首先显示为黑色,然后在处理背景或绘制(取决于我修改的控件样式)后,它被绘制为石灰,然后,就在那之后,它是透明的。在没有增加延迟/断点的情况下,石灰到透明之间的切换是不可见的,但黑色到石灰部分是。。。我不知道为什么WinForms一开始就把它画成黑色,因为我根本没有设置为黑色的属性。一毫秒的闪烁?或者它是一个长的,1.5秒的闪烁?毫秒,一点也不长。如果我在Visual Studio中设置了断点或某些事件的延迟,我可以看到窗体首先显示为黑色,然后在处理背景或绘制(取决于我修改的控件样式)后,它被绘制为石灰,然后,就在那之后,它是透明的。在没有增加延迟/断点的情况下,石灰到透明之间的切换是不可见的,但黑色到石灰部分是。。。我不知道为什么WinForms一开始就把它画成黑色,因为我根本没有设置为黑色的属性。工作起来像个冠军,谢谢!在我的简单示例和更复杂的表单上工作。在这个简单的例子中,我不需要定时器,只需在所示的表单_中重置不透明度,但我确实需要定时器来处理更复杂的表单。。。现在,如果这样做有效的话,我甚至可以让我的表单淡入:)你根本不需要浪费计时器,只需使用BeginInvoke。您需要的是在当前消息分派完成后返回不透明度值。BeginInvoke使用PostMessage,因此代码将在当前发送完成后执行。工作起来像champ,谢谢!在我的简单示例和更复杂的表单上工作。在这个简单的例子中,我不需要定时器,只需在所示的表单_中重置不透明度,但我确实需要定时器来处理更复杂的表单。。。现在,如果这样做有效的话,我甚至可以让我的表单淡入:)你根本不需要浪费计时器,只需使用BeginInvoke。您需要的是在当前消息分派完成后返回不透明度值。BeginInvoke使用PostMessage,因此代码将在当前分派完成后执行。