Unity Windows Overlay

0

I'm trying to make a Overlay for the Windows OS with Unity. I got all the information, needed for this from this thread in UnityForum. The script I used is the following:

    using System;
    using System.Runtime.InteropServices;
    using UnityEngine;
    
    public class TransparentWindow : MonoBehaviour
    {
        [SerializeField]
        private Material m_Material;
        
        private struct MARGINS
        {
            public int cxLeftWidth;
            public int cxRightWidth;
            public int cyTopHeight;
            public int cyBottomHeight;
        }
        
        [DllImport("user32.dll")]
        private static extern IntPtr GetActiveWindow();
        
        [DllImport("user32.dll")]
        private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
        
        [DllImport("user32.dll")]
        static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
        
        [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, int uFlags);
        
        [DllImport("Dwmapi.dll")]
        private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
        
        const int GWL_STYLE = -16;
        const uint WS_POPUP = 0x80000000;
        const uint WS_VISIBLE = 0x10000000;
        const int HWND_TOPMOST = -1;
        
        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);
        
            // Transparent windows with click through
            //GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
            SetWindowLong(hwnd, -20, 524288 | 32);
            // Transparency=51=20%, LWA_ALPHA=2
            SetLayeredWindowAttributes(hwnd, 0, 255, 2);
            //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
            SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); 
            DwmExtendFrameIntoClientArea(hwnd, ref margins);
#endif
        }
        
        void OnRenderImage(RenderTexture from, RenderTexture to)
        {
            Graphics.Blit(from, to, m_Material);
        }
    }

Now the thing is: The transparency(works with shader and material), the Click-through and the alwaysOnTop properties are working perfectly.But, if I click through the window, the application is pausing. How can I implemet, that the program is not pausing while not focused?

Another thing is, that the whole programm just works, if you start it windowed, but not in fullscreen. If i start in fullscreen, it minimizes, when I click something.

Thank you!

c#
.net
unity3d
winapi
user32
asked on Stack Overflow Jun 11, 2019 by RomanTenger • edited Jun 20, 2020 by Community

1 Answer

0

They might both be related. Unity has an option Application.runInBackground

Should the player be running when the application is in the background?

Default is false (application pauses when it is in the background).

You can enable it in your script like

private void Awake()
{
    Application.runInBackground = true;
}

or in the Player settings EditProject SettingsPlayerResolution and Presentation

enable Run In Background

the option Visible in Background might be interresting for you as well

Enable this option to show the application in the background if Windowed Fullscreen Mode is used (in Windows).

enter image description here

Also see the Standalone Player settings for more information.


General tip:

You should rather wrap the entire Start method with

#if !UNITY_EDITOR
    private void Start()
    {

    }
#endif

If you don't it's not bad but also an empty Start method will be called by Unity causing unnecessary overhead.

answered on Stack Overflow Jun 11, 2019 by derHugo • edited Jun 11, 2019 by derHugo

User contributions licensed under CC BY-SA 3.0