拖动不透明窗体
本文关键字:窗体 不透明 拖动 | 更新日期: 2023-09-27 17:51:04
我有下面的代码来拖动窗体,并使其在拖动时透明。问题是,它闪烁,并不是拖动平滑。我在表格上有一张照片,不确定这是不是导致这个的原因。我怎样才能让它不闪烁。如果我去掉不透明度,它就会被快速/平滑地拖动。
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam,
int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
public void Drag(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Opacity = 0.9;
ReleaseCapture();
SendMessage(Handle, 0xA1, 0x2, 0);
this.Opacity = 1;
}
}
private void Body_MouseDown(object sender, MouseEventArgs e)
{
Drag(e);
}
Form和Control类的许多属性都很"重",需要在底层的本机Windows窗口中进行大量更改。它们是与传递给本机CreateWindowEx()调用的样式标志相关联的属性。不透明度属性,以及透明键属性是这样的,当你从默认值改变它们时,窗口需要另一个样式标志,WS_EX_LAYERED。
这是一个问题,因为这个样式标志是在创建窗口时指定的。Windows支持在使用SetWindowsLongPtr()创建窗口后更改它们,但这总是不稳定的。特别是对于WS_EX_LAYERED,当它被打开时,很多东西在底层发生。它是通过利用视频适配器中称为"层"的硬件特性实现的。层是一个独立的显存块,它的像素与主存结合在一起。支持提供不透明度效果(multiply)和透明度键效果(省略)的混频器。因此,在创建窗口后,动态更改不透明度属性是相当困难的。以至于WPF完全禁止它。但Winforms没有,它需要解决Windows 98的限制。这也使得像ShowInTaskbar, righttolleft, FormBorderStyle这样的属性很难改变。它使用技巧来允许更改这些属性,它完全破坏本机窗口并重新创建它,现在使用新的样式标志。
问题解决了,但是这有明显的副作用。不可避免地,你看到的窗口消失了,新的窗口被创建并画在同一个位置。这会导致你抱怨的闪烁。此外,破坏窗口会导致大量内部状态丢失。Winforms尽其所能恢复新窗口的状态,但是无法恢复"我当前正在移动"的状态。模态移动循环已经终止。
这个问题的解决方法很粗糙但很简单。在属性窗口中设置不透明度为99%。并更改代码将其恢复为99而不是100。现在,样式位再也不需要更改了,所以您再也不会得到这些工件了。