Как создать полупрозрачное окно в WPF, которое позволяет проходить событиям мыши
Я пытаюсь создать эффект, аналогичный функции Lights out /lights dim в Adobe Lightroom ( 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 для объекта пути. Таким образом, события мыши будут проходить через него к другим элементам управления в той же форме (т.е. вы можете нажать на кнопку, потому что она находится в той же форме).
Но события мыши не будут проходить через объект Path в окна, которые находятся под ним.
Есть идеи? Или лучшие способы решить эту проблему?
Благодарю.
3 ответа
У меня была похожая проблема, и я нашел решение:
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
То, что вы описали, звучит как ожидаемое поведение. Одно из решений состоит в том, чтобы установить для параметра Fill значение {x:Null} на пути, поскольку это единственный надежный способ сделать объект не проверенным на попадание.
У меня есть другая идея.
Что если вы сделали ровно ОДИН ПИКСЕЛ прямо под курсором мыши полностью прозрачным?:]