简体   繁体   中英

Topmost form, clicking “through” possible?

Thank you for previous answers that enabled to me complete the basic tool that shows large red cross in the mouse coordinates in order to let be more visible. The red cross is an image with transparent background in the transparent form. The problem is that you cannot click through, since its topmost and the center of form is actually positioned to mouse xy. Is there any way how to make this usable in order to have the cross still displayed on the cursor but "clickable" through?

You can use SetWindowLong to set the WS_EX_TRANSPARENT window style:

If the layered window has the WS_EX_TRANSPARENT extended window style, the shape of the layered window will be ignored and the mouse events will be passed to the other windows underneath the layered window.

CodeProject has this article detailing the technique. Though it's in VB.NET it should be easy to convert to C#.

I have used the following code in the past:

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

but it also was copied from somewhere else. The important lines here are in the OnShown method. Though I have to admit that the line

wl = wl | 0x80000 | 0x20;

is a little cryptic, setting the WS_EX_LAYERED and WS_EX_TRANSPARENT extended styles.

You can probably also set it like

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

To provide a more detailed/commented version, which also uses TransparencyKey as transparency key (not black as the version above), and one might set _alpha as desired.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM