拖动不透明表格?

时间:2013-01-08 17:22:19

标签: c# .net winforms

我有以下代码来拖动表单,并在拖动它时使其透明。问题是它闪烁,并没有拖延顺利。我在表格上有一张照片,不知道是不是这就是造成这种情况的原因。怎么能让它不闪烁。如果我删除了不透明度,那么它会被快速/平滑拖动。

[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);
}

1 个答案:

答案 0 :(得分:3)

Form和Control类有许多属性“很重”,需要在底层本机Windows窗口中进行大量更改。它们是与传递给本机CreateWindowEx()调用的样式标志关联的属性。 Opacity属性以及TransparencyKey属性就是这样,当您从默认值更改它们时,窗口需要另一个样式标志WS_EX_LAYERED。

这是一个问题,因为在创建窗口时指定了此样式标志。在使用SetWindowsLongPtr()创建窗口后,Windows有一些支持更改它们,但这一直是不稳定的。特别是对于WS_EX_LAYERED,当打开时会发生很多事情。它通过利用名为“layers”的视频适配器中的硬件功能来实现。层是视频存储器的单独块,其像素与主存储器组合。支持它的混音器提供不透明效果(乘法)和透明度键效果(省略)。

因此,在创建窗口后动态更改Opacity属性非常困难。以至于WPF完全禁止它。但Winforms没有,它需要处理Windows 98的限制。这也使得很难更改ShowInTaskbar,RightToLeft,FormBorderStyle等属性。它使用技巧来允许更改这些属性,它完全破坏了本机窗口并重新创建它,现在使用新的样式标志。

问题解决了,但这确实有明显的副作用。不可避免地,你看到的窗口消失了,新窗口被创建并绘制在同一个位置。这会引起你抱怨的闪烁。此外,破坏窗口会导致许多内部状态丢失。 Winforms尽力恢复该状态以及新窗口的状态,但“我当前正在移动”状态无法恢复。模态移动循环已经终止。

这个问题的解决方法很简单但很简单。将“属性”窗口中的“不透明度”属性设置为99%。并更改您的代码以将其恢复为99而不是100.现在样式位永远不必更改,因此您将不再获得这些工件。