2010-05-16 10 views
31

Sto tentando di creare un effetto simile alla funzione di attenuazione luci/luci in Adobe Lightroom (http://www.youtube.com/watch?v=87hNd3vaENE) tranne in WPF.Come creare una finestra semitrasparente in WPF che consente il passaggio degli eventi del mouse tramite

Quello che ho provato è stato creare un'altra finestra sopra la mia finestra esistente, renderla trasparente e mettere su di essa una geometria Path semitrasparente. Ma voglio che gli eventi del mouse siano in grado di passare attraverso questa finestra semitrasparente (fino alle finestre sottostanti).

Questa è una versione semplificata di quello che ho:

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

La finestra è completamente trasparente, in modo da sui luoghi in cui il percorso non copre, eventi del mouse passano proprio attraverso. Fin qui tutto bene. IsHitTestvisible è impostato su false sull'oggetto path. Quindi gli eventi del mouse passeranno attraverso di esso ad altri controlli sullo stesso modulo (cioè puoi fare clic sul pulsante, perché è sullo stesso modulo).

Ma gli eventi del mouse non passano attraverso l'oggetto Path su finestre che si trovano al di sotto di esso.

Qualche idea? O modi migliori per risolvere questo problema?

Grazie.

risposta

52

Ho avuto simile problema e trovato una soluzione:

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

per la finestra set:

WindowStyle = None 
Topmost = true 
AllowsTransparency = true 

in codice dietro la finestra per l'aggiunta:

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

e voila - finestra click-through! Vedere la risposta originale in: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/a3cb7db6-5014-430f-a5c2-c9746b077d4f

+2

Grazie, questo è esattamente quello che stavo cercando. – RMK

+0

questo è fantastico, vorrei solo realizzare un'altra cosa: nascondere il cursore. fondamentalmente impostando il cursore su Nessuno, ma con questo codice COOOOL in posizione il cursore cambia in base a ciò che si trova al di sotto della finestra. C'è un modo per far cadere i clic attraverso la nostra finestra E non avere il cursore visibile? –

+0

funziona perfettamente! Sono stato in grado di utilizzare il metodo "click through" sulla finestra WPF nell'applicazione WinForms. – Alex

2

Quello che hai descritto sembra il comportamento previsto. Una soluzione è impostare Fill su {x: Null} sul Path poiché questo è l'unico modo sicuro per fare in modo che un oggetto non colpisca il test.

0

Ho una buona idea.

E se faceste esattamente UNO PIXEL, proprio sotto il cursore del mouse, completamente trasparente? :]

Problemi correlati