我正在尝试创建类似于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对象传递到它下面的窗口。
有什么想法吗?或者更好的方法来解决这个问题?
感谢。
答案 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怎么办? :