Подтвердить что ты не робот

Как создать полупрозрачное окно в 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 в окнах, которые находятся ниже.

Любые идеи? Или лучшие способы решения этой проблемы?

Спасибо.

4b9b3361

Ответ 1

У меня была аналогичная проблема и нашел решение:

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

Ответ 2

То, что вы описали, похоже на ожидаемое поведение. Одним из решений является установка Fill на {x: Null} на пути, поскольку это единственный верный способ сделать объект не удачным.

Ответ 3

У меня другая идея.

Что делать, если вы сделали точно ОДИН ПИКСЕЛ, прямо под курсором мыши, полностью прозрачным? :]