最顶层的窗体,可以点击“穿透”吗?

11

感谢您之前的回答,使我完成了一个基本工具,该工具能够在鼠标坐标处显示大号红十字,以便更加可见。这个红十字是一个带有透明背景的图像。问题是由于它位于最上层和中心位置正好位于鼠标xy位置,所以不能进行点击。有没有办法让这个红十字仍然显示在光标上但又能通过"点击"呢?

2个回答

12
你可以使用SetWindowLong函数来设置WS_EX_TRANSPARENT窗口样式:

如果分层窗口具有WS_EX_TRANSPARENT扩展窗口样式,则分层窗口的形状将被忽略,并且鼠标事件将传递到位于分层窗口下面的其他窗口。

CodeProject网站上有这篇文章详细介绍了该技术。虽然是VB.NET代码,但很容易转换为C#代码。
我以前曾经使用过以下代码:
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);
}

但这段代码也是从别处复制过来的。这里重要的是在OnShown方法中的那些行。尽管我必须承认这一行

wl = wl | 0x80000 | 0x20;

这段代码有些晦涩,它设置了WS_EX_LAYERED和WS_EX_TRANSPARENT扩展样式。

你可能也可以像下面这样设置

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

请问您能否提供更多细节?我对这个低级API不是很熟悉,谢谢! - Petr
非常感谢,这里真的很棒,回答非常迅速。 - Petr
使用SetLayeredWindowAttributes后,之前在VS Designer中设置的透明度将会丢失,导致窗体只有半透明效果。 但是禁用这一行不会影响“可点击”的效果,它仍然可以很好地工作! - Petr
1
这是正确的样式使用方式,但不要以这种方式应用它。 而是重写[CreateParams]。 Http://stackoverflow.com/q/13986363/1386111 - Ben Voigt
@Joey,使用具有透明背景的图片是否可以实现这一点?例如一个圆形? - hurnhu
显示剩余4条评论

0
为了提供更详细/注释版本,该版本还使用TransparencyKey作为透明度关键字(而非上述版本中的黑色),并且可以根据需要设置_alpha。
        /// <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);
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接