I am trying to find a way to create a transparent overlay that I can put anywhere on the screen, but that does not stop keystrokes and mouse events from passing through.

If you have ever seen the program Camtasia, they do it... when you define a portion of the screen, they drop a shadowed gradient over the screen, and as you drag a rectangle, it "cut's away" the gradient. But, even though the screen has the shadow layer, everything is still clickable and usable. It is a visual effect that doesn't seem to alter the functionality of any program.

I have done something that ALMOST works. I have a form that I set the opacity down on, and then I use the GetWindowLong function to set a transparent pass-through style. But it won't work for every application. For example, a drawing program won't work when I have the overlay up.

But... in Camtasia, everything still works fine... so they must know some mojo I don't... Anyone have any ideas?

The code I am using is:

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

        private const int GWL_EXSTYLE = -20;
        private const int WS_EX_TRANSPARENT = 0x20;

...

           int exstyle = GetWindowLong(this.Handle, GWL_EXSTYLE);
            exstyle |= WS_EX_TRANSPARENT;
            SetWindowLong(this.Handle, GWL_EXSTYLE, exstyle);

OK... I got this on my own.

In case anyone else is trying to do it, you also need to make your form a child of the Desktop. That seems to be working.

So, the missing code is - first you need the interop Includes:

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    public static extern IntPtr GetDesktopWindow();
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr FindWindow(
    [MarshalAs(UnmanagedType.LPTStr)] string lpClassName,
    [MarshalAs(UnmanagedType.LPTStr)] string lpWindowName);
    [DllImport("user32.dll")]
     public static extern IntPtr SetParent(
          IntPtr hWndChild,      // handle to window
          IntPtr hWndNewParent   // new parent window
        );
    [DllImport("user32.dll", SetLastError = true)]
    static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll", SetLastError = true)]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    private const int GWL_EXSTYLE = -20;
    private const int WS_EX_TRANSPARENT = 0x20;

Then, in the method you call to turn the window into an overlay screen (or in the form SHOWN method if you prefer...) Add this code:

int exstyle = GetWindowLong(this.Handle, GWL_EXSTYLE);
        exstyle |= WS_EX_TRANSPARENT;
        SetWindowLong(this.Handle, GWL_EXSTYLE, exstyle);

        IntPtr hwndf = this.Handle;
        IntPtr hwndParent = GetDesktopWindow();
        SetParent(hwndf, hwndParent);

        this.TopMost = true;
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.