如何在WPF中创建一个允许鼠标事件通过的半透明窗口

时间:2010-05-16 05:13:12

标签: wpf transparency

我正在尝试创建类似于Adobe Lightroom中的Lights out / lights dim功能(http://www.youtube.com/watch?v=87hNd3vaENE)的效果,但在WPF中除外。

我尝试的是在我现有窗口的顶部创建另一个窗口,使其透明并在其上放置半透明路径几何体。但我希望鼠标事件能够通过这个半透明窗口(在下面的窗口上)。

这是我所拥有的简化版本:

<Window x:Class="LightsOut.MaskWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    AllowsTransparency="True" 
    WindowStyle="None"
    ShowInTaskbar="False"
    Topmost="True" 
    Background="Transparent">

<Grid>

    <Button HorizontalAlignment="Left" Height="20" Width="60">click</Button>

    <Path IsHitTestVisible="False" Stroke="Black" Fill="Black" Opacity="0.3">

        <Path.Data>
            <RectangleGeometry Rect="0,0,1000,1000 "/>
        </Path.Data>
    </Path>             

</Grid>

窗口是完全透明的,因此在路径未覆盖的位置,鼠标事件会直接通过。到现在为止还挺好。路径对象上的IsHitTestvisible设置为false。因此鼠标事件将通过它传递到同一表单上的其他控件(即,您可以单击Button,因为它位于同一表单上)。

但鼠标事件不会通过Path对象传递到它下面的窗口。

有什么想法吗?或者更好的方法来解决这个问题?

感谢。

3 个答案:

答案 0 :(得分:58)

我遇到了类似的问题并找到了解决方案:

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

为您的窗口设置:

WindowStyle = None
Topmost = true
AllowsTransparency = true

在窗口后面的代码中添加:

protected override void OnSourceInitialized(EventArgs e)
{
  base.OnSourceInitialized(e);
  var hwnd = new WindowInteropHelper(this).Handle;
  WindowsServices.SetWindowExTransparent(hwnd);
}

和瞧 - 点击窗口!请参阅:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/a3cb7db6-5014-430f-a5c2-c9746b077d4f

中的原始答案

答案 1 :(得分:2)

您所描述的内容听起来像预期的行为。一种解决方案是在路径上将Fill设置为{x:Null},因为这是使对象不受测试的唯一可靠方法。

答案 2 :(得分:1)

我还有另一个想法。

如果您在鼠标光标下完全透明地制作了一个PIXEL怎么办? :