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

发布于 2024-09-01 16:14:15 字数 1171 浏览 4 评论 0原文

我正在尝试创建类似于 Adobe Lightroom WPF 中除外。

我尝试的是在现有窗口之上创建另一个窗口,使其透明并在其上放置半透明的 Path 几何图形。但我希望鼠标事件能够穿过这个半透明窗口(到下面的窗口)。

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

<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>

窗口是完全透明的,因此在 Path 未覆盖的地方,鼠标事件会直接通过。到目前为止,一切都很好。路径对象上的 IsHitTestvisible 设置为 False。因此,鼠标事件将通过它传递到同一窗体上的其他控件(即您可以单击 Button,因为它位于同一窗体上)。

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

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

I am trying to create an effect similar to the Lights out /lights dim feature in Adobe Lightroom except in WPF.

What I tried was to create another window over-top of my existing window, make it transparent and put a semi-transparent Path geometry on it. But I want mouse events to be able to pass through this semi-transparent window (on to the windows below).

This is a simplified version of what I have:

<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>

The window is fully transparent, so on places where the Path doesn't cover, mouse events pass right through. So far so good. The IsHitTestvisible is set to False on the path object. So, mouse events will pass through it to other controls on the same form (i.e. you can click on the Button, because it is on the same form).

But mouse events won't pass through the Path object onto windows that are below it.

Any ideas? Or better ways to solve this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

月野兔 2024-09-08 16:14:15

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

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

I've had similar problem and found a solution:

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

for your window set:

WindowStyle = None
Topmost = true
AllowsTransparency = true

in code behind for the window add:

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

and voila - click-through window! See original answer in: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/a3cb7db6-5014-430f-a5c2-c9746b077d4f

不寐倦长更 2024-09-08 16:14:15

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

What you described sounds like the expected behavior. One solution is to set the Fill to {x:Null} on the Path as that is the only sure way to make an object not hit test.

楠木可依 2024-09-08 16:14:15

我有另一个想法。

如果您在鼠标光标正下方制作一个完全透明的像素,会怎么样? :]

I haveanother idea.

What if you made exactly ONE PIXEL, right under the mouse cursor, completely transparent? :]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文