2010-12-28 8 views
5

Ho un'utilità di cattura dello schermo su cui posso eludere un'area sul desktop. Ho fatto questo è un modo abbastanza semplice, ho una forma che è la stessa dimensione dello schermo su cui disegno uno screenshot del desktop trasformato in scala di grigi. Quando l'utente tiene premuto il tasto sinistro del mouse, lui/lei può selezionare un'area sul modulo. Il rettangolo che l'utente disegna è riempito con TransparentColor. Una volta che l'utente solleva il mouse, il rettangolo trasparente viene lasciato in posizione e il desktop effettivo è visibile. Ecco il mio problema: Sul mio PC di sviluppo posso effettivamente fare clic attraverso questo rettangolo trasparente e navigare ecc. Mentre sul mio altro PC il modulo risponde al clic del mouse sul rettangolo trasparente effettivo.Click-through al desktop su un modulo trasparente

Sto usando .NET 4.0 in C#, qualche idea su come posso effettivamente fare clic sul desktop in tutti i casi ??

Grazie e molto apprezzato :)

risposta

7

sono riuscito a trovare una soluzione adeguata a questo problema dopo aver guardato molto profondamente in questo. Si scopre che con le giuste chiamate API Win32 è possibile impostare un modulo "Invisibile" ai clic del mouse. Ciò può essere ottenuto da:

[DllImport("user32.dll", SetLastError = true)] 
static extern int GetWindowLong(IntPtr hWnd, int nIndex); 

[DllImport("user32.dll")] 
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); 

[DllImport("user32.dll")] 
static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags); 

public void SetFormTransparent(IntPtr Handle) { 
    oldWindowLong = GetWindowLong(Handle, GWL_EXSTYLE); 
    SetWindowLong(Handle, GWL_EXSTYLE, Convert.ToInt32(oldWindowLong | WS_EX_LAYERED | WS_EX_TRANSPARENT)); 
} 

public void SetFormNormal(IntPtr Handle) { 
    SetWindowLong(Handle, GWL_EXSTYLE, Convert.ToInt32(oldWindowLong | WS_EX_LAYERED)); 
} 

Ma c'è un trucco per tutto. Devi fare attenzione che tutti i clic fatti sul forum cadano attraverso il modulo e vengano inviati a qualsiasi cosa sotto il modulo. Per garantire che se clicco sul mio modulo, ad es. su un pulsante e voglio che il tasto su cui ho fatto clic ho fatto un semplice trucco. Ho un timer in background che esegue ogni N millisecondi e analizza la posizione del Cursore. Se è sopra l'area che voglio che sia, imposterà il Form su Normal tramite SetFormNormal() altrimenti sarà trasparente.

Spero che questo bit di codice sia d'aiuto e la gente lo userà.

+0

Invece di utilizzare un timer, perché non sfruttare gli eventi OnMouseEnter/OnMouseDown per ogni controllo nel modulo? – Jason

+6

Si prega di aggiungere i valori mancanti per le costanti. –

+0

Ecco alcuni link utili: http://stackoverflow.com/questions/1524035/topmost-form-clicking-through-possible, http://pinvoke.net/default.aspx/Constants.GWL%20-%20GetWindowLong, http://pinvoke.net/default.aspx/Constants.Window%20styles – Xantix