Unity 设置无边框窗口

        最近在做窗口模式切换和设置分辨率,发现Unity只有设置窗口或全屏切换的API,没有设置无边框窗口的API。于是我就在在网上找到了一种设置方法。

        注意,该方法仅限windows系统。

        引用用windows的user32.dll库,调用库里的方法,来设置窗口无边框:

/// <summary>
    /// 使用查找任务栏
    /// </summary>
    /// <param name="strClassName"></param>
    /// <param name="nptWindowName"></param>
    /// <returns></returns>
    [DllImport("user32.dll")]
    static extern IntPtr FindWindow(string strClassName, int nptWindowName);

    /// <summary>
    /// 获取当前窗口
    /// </summary>
    /// <returns></returns>
    [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow();

    /// <summary>
    /// 获取窗口位置以及大小
    /// </summary>
    /// <param name="hWnd"></param>
    /// <param name="lpRect"></param>
    /// <returns></returns>
    [DllImport("user32.dll")] static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT
    {
        public int Left; //最左坐标
        public int Top; //最上坐标
        public int Right; //最右坐标
        public int Bottom; //最下坐标
    }

    /// <summary>
    /// 设置窗口位置,尺寸
    /// </summary>
    /// <param name="hWnd"></param>
    /// <param name="hWndInsertAfter"></param>
    /// <param name="X"></param>
    /// <param name="Y"></param>
    /// <param name="cx"></param>
    /// <param name="cy"></param>
    /// <param name="uFlags"></param>
    /// <returns></returns>
    [DllImport("user32.dll")] static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

    /// <summary>
    /// 设置windows自带边框
    /// </summary>
    /// <param name="hwnd"></param>
    /// <param name="_nIndex"></param>
    /// <param name="dwNewLong"></param>
    /// <returns></returns>
    [DllImport("user32.dll")] static extern IntPtr SetWindowLong(IntPtr hwnd, int _nIndex, int dwNewLong);

        设置无边框模式时要注意,只能在窗口模式下设置无边框,全屏模式下设置无边框只会退出全屏变成窗口模式,所以在全屏模式下要先设置为窗口模式,再设置无边框。

/// <summary>
    /// 除任务栏外最大化窗口(无边框)
    /// </summary>
    public void WitnOutBorder()
    {
        //如果是全屏模式,要切换成窗口模式
        if (Screen.fullScreen)
        {
            //新的分辨率(exe文件新的宽高)  这个是Unity里的设置屏幕大小,
            //Screen.SetResolution((int)m_ScreenPosition.width, (int)m_ScreenPosition.height, false);
            Screen.fullScreen = false;
        }

        StartCoroutine(WitnOutBorderCoroutine());
    }

    /// <summary>
    /// 除任务栏外最大化窗口(无边框)协程
    /// </summary>
    private IEnumerator WitnOutBorderCoroutine()
    {
        //等待游戏变成窗口模式
        while (Screen.fullScreen)
        {
            yield return null;
        }

        //新的屏幕宽度
        m_ScreenPosition.width = m_Resolutions[0].width;
        //新的屏幕高度=当前屏幕分辨率的高度-状态栏的高度
        int currMaxScreenHeight = m_Resolutions[0].height - GetTaskBarHeight();
        m_ScreenPosition.height = currMaxScreenHeight;

        //m_ScreenPosition.x = (int)((Screen.currentResolution.width - m_ScreenPosition.width) / 2);//宽度居中
        //m_ScreenPosition.y = (int)((Screen.currentResolution.height - m_ScreenPosition.height) / 2);//高度居中

        //设置无框
        SetWindowLong(GetForegroundWindow(), GWL_STYLE, WS_BORDER);
        //exe居左上显示;
        bool result = SetWindowPos(GetForegroundWindow(), 0, 0, 0, (int)m_ScreenPosition.width, (int)m_ScreenPosition.height, SWP_SHOWWINDOW);
        //exe居中显示;
        // bool result = SetWindowPos(GetForegroundWindow(), 0, (int)m_ScreenPosition.x, (int)m_ScreenPosition.y,  (int)m_ScreenPosition.width, (int)m_ScreenPosition.height, SWP_SHOWWINDOW);

        m_CurrResolution = string.Format("{0}x{1}", m_Resolutions[0].width, m_Resolutions[0].height);
        GameEntry.Setting.SetString(Constant.Setting.Resolution, m_CurrResolution);
        GameEntry.Setting.Save();
    }

        下面为窗口设置完整代码:

using GameFramework;
using GameMain;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using UnityEngine;

/// <summary>
/// 窗口模式
/// </summary>
public enum WindowMode
{
    /// <summary>
    /// 全屏
    /// </summary>
    FullScreen = 0,
    /// <summary>
    /// 窗口
    /// </summary>
    Windowed = 1,
    /// <summary>
    /// 无边框
    /// </summary>
    WitnOutBorder = 2
}

public class WindowSetting : MonoSingLeton<WindowSetting>
{
    /// <summary>
    /// 当前窗口模式
    /// </summary>
    private WindowMode m_CurrWindowMode;

    /// <summary>
    /// 当前窗口模式
    /// </summary>
    public WindowMode CurrWindowMode { get { return m_CurrWindowMode; } }

    /// <summary>
    /// 分辨率
    /// </summary>
    private string m_CurrResolution = string.Empty;

    /// <summary>
    /// 屏幕分辨率
    /// </summary>
    public string CurrResolution { get { return m_CurrResolution; } }

    /// <summary>
    /// 使用查找任务栏
    /// </summary>
    /// <param name="strClassName"></param>
    /// <param name="nptWindowName"></param>
    /// <returns></returns>
    [DllImport("user32.dll")]
    static extern IntPtr FindWindow(string strClassName, int nptWindowName);

    /// <summary>
    /// 获取当前窗口
    /// </summary>
    /// <returns></returns>
    [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow();

    /// <summary>
    /// 获取窗口位置以及大小
    /// </summary>
    /// <param name="hWnd"></param>
    /// <param name="lpRect"></param>
    /// <returns></returns>
    [DllImport("user32.dll")] static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT
    {
        public int Left; //最左坐标
        public int Top; //最上坐标
        public int Right; //最右坐标
        public int Bottom; //最下坐标
    }

    /// <summary>
    /// 设置窗口位置,尺寸
    /// </summary>
    /// <param name="hWnd"></param>
    /// <param name="hWndInsertAfter"></param>
    /// <param name="X"></param>
    /// <param name="Y"></param>
    /// <param name="cx"></param>
    /// <param name="cy"></param>
    /// <param name="uFlags"></param>
    /// <returns></returns>
    [DllImport("user32.dll")] static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

    /// <summary>
    /// 设置windows自带边框
    /// </summary>
    /// <param name="hwnd"></param>
    /// <param name="_nIndex"></param>
    /// <param name="dwNewLong"></param>
    /// <returns></returns>
    [DllImport("user32.dll")] static extern IntPtr SetWindowLong(IntPtr hwnd, int _nIndex, int dwNewLong);

    const uint SWP_SHOWWINDOW = 0x0040;
    const int GWL_STYLE = -16;
    const int WS_BORDER = 1;

    /// <summary>
    /// 所有可选分辨率
    /// </summary>
    Resolution[] m_Resolutions;

    /// <summary>
    /// 当前屏幕可用分辨率
    /// </summary>
    public Resolution[] Resolutions { get { return m_Resolutions; } }

    /// <summary>
    /// 当前屏幕可用分辨率字典
    /// </summary>
    Dictionary<string, Resolution> m_ResolutionDic;

    /// <summary>
    /// 当前屏幕可用分辨率字典
    /// </summary>
    public Dictionary<string, Resolution> ResolutionDic { get { return m_ResolutionDic; } }

    /// <summary>
    /// 最终的屏幕的位置和长宽
    /// </summary>
    private Rect m_ScreenPosition;

    protected override void Init()
    {
        base.Init();
        m_ResolutionDic = new Dictionary<string, Resolution>();
        for (int i = 0; i < Screen.resolutions.Length; i++)
        {
            string str = Utility.Text.Format("{0}x{1}", Screen.resolutions[i].width, Screen.resolutions[i].height);
            m_ResolutionDic[str] = Screen.resolutions[i];
        }

        m_Resolutions = m_ResolutionDic.Values.ToArray();
        Array.Reverse(m_Resolutions);

        //获取保存在本地的窗口模式
        m_CurrWindowMode = (WindowMode)GameEntry.Setting.GetInt(Constant.Setting.WindowMode, 0);

        //获取保存在本地的分辨率
        m_CurrResolution = GameEntry.Setting.GetString(Constant.Setting.Resolution, string.Format("{0}x{1}", m_Resolutions[0].width, m_Resolutions[0].height));

#if UNITY_EDITOR

#else
        if(m_CurrWindowMode == WindowMode.WitnOutBorder)
        {
            WitnOutBorder();
        }
#endif
    }

    public override void Dispose()
    {
        StopAllCoroutines();
        base.Dispose();
    }

    /// <summary>
    /// 设置窗口模式
    /// </summary>
    /// <param name="windowMode"></param>
    public void SetWindowMode(WindowMode windowMode)
    {
        switch (windowMode)
        {
            case WindowMode.FullScreen:
                SetResolution(m_CurrResolution, true);
                break;
            case WindowMode.Windowed:
                SetResolution(m_CurrResolution, false);
                break;
            case WindowMode.WitnOutBorder:
                WitnOutBorder();
                break;
        }
        m_CurrWindowMode = windowMode;
        //将当前窗口模式保存到本地
        GameEntry.Setting.SetInt(Constant.Setting.WindowMode, (int)m_CurrWindowMode);
        GameEntry.Setting.Save();
    }

    /// <summary>
    /// 获取当前分辨率
    /// </summary>
    public Resolution GetCurrResolution()
    {
        if (m_ResolutionDic.ContainsKey(m_CurrResolution))
        {
            return m_ResolutionDic[m_CurrResolution];
        }
        return m_Resolutions[0];
    }

    /// <summary>
    /// 设置分辨率
    /// </summary>
    /// <param name="width">宽</param>
    /// <param name="height">高</param>
    /// <param name="fullScreen">是否全屏</param>
    public void SetResolution(int width, int height, bool fullScreen)
    {
        Screen.SetResolution(width, height, fullScreen);
        m_CurrResolution = string.Format("{0}x{1}", width, height);
        if (fullScreen)
            m_CurrWindowMode = WindowMode.FullScreen;
        else
            m_CurrWindowMode = WindowMode.Windowed;

        //将当前分辨率保存到本地
        GameEntry.Setting.SetString(Constant.Setting.Resolution, m_CurrResolution);
        GameEntry.Setting.Save();
    }

    /// <summary>
    /// 设置分辨率
    /// </summary>
    /// <param name="index">当前屏幕可用分辨率m_Resolutions数组的下标</param>
    /// <param name="fullScreen">是否全屏</param>
    public void SetResolution(int index, bool fullScreen)
    {
        if (index < 0 && index > m_Resolutions.Length)
        {
            //错误index索引超出范围
            return;
        }
        Screen.SetResolution(m_Resolutions[index].width, m_Resolutions[index].height, fullScreen);
        m_CurrResolution = string.Format("{0}x{1}", m_Resolutions[index].width, m_Resolutions[index].height);
        if (fullScreen)
            m_CurrWindowMode = WindowMode.FullScreen;
        else
            m_CurrWindowMode = WindowMode.Windowed;
        //将当前分辨率保存到本地
        GameEntry.Setting.SetString(Constant.Setting.Resolution, m_CurrResolution);
        GameEntry.Setting.Save();
    }

    /// <summary>
    /// 设置分辨率
    /// </summary>
    /// <param name="resolutionStr"></param>
    /// <param name="fullScreen"></param>
    public void SetResolution(string resolutionStr, bool fullScreen)
    {
        if (m_ResolutionDic.ContainsKey(resolutionStr))
        {
            Resolution resolution = m_ResolutionDic[resolutionStr];
            Screen.SetResolution(resolution.width, resolution.height, fullScreen);
            m_CurrResolution = resolutionStr;
            //将当前分辨率保存到本地
            GameEntry.Setting.SetString(Constant.Setting.Resolution, m_CurrResolution);
            GameEntry.Setting.Save();
        }
    }

    /// <summary>
    /// 获取当前窗口尺寸
    /// </summary>
    /// <returns></returns>
    public Rect GetWindowInfo()
    {
        RECT rect = new RECT();
        Rect targetRect = new Rect();
        GetWindowRect(GetForegroundWindow(), ref rect);
        targetRect.width = Mathf.Abs(rect.Right - rect.Left);
        targetRect.height = Mathf.Abs(rect.Top - rect.Bottom);

        //锚点在左上角
        targetRect.x = rect.Left;
        targetRect.y = rect.Top;
        return targetRect;
    }

    /// <summary>
    /// 获取任务栏高度
    /// </summary>
    /// <returns>任务栏高度</returns>
    private int GetTaskBarHeight()
    {
        int taskbarHeight = 10;
        IntPtr hWnd = FindWindow("Shell_TrayWnd", 0);       //找到任务栏窗口
        RECT rect = new RECT();
        GetWindowRect(hWnd, ref rect);                      //获取任务栏的窗口位置及大小
        taskbarHeight = (int)(rect.Bottom - rect.Top);      //得到任务栏的高度
        return taskbarHeight;
    }

    /// <summary>
    /// 除任务栏外最大化窗口(无边框)
    /// </summary>
    public void WitnOutBorder()
    {
        //如果是全屏模式,要切换成窗口模式
        if (Screen.fullScreen)
        {
            //新的分辨率(exe文件新的宽高)  这个是Unity里的设置屏幕大小,
            //Screen.SetResolution((int)m_ScreenPosition.width, (int)m_ScreenPosition.height, false);
            Screen.fullScreen = false;
        }

        StartCoroutine(WitnOutBorderCoroutine());
    }

    /// <summary>
    /// 除任务栏外最大化窗口(无边框)协程
    /// </summary>
    private IEnumerator WitnOutBorderCoroutine()
    {
        //等待游戏变成窗口模式
        while (Screen.fullScreen)
        {
            yield return null;
        }

        //新的屏幕宽度
        m_ScreenPosition.width = m_Resolutions[0].width;
        //新的屏幕高度=当前屏幕分辨率的高度-状态栏的高度
        int currMaxScreenHeight = m_Resolutions[0].height - GetTaskBarHeight();
        m_ScreenPosition.height = currMaxScreenHeight;

        //m_ScreenPosition.x = (int)((Screen.currentResolution.width - m_ScreenPosition.width) / 2);//宽度居中
        //m_ScreenPosition.y = (int)((Screen.currentResolution.height - m_ScreenPosition.height) / 2);//高度居中

        //设置无框
        SetWindowLong(GetForegroundWindow(), GWL_STYLE, WS_BORDER);
        //exe居左上显示;
        bool result = SetWindowPos(GetForegroundWindow(), 0, 0, 0, (int)m_ScreenPosition.width, (int)m_ScreenPosition.height, SWP_SHOWWINDOW);
        //exe居中显示;
        // bool result = SetWindowPos(GetForegroundWindow(), 0, (int)m_ScreenPosition.x, (int)m_ScreenPosition.y,  (int)m_ScreenPosition.width, (int)m_ScreenPosition.height, SWP_SHOWWINDOW);

        m_CurrResolution = string.Format("{0}x{1}", m_Resolutions[0].width, m_Resolutions[0].height);
        //将当前分辨率保存到本地
        GameEntry.Setting.SetString(Constant.Setting.Resolution, m_CurrResolution);
        GameEntry.Setting.Save();
    }

    /// <summary>
    /// 设置全屏无边框
    /// </summary>
    private void Setposition()
    {
        SetWindowLong(GetForegroundWindow(), GWL_STYLE, WS_BORDER);      //无边框
        bool result = SetWindowPos(GetForegroundWindow(), 0, 0, 0, m_Resolutions[0].width, m_Resolutions[0].height, SWP_SHOWWINDOW);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Unity设置PC EXE窗口标题颜色,您需要使用Windows API来实现。以下是一种实现方法: 1. 在Unity中创建一个C#脚本,并在脚本中添加以下代码: ```csharp using System; using System.Runtime.InteropServices; using UnityEngine; public class WindowColorManager { [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); public const int WM_SETTEXT = 0x000C; public static void SetWindowTitleColor(string title, Color color) { IntPtr hWnd = GetForegroundWindow(); IntPtr hFont = SendMessage(hWnd, 0x0030, IntPtr.Zero, IntPtr.Zero); // 获取窗口字体 int rgb = (color.b * 65536) + (color.g * 256) + color.r; int lParam = (rgb & 0xFF0000) >> 16 | (rgb & 0xFF00) | (rgb & 0xFF) << 16; SendMessage(hWnd, WM_SETTEXT, IntPtr.Zero, Marshal.StringToHGlobalAuto(title)); // 设置窗口标题 SendMessage(hWnd, 0x0040, hFont, new IntPtr(lParam)); // 设置窗口颜色 } } ``` 2. 在需要设置窗口标题颜色的地方,调用`SetWindowTitleColor`方法并传入所需的标题和颜色。例如,在点击按钮时设置窗口标题颜色为红色: ```csharp using UnityEngine; using UnityEngine.UI; public class ButtonClickHandler : MonoBehaviour { public Button button; public string windowTitle; public Color windowColor; void Start() { button.onClick.AddListener(SetWindowTitleColor); } void SetWindowTitleColor() { WindowColorManager.SetWindowTitleColor(windowTitle, windowColor); } } ``` 请注意,此方法仅适用于Windows平台,并且需要使用DllImport来调用Windows API。另外,这种方法会修改整个窗口的标题和颜色,而不仅仅是Unity应用程序的窗口标题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值