Window on top of everything like mouse cursor

0

I am programming a mouse cursor to be used in the operating system that has motion blur on Windows 10. I decided to use Unity3D for this because of Unity3D has very powerful in terms of effects and hardware rendering. I coded an overlay window to be rendered as top most. However, context menus on any application are getting rendered on top of the window and the objects on the form are getting behind the context menu. Is there a way to achieve this? I don't need to use Unity3D for this so any suggestions are welcome.

Here is the code I wrote for the window.

using System;
using System.Runtime.InteropServices;
using UnityEngine;

[RequireComponent(typeof(Camera))]
public class TransparentWindow : MonoBehaviour
{
    private struct MARGINS
    {
        public int cxLeftWidth;
        public int cxRightWidth;
        public int cyTopHeight;
        public int cyBottomHeight;
    }

    // Define function signatures to import from Windows APIs

    [DllImport("user32.dll")]
    private static extern IntPtr GetActiveWindow();

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

    [DllImport("Dwmapi.dll")]
    private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);

    [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
    static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);

    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    private static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, uint uFlags);

    [DllImport("user32.dll")]
    static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);



    // Definitions of window styles
    const int GWL_STYLE = -16;
    const uint WS_POPUP = 0x80000000;
    const uint WS_VISIBLE = 0x10000000;
    const uint WS_EX_LAYERED = 0x00080000;
    const uint WS_EX_TRANSPARENT = 0x00000020;
    const uint WS_EX_TOPMOST = 0x00000008;

    const int HWND_TOPMOST = -1;



    const UInt32 SWP_NOSIZE = 0x0001;
    const UInt32 SWP_NOMOVE = 0x0002;
    const UInt32 SWP_NOZORDER = 0x0004;
    const UInt32 SWP_NOREDRAW = 0x0008;
    const UInt32 SWP_NOACTIVATE = 0x0010;
    const UInt32 SWP_FRAMECHANGED = 0x0020;
    const UInt32 SWP_SHOWWINDOW = 0x0040;
    const UInt32 SWP_HIDEWINDOW = 0x0080;
    const UInt32 SWP_NOCOPYBITS = 0x0100;
    const UInt32 SWP_NOOWNERZORDER = 0x0200;
    const UInt32 SWP_NOSENDCHANGING = 0x0400;
    const UInt32 SWP_DRAWFRAME = SWP_FRAMECHANGED;
    const UInt32 SWP_NOREPOSITION = SWP_NOOWNERZORDER;

    const UInt32 SWP_DEFERERASE = 0x2000;
    const UInt32 SWP_ASYNCWINDOWPOS = 0x4000;

    // This static method is required because legacy OSes do not support
    // SetWindowLongPtr 
    public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, uint dwNewLong)
    {
        if (IntPtr.Size == 8)
            return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
        else
            return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong));
    }

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

    [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
    private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, uint dwNewLong);

    void Start()
    {
#if !UNITY_EDITOR // You really don't want to enable this in the editor..

        int fWidth = Screen.width;
        int fHeight = Screen.height;
        var margins = new MARGINS() { cxLeftWidth = -1 };
        var hwnd = GetActiveWindow();


        SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
        SetWindowLongPtr(hwnd, -20, WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT); // GWL_EXSTYLE -20
        SetLayeredWindowAttributes(hwnd, 0, 255, 2);
        SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);

        DwmExtendFrameIntoClientArea(hwnd, ref margins);

#endif
    }

   void OnRenderImage(RenderTexture from, RenderTexture to)
    {
        Graphics.Blit(from, to, m_Material);
    }
}

Here is the screenshot animation shows my issue. Please see the second mouse cursor in this screenshot which follows operating system's mouse cursor:

Example

c#
windows
winforms
unity3d
asked on Stack Overflow May 12, 2019 by Bura Chuhadar • edited May 12, 2019 by Bura Chuhadar

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0