Formulário mais alto, clicando em “through” possível?

Obrigado por respostas anteriores que me permitiram completar a ferramenta básica que mostra uma grande cruz vermelha nas coordenadas do mouse para deixar ficar mais visível. A cruz vermelha é uma imagem com fundo transparente na forma transparente. O problema é que você não pode clicar, já que o topo e o centro da forma estão realmente posicionados no mouse xy. Existe alguma maneira de fazer isso utilizável para ter a cruz ainda exibida no cursor, mas “clicável” através de?

Você pode usar SetWindowLong para definir o estilo de janela WS_EX_TRANSPARENT:

Se a janela em camadas tiver o estilo de janela estendida WS_EX_TRANSPARENT, a forma da janela em camadas será ignorada e os events do mouse serão transmitidos para as outras janelas abaixo da janela em camadas.

CodeProject tem este artigo detalhando a técnica. Embora esteja em VB.NET, deve ser fácil converter em C #.

Eu usei o seguinte código no passado:

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

mas também foi copiado de outro lugar. As linhas importantes aqui estão no método OnShown . Embora eu tenha que admitir que a linha

 wl = wl | 0x80000 | 0x20; 

é um pouco enigmático, definindo os estilos estendidos WS_EX_LAYERED e WS_EX_TRANSPARENT.

Você provavelmente também pode definir como

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

Para fornecer uma versão mais detalhada / comentada, que também usa TransparencyKey como chave de transparência (não preta como a versão acima), e pode-se definir _alpha como desejado.

  ///  /// 0: the window is completely transparent ... 255: the window is opaque ///  private byte _alpha; private enum GetWindowLong { ///  /// Sets a new extended window style. ///  GWL_EXSTYLE = -20 } private enum ExtendedWindowStyles { ///  /// Transparent window. ///  WS_EX_TRANSPARENT = 0x20, ///  /// Layered window. http://msdn.microsoft.com/en-us/library/windows/desktop/ms632599%28v=vs.85%29.aspx#layered ///  WS_EX_LAYERED = 0x80000 } private enum LayeredWindowAttributes { ///  /// Use bAlpha to determine the opacity of the layered window. ///  LWA_COLORKEY = 0x1, ///  /// Use crKey as the transparency color. ///  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); }