2010-05-16 11 views
31

Próbuję stworzyć efekt podobny do funkcji przyciemniania świateł/świateł w programie Adobe Lightroom (http://www.youtube.com/watch?v=87hNd3vaENE) z wyjątkiem WPF.Tworzenie półprzezroczystego okna w WPF, które pozwala przejść przez zdarzenia myszy

Próbowałem utworzyć kolejne okno z mojego istniejącego okna, uczynić je przezroczystym i umieścić na nim półprzezroczystą geometrię ścieżki. Ale chcę, aby zdarzenia myszy były w stanie przejść przez to półprzezroczyste okno (do okien 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 całkowicie przezroczysty, więc w miejscach, gdzie ścieżka nie obejmuje zdarzenia myszy przechodzą na wylot. Jak na razie dobrze. IsHitTestvisible jest ustawione na false na obiekcie ścieżki. Więc zdarzenia myszy przejdą przez to do innych kontrolek w tej samej formie (np. Możesz kliknąć przycisk, ponieważ jest on w tej samej formie).

Jednak zdarzenia myszy nie będą przechodzić przez obiekt Path do okien znajdujących się pod nim.

Wszelkie pomysły? Lub lepsze sposoby rozwiązania tego problemu?

Dzięki.

Odpowiedz

52

miałem podobny problem i znalazł 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); 
    } 
} 

do zestawu okno:

WindowStyle = None 
Topmost = true 
AllowsTransparency = true 

w kodzie tyłu za dodanie okna:

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

i voila - okno po kliknięciu! Zobacz oryginalną odpowiedź: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/a3cb7db6-5014-430f-a5c2-c9746b077d4f

+2

Dzięki temu właśnie tego szukałem. – RMK

+0

To jest niesamowite, chciałbym osiągnąć jeszcze jedną rzecz: ukrywanie kursora. zasadniczo ustawienie kursora na None, ale z tym kodem COOOOL w miejscu kursor zmienia się w zależności od tego, co znajduje się pod oknem. Czy istnieje sposób, aby kliknięcia spadały przez nasze okno ORAZ nie wyświetlały się kursora? –

+0

działa idealnie! Byłem w stanie użyć metody "click through" w oknie WPF w aplikacji WinForm. – Alex

2

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 na sprawdzenie, czy obiekt nie został trafiony.

0

Mam inny pomysł.

Co jeśli zrobiłeś dokładnie JEDEN PIKSEL, tuż pod kursorem myszy, całkowicie przezroczysty? :]

Powiązane problemy