Unity Windows叠加层

时间:2019-06-11 15:39:03

标签: c# .net unity3d winapi user32

我正在尝试使用Unity为Windows操作系统制作覆盖图。 我从UnityForum的该线程中获得了所需的所有信息。 我使用的脚本如下:

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

现在的事情是:透明度(可用于着色器和材质),Click-through和alwaysOnTop属性运行良好。但是,如果我单击窗口,则应用程序正在暂停。我如何实现该程序在不集中精力时不会暂停?

另一件事是,如果您在窗口中启动整个程序,那么整个程序就可以正常工作,而不是全屏显示。如果我以全屏模式启动,则当我单击某些内容时,它将最小化。

谢谢!

1 个答案:

答案 0 :(得分:0)

它们可能都相关。 Unity有一个选项Application.runInBackground

  

应用程序在后台运行时,播放器是否应在运行?

     

默认值为false(应用程序在后台时暂停)。

您可以在脚本中启用它,例如

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

或在播放器设置中编辑项目设置播放器分辨率和演示文稿

启用在后台运行

在后台可见选项可能对您来说也很有趣

  

如果使用“窗口式全屏模式”(在Windows中),请启用此选项以在后台显示应用程序。

enter image description here

另请参阅Standalone Player settings


一般提示:

您应该将整个Start方法包装为

#if !UNITY_EDITOR
    private void Start()
    {

    }
#endif

如果您不这样做,那还不错,但是Unity也会调用一个空的Start方法,从而导致不必要的开销。