Unity外部控制PC(Windows) 全屏程序的最小化 / 恢复全屏控制。

直接贴上完整的最小化程序代码,和恢复全屏的控制代码, 

打包自己电脑测试全屏最小化是可以的,恢复是不可以的,因为最小化之后会失去焦点,只能自己点击程序才可恢复全屏, 所以只能别人控制程序才可以实现恢复,不管是websocket 还是UDP都可以

此类项目控制只适用于被别人控制来进行最小化和恢复全屏的

 

代码如下:

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

/// <summary>
/// PC(Windows) 全屏程序的最小化 / 恢复全屏控制。
///
/// 原理:
///   Unity 的 Screen API 没有最小化接口,Windows 平台需要 P/Invoke user32.dll:
///     - ShowWindow(hwnd, SW_MINIMIZE) → 最小化到任务栏
///     - ShowWindow(hwnd, SW_RESTORE)  → 从最小化还原窗口
///   还原后如果没回到全屏(最小化/失焦过程中被系统或 Unity 退出全屏),
///   再用 Screen.fullScreenMode = FullScreenWindow 强制拉回无边框全屏。
///
/// 使用方式:
///   1. 挂到场景中任意常驻 GameObject 上(建议和 UI 管理器放一起,别被销毁)。
///   2. UI 按钮的 OnClick 直接绑定 Minimize / RestoreToFullScreen。
///   3. PlayerSettings → Resolution and Presentation → Fullscreen Mode
///      建议选 "Fullscreen Window"(无边框全屏,最小化/还原行为最稳)。
///
/// 注意事项:
///   - 仅在 Build 后的 Windows .exe 中生效,Editor 中为空操作。
///   - 用户点任务栏图标还原是系统行为,不需要代码;但如果还原后没回全屏,
///     OnApplicationFocus 里的自动回全屏兜底会处理(autoRestoreFullScreen 可关)。
///   - 最小化即失焦,默认 Unity 会暂停逻辑(OnApplicationPause);
///     需要后台继续跑就勾选 runInBackground。
/// </summary>
public class WindowMinMaxController : MonoSingleton <WindowMinMaxController>
{
    [Header("行为设置")]
    [Tooltip("最小化/失焦后程序是否继续在后台运行(不暂停)")]
    public bool runInBackground = true;

    [Tooltip("重新获得焦点时自动回到全屏(含用户点任务栏还原的情况)")]
    public bool autoRestoreFullScreen = true;

    [Tooltip("演示用快捷键:Ctrl+M 最小化,Ctrl+R 恢复全屏,F11 全屏切换")]
    public bool enableTestHotkeys = true;

    // ===== Win32 常量 =====
    private const int SW_MINIMIZE = 6;
    private const int SW_RESTORE = 9;

    // ===== DllImport(仅 Windows 独立版有效)=====
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
    [DllImport("user32.dll")]
    private static extern IntPtr GetActiveWindow();

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

    [DllImport("user32.dll")]
    private static extern bool IsIconic(IntPtr hWnd);   // 是否最小化

    [DllImport("user32.dll")]
    private static extern bool SetForegroundWindow(IntPtr hWnd);
#endif

    // 缓存窗口句柄
    private IntPtr hwnd = IntPtr.Zero;

    private void Start()
    {
        Application.runInBackground = runInBackground;
        CacheWindowHandle();
    }

    private void Update()
    {
        if (!enableTestHotkeys) return;

        if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.M))
            Minimize();
        if (Input.GetKeyDown(KeyCode.V))
            RestoreToFullScreen();
        if (Input.GetKeyDown(KeyCode.F11))
            Screen.fullScreen = !Screen.fullScreen;
    }

    /// <summary>重新获得焦点时兜底:确保回到全屏(覆盖点任务栏还原、Alt+Tab 切回等情况)</summary>
    private void OnApplicationFocus(bool hasFocus)
    {
        if (hasFocus && autoRestoreFullScreen)
            EnterFullScreen();
    }

    /// <summary>获取并缓存当前程序窗口句柄(先取活动窗口,兜底进程主窗口)</summary>
    private void CacheWindowHandle()
    {
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
        hwnd = GetActiveWindow();
        if (hwnd == IntPtr.Zero)
            hwnd = Process.GetCurrentProcess().MainWindowHandle;
        if (hwnd == IntPtr.Zero)
            UnityEngine.Debug.LogError("[WindowMinMax] 获取窗口句柄失败,最小化/恢复将无效。");
#endif
    }

    // ================== 对外操作(可绑定 UI 按钮) ==================

    /// <summary>最小化到任务栏</summary>
    public void Minimize()
    {
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
        if (hwnd == IntPtr.Zero) CacheWindowHandle();
        if (hwnd == IntPtr.Zero) return;

        // 独占全屏下直接最小化可能失效/黑屏,先切成无边框全屏规避
        if (Screen.fullScreen && Screen.fullScreenMode == FullScreenMode.ExclusiveFullScreen)
            Screen.fullScreenMode = FullScreenMode.MaximizedWindow;

        ShowWindow(hwnd, SW_MINIMIZE);
#endif
    }

    /// <summary>从最小化恢复,并确保回到全屏(回到最小化前的全屏状态)</summary>
    public void RestoreToFullScreen()
    {
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
        if (hwnd == IntPtr.Zero) CacheWindowHandle();
        if (hwnd != IntPtr.Zero && IsIconic(hwnd))
        {
            ShowWindow(hwnd, SW_RESTORE);
            SetForegroundWindow(hwnd);
        }

        // 无论还原前是什么状态,强制回到无边框全屏
        EnterFullScreen();
#endif
    }

    /// <summary>强制进入无边框全屏(不操作最小化状态)</summary>
    public void EnterFullScreen()
    {
        Screen.fullScreenMode = FullScreenMode.FullScreenWindow;
    }

    /// <summary>退出全屏变成普通窗口</summary>
    public void ExitFullScreen()
    {
        Screen.fullScreen = false;
    }

    /// <summary>当前是否处于最小化状态(Editor 恒为 false)</summary>
    public bool IsMinimized
    {
        get
        {
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
            return hwnd != IntPtr.Zero && IsIconic(hwnd);
#else
            return false;
#endif
        }
    }
}

 

 
posted @ 2026-09-10 09:26  剑起苍穹  阅读(32)  评论(0)    收藏  举报
/*鼠标点击特效*/