经过一番挖掘,我找到了答案。它结合了我在问题中 #4 和 #5 中描述的内容,但必须以不同的方式进行。我读到 WPF 控件没有窗口句柄,因为 wpf 控件不是像 winforms 控件那样的窗口。这并不完全正确。 WPF 控件确实有窗口句柄。
代码
从this answer 复制的WindowsServices 类,带有一个额外的方法来删除透明度:
public static class WindowsServices
{
const int WS_EX_TRANSPARENT = 0x00000020;
const int GWL_EXSTYLE = (-20);
[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
public static void SetWindowExTransparent(IntPtr hwnd)
{
var extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);
}
public static void SetWindowExNotTransparent(IntPtr hwnd)
{
var extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle & ~WS_EX_TRANSPARENT);
}
}
*注意:此上下文中的透明度是指窗口对鼠标输入是透明的,而不是视觉上透明的。您仍然可以看到在窗口上呈现的任何内容,但鼠标点击将发送到它后面的任何窗口。
窗口 xaml:
<Window x:Class="TransClickThrough.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800"
Topmost="True"
WindowStyle="None"
AllowsTransparency="True"
Background="{x:Null}">
<Grid>
<Button x:Name="button1" Content="Button" HorizontalAlignment="Left" Margin="183,136,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>
-
Topmost="True" 导致此窗口始终绘制在顶部,即使
当其他窗口有焦点时。
-
WindowStyle="None" 删除
窗口标题栏和边框AllowsTransparency="True" 做什么
顾名思义,它允许窗口是透明的。
-
Background="{x:Null}" 使其透明。你也可以设置
到具有 0 Opacity 的 SolidColorBrush。无论哪种方式都有效。
窗口代码隐藏:
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// Make entire window and everything in it "transparent" to the Mouse
var windowHwnd = new WindowInteropHelper(this).Handle;
WindowsServices.SetWindowExTransparent(windowHwnd);
// Make the button "visible" to the Mouse
var buttonHwndSource = (HwndSource)HwndSource.FromVisual(btn);
var buttonHwnd = buttonHwndSource.Handle;
WindowsServices.SetWindowExNotTransparent(buttonHwnd);
}