Jak utworzyć półprzezroczyste okno w WPF, które umożliwia przechodzenie zdarzeń myszy

Próbuję stworzyć efekt podobny do funkcji Lights out /lights dim w Adobe Lightroom ( http://www.youtube.com/watch?v=87hNd3vaENE ) z wyjątkiem WPF.

Próbowałem stworzyć kolejne okno nad istniejącym oknem, uczynić je przezroczystymi i umieścić na nim półprzezroczystą geometrię ścieżki. Ale chcę, aby zdarzenia myszy mogły przejść przez to półprzezroczyste okno(na okna poniżej).

Jest to uproszczona wersja tego, co mam:

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

Okno jest w pełni przezroczyste, więc w miejscach, gdzie ścieżka nie obejmuje, zdarzenia myszy przechodzą bezpośrednio przez. Jak na razie dobrze. IsHitTestvisible jest ustawiony na false w obiekcie path. Tak więc zdarzenia myszy przechodzą przez niego do innych kontrolek na tym samym formularzu (czyli można kliknąć na przycisk, ponieważ jest on na tym samym formularzu).

Ale zdarzenia myszy nie przechodzą przez obiekt Path do okien znajdujących się pod nim.

Jakieś pomysły? Lub lepsze sposoby rozwiązania ten problem? Dzięki.
Author: RMK, 2010-05-16

3 answers

Miałem podobny problem i znalazłem rozwiązanie:

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

Dla Twojego zestawu okien:

WindowStyle = None
Topmost = true
AllowsTransparency = true

W kodzie za oknem dodaj:

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

I voila-Kliknij-przez okno! Zobacz oryginalną odpowiedź w: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/a3cb7db6-5014-430f-a5c2-c9746b077d4f

 53
Author: Bazurbat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-01 15:06:55

To, co opisałeś, brzmi jak oczekiwane zachowanie. Jednym z rozwiązań jest ustawienie wypełnienia na {x: Null} na ścieżce, ponieważ jest to jedyny pewny sposób, aby obiekt nie trafił w test.

 2
Author: Steven,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-12 04:50:19

Mam inny pomysł.

A gdyby zrobić dokładnie jeden piksel, tuż pod kursorem myszy, całkowicie przezroczysty? :]

 0
Author: AgentFire,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-28 01:26:50