2009-10-06 10 views
9

Gracias por las respuestas anteriores que me permitieron completar la herramienta básica que muestra una gran cruz roja en las coordenadas del mouse para que sea más visible. La cruz roja es una imagen con fondo transparente en forma transparente. El problema es que no puede hacer clic, ya que su parte superior y el centro de la forma están realmente posicionados con el mouse xy. ¿Hay alguna manera de hacer que esto se pueda utilizar para que la cruz aún se muestre en el cursor pero se pueda "hacer clic"?¿Forma superior, haciendo clic en "a través" posible?

Respuesta

8

Puede utilizar SetWindowLong para establecer el estilo de ventana WS_EX_TRANSPARENT:

Si la ventana de capas tiene el estilo de ventana WS_EX_TRANSPARENT extendida, la forma de la ventana por capas tendrá en cuenta y los eventos de ratón se pasará a la otras ventanas debajo de la ventana en capas.

CodeProject tiene this artículo que detalla la técnica. Aunque está en VB.NET, debería ser fácil convertirlo a C#.

He utilizado el siguiente código en el pasado:

public enum GWL 
{ 
    ExStyle = -20 
} 

public enum WS_EX 
{ 
    Transparent = 0x20, 
    Layered = 0x80000 
} 

public enum LWA 
{ 
    ColorKey = 0x1, 
    Alpha = 0x2 
} 

[DllImport("user32.dll", EntryPoint = "GetWindowLong")] 
public static extern int GetWindowLong(IntPtr hWnd, GWL nIndex); 

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

[DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")] 
public static extern bool SetLayeredWindowAttributes(IntPtr hWnd, int crKey, byte alpha, LWA dwFlags); 

protected override void OnShown(EventArgs e) 
{ 
    base.OnShown(e); 
    int wl = GetWindowLong(this.Handle, GWL.ExStyle); 
    wl = wl | 0x80000 | 0x20; 
    SetWindowLong(this.Handle, GWL.ExStyle, wl); 
    SetLayeredWindowAttributes(this.Handle, 0, 128, LWA.Alpha); 
} 

pero también fue copiado de otro lugar. Las líneas importantes aquí están en el método OnShown. Aunque tengo que admitir que la línea

wl = wl | 0x80000 | 0x20; 

es un poco críptico, estableciendo el WS_EX_LAYERED y estilos WS_EX_TRANSPARENT extendida.

Puede probablemente también configurarlo como

wl = wl | WS_EX.Layered | WS_EX.Transparent; 
+0

¿Podría proporcionarme un poco más detalles? No tengo experiencia en esta API de bajo nivel, ¡gracias! – Petr

+0

Muchas gracias, este es un lugar realmente increíble, tales respuestas rápidas. – Petr

+0

Con SetLayeredWindowAttributes, la transparencia, establecida anteriormente en VS Designer, se pierde y el formulario es semitransparente. ¡Pero deshabilitar esta línea no afecta los efectos de "clic", funciona muy bien! – Petr

0

Para proporcionar una versión más detallada/comentado, que también utiliza TransparencyKey como clave de la transparencia (no negro como la versión anterior), y uno puede establecer _alpha según se desee .

 /// <summary> 
     /// 0: the window is completely transparent ... 255: the window is opaque 
     /// </summary> 
     private byte _alpha; 

     private enum GetWindowLong 
     { 
      /// <summary> 
      /// Sets a new extended window style. 
      /// </summary> 
      GWL_EXSTYLE = -20 
     } 

     private enum ExtendedWindowStyles 
     { 
      /// <summary> 
      /// Transparent window. 
      /// </summary> 
      WS_EX_TRANSPARENT = 0x20, 
      /// <summary> 
      /// Layered window. http://msdn.microsoft.com/en-us/library/windows/desktop/ms632599%28v=vs.85%29.aspx#layered 
      /// </summary> 
      WS_EX_LAYERED = 0x80000 
     } 

     private enum LayeredWindowAttributes 
     { 
      /// <summary> 
      /// Use bAlpha to determine the opacity of the layered window. 
      /// </summary> 
      LWA_COLORKEY = 0x1, 
      /// <summary> 
      /// Use crKey as the transparency color. 
      /// </summary> 
      LWA_ALPHA = 0x2 
     } 

     [DllImport("user32.dll", EntryPoint = "GetWindowLong")] 
     private static extern int User32_GetWindowLong(IntPtr hWnd, GetWindowLong nIndex); 

     [DllImport("user32.dll", EntryPoint = "SetWindowLong")] 
     private static extern int User32_SetWindowLong(IntPtr hWnd, GetWindowLong nIndex, int dwNewLong); 

     [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")] 
     private static extern bool User32_SetLayeredWindowAttributes(IntPtr hWnd, int crKey, byte bAlpha, LayeredWindowAttributes dwFlags); 

     protected override void OnShown(EventArgs e) 
     { 
      base.OnShown(e); 
      //Click through 
      int wl = User32_GetWindowLong(this.Handle, GetWindowLong.GWL_EXSTYLE); 
      User32_SetWindowLong(this.Handle, GetWindowLong.GWL_EXSTYLE, wl | (int)ExtendedWindowStyles.WS_EX_LAYERED | (int)ExtendedWindowStyles.WS_EX_TRANSPARENT); 
      //Change alpha 
      User32_SetLayeredWindowAttributes(this.Handle, (TransparencyKey.B << 16) + (TransparencyKey.G << 8) + TransparencyKey.R, _alpha, LayeredWindowAttributes.LWA_COLORKEY | LayeredWindowAttributes.LWA_ALPHA); 
     } 
Cuestiones relacionadas