如何在WPF中使窗口对鼠标事件不可见?

5

我创建了这个类,它完美地使我的WPF应用程序对鼠标事件透明。

using System.Runtime.InteropServices;

class Win32

{
    public const int WS_EX_TRANSPARENT = 0x00000020;
    public const int GWL_EXSTYLE = (-20);

    [DllImport("user32.dll")]
    public static extern int GetWindowLong(IntPtr hwnd, int index);

    [DllImport("user32.dll")]
    public static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

    public static void makeTransparent(IntPtr hwnd)
    {
        // Change the extended window style to include WS_EX_TRANSPARENT
        int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
        Win32.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);    
    }

    public static void makeNormal(IntPtr hwnd)
    {
      //how back to normal what is the code ?

    }

}

我运行这个代码来忽略鼠标事件,但执行完之后,我希望应用程序能够恢复正常并再次处理鼠标事件。该怎么做?
IntPtr hwnd = new WindowInteropHelper(this).Handle;
Win32.makeTransparent(hwnd);

如何编写代码使应用程序恢复正常?

3个回答

7
你现有的类中以下代码获取现有窗口样式(GetWindowLong),并将WS_EX_TRANSPARENT样式标志添加到这些现有的窗口样式中:
// Change the extended window style to include WS_EX_TRANSPARENT
int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
Win32.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);

当您想将其恢复到正常行为时,需要从窗口样式中移除您添加的WS_EX_TRANSPARENT标志。这可以通过执行按位AND NOT操作来完成(与您执行的OR操作形成对比,用于添加标志)。绝对没有必要像deltreme's answer建议的那样记住先前检索到的扩展样式,因为您只想清除WS_EX_TRANSPARENT标志。

代码如下:

public static void makeNormal(IntPtr hwnd)
{
    //Remove the WS_EX_TRANSPARENT flag from the extended window style
    int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
    Win32.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle & ~WS_EX_TRANSPARENT);
}

感谢所有的回复和支持,但是......运算符“!”不能应用于类型为“int”的操作数。 - Larsen187
@Larsen187:抱歉,是我的错误。我已经更新了代码。现在应该可以工作了。你需要一个~,而不是一个!——它们在键盘上太接近了。 - Cody Gray

1

你尝试过使用这个吗?(这等同于窗口)

this.IsHitTestVisible = false;

我不确定你所说的“不起作用”是什么意思。如果您在表单上有一个按钮,但无法单击它,请将其设置为true,这样鼠标事件就会重新开始工作。 - John Petrak
我认为他的意思是,发生在窗体上的鼠标事件(如单击)会传递到它下面的任何东西。他不仅想禁用点击,而且希望使窗口对这些事件“透明”,就像它不存在一样。 - Cody Gray

1

这段代码获取当前窗口的样式:

int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE); 

这段代码在extendedStyle上设置了WS_EX_TRANSPARENT标志:
Win32.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);

你所需要做的就是记住从 GetWindowLong() 得到的 extendedStyle,然后再次使用原始值调用 SetWindowLong()

2
没有必要记住 extendedStyle。您只需检索当前值并从中删除 WS_EX_TRANSPARENT 标志即可。有关更多详细信息,请参见我的答案 - Cody Gray
@Cody Gray:同意,那是一个更优雅的解决方案。 - C.Evenhuis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接