You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中将游戏窗口置于任务栏上方的实现方法求助

解决Unity窗口置于任务栏上方的问题

你的问题核心在于窗口最大化操作覆盖了手动位置设置,加上部分Win32 API参数类型不兼容64位环境,导致修改SetWindowPos的y值无效。以下是具体修正方案:

问题根源拆解

  • ShowWindowAsync(3)(窗口最大化)会让系统接管窗口布局,手动设置的x/y坐标被直接覆盖
  • GetActiveWindow无法保证获取到Unity主窗口句柄,可能导致API调用失效
  • 原代码使用int处理窗口句柄,在64位系统下会出现截断错误

修正后的完整代码

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

public class TransparentWindow : MonoBehaviour
{
    [DllImport("user32.dll", EntryPoint = "SetWindowLongPtrA")]
    static extern IntPtr SetWindowLongPtr(IntPtr hwnd, int nIndex, IntPtr dwNewLong);
    [DllImport("user32.dll")]
    static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
    static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
    [DllImport("user32.dll", EntryPoint = "GetWindowLongPtrA")]
    private static extern IntPtr GetWindowLongPtr(IntPtr hwnd, int nIndex);
    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    private static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();

    // Win32常量定义
    const uint LWA_COLORKEY = 0x00000001;
    static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
    const int GWL_STYLE = -16;
    const int GWL_EXSTYLE = -20;
    const uint WS_CAPTION = 0x00C00000;
    const uint WS_HSCROLL = 0x00100000;
    const uint WS_VSCROLL = 0x00200000;
    const uint WS_SYSMENU = 0x00080000;
    const uint WS_EX_LAYERED = 0x00080000;
    const uint SWP_FRAMECHANGED = 0x0020;
    const uint SWP_SHOWWINDOW = 0x0040;
    const uint SWP_NOOWNERZORDER = 0x0200;

    void Start()
    {
        // 获取Unity主窗口句柄,替代不可靠的GetActiveWindow
        IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
        if (handle == IntPtr.Zero) handle = GetForegroundWindow();

        int screenWidth = Screen.currentResolution.width;
        int windowHeight = Screen.currentResolution.height / 10;

        // 移除标题栏及滚动条样式
        IntPtr currentStyle = GetWindowLongPtr(handle, GWL_STYLE);
        currentStyle = (IntPtr)((long)currentStyle & ~(long)(WS_CAPTION | WS_HSCROLL | WS_VSCROLL | WS_SYSMENU));
        SetWindowLongPtr(handle, GWL_STYLE, currentStyle);

        // 设置分层透明属性
        IntPtr exStyle = GetWindowLongPtr(handle, GWL_EXSTYLE);
        exStyle = (IntPtr)((long)exStyle | (long)WS_EX_LAYERED);
        SetWindowLongPtr(handle, GWL_EXSTYLE, exStyle);
        SetLayeredWindowAttributes(handle, 0, 0, LWA_COLORKEY);

        // 强制窗口置顶并固定位置(y=0贴屏幕顶部,避开底部任务栏)
        SetWindowPos(handle, HWND_TOPMOST, 0, 0, screenWidth, windowHeight, SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);

        // 匹配Unity分辨率到窗口大小,禁用全屏模式
        Screen.SetResolution(screenWidth, windowHeight, false);
    }
}

关键改动说明

  1. 可靠获取窗口句柄:用Process.GetCurrentProcess().MainWindowHandle直接定位Unity主窗口,避免句柄错误
  2. 64位兼容修正:改用SetWindowLongPtrA/GetWindowLongPtrA和IntPtr类型处理句柄,避免32位/64位环境下的类型截断
  3. 移除最大化操作:删除ShowWindowAsync(3),让手动设置的x/y坐标生效
  4. 固定窗口位置:将y值设为0,让窗口紧贴屏幕顶部,自然避开底部任务栏;HWND_TOPMOST确保窗口始终在普通窗口上方

内容的提问来源于stack exchange,提问作者alperrakn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 21:46:35