Unity 设置窗口置顶超级详解版

目录

前言

一、user32.dll

1.什么是user32.dll

2.如何使用user32.dll

 二、句柄Handle

1.句柄

2.句柄的功能

3.拿句柄的方法

三、窗口置顶

1.窗口置顶的方法

2.参数说明

3.使用方法 

四、作者的碎碎念


前言

up依旧挑战全网讲解最详细版本~~

本篇文章讲解的是unity打包了window的安装包使用的窗口设置,安卓之类的不在此列~

一、user32.dll

1.什么是user32.dll

想要窗口置顶,其实已经不是在控制软件了,实际上请求的是windows的帮助,告诉系统:“系统,把我放到最上面~”。

这时候就需要和系统做一些交互,让我们去写和系统交互这部分代码,那是不可能的。我们就知道怎么用就行。user32.dll是微软写好的文件,里面封装了很多方法,可以让我们直接和系统交互。

备注:

up这里只讲和窗口置顶相关的方法。如果你想知道,还有哪些方法呢?可以查询下方链接。

Windows API 索引 - Win32 apps | Microsoft Learn

windows系统是微软公司研发的,所以这个网页是微软公司放出来,给大家写的一些说明书,还有其他内容可以查到,大家可以自己查询。

如果你真的去查阅了,你会发现,他的方法和我们是不一样的的。

(如图2所示方法)IntPtr GetForegroundWindow()

链接是:

GetForegroundWindow 函数 (winuser.h) - Win32 apps | Microsoft Learn

在原文中是:

图1 方法GetForegroundWindow()

你会发现画红圈圈那里是不一样的,那怎么办呢?

因为,在封装的时候,使用词汇进行了一点改变,在另外一个链接里有说明:

用平台调用封送数据 - .NET Framework | Microsoft Learn

图2 部分分装说明

在C#中,我们所有的HWND,都被Intptr代替。

全部表格如下:

2.如何使用user32.dll

因为,我们的方法都来自于这个dll,所以我们每次要把dll里的方法拿出来,我们才能用。所以我们每一个系统方法上面,必须要写[DllImport("user32.dll")](如图3所示)

图3 引用user32.dll

 二、句柄Handle

1.句柄

关于为什么这么翻译,up在网上没有找到官方的说明,这里up自己的理解是“句子的手柄”。

句子代表我们写的很多代码,手柄就是平时玩游戏的手柄,我们通过句柄来控制东西。我们需要这个控制的权限。

2.句柄的功能

我们看见的每个窗口,都有个专用的手柄,你要控制谁,就需要拿到这个手柄。(如图4,单纯皮一下所示)

图4 孙悟空吸句柄

3.拿句柄的方法

下方函数的意思是,寻找句柄,并返回句柄。

官方链接:FindWindowExA 函数 (winuser.h) - Win32 apps | Microsoft Learn

HWND FindWindowExA(
  [in, optional] HWND   hWndParent,
  [in, optional] HWND   hWndChildAfter,
  [in, optional] LPCSTR lpszClass,
  [in, optional] LPCSTR lpszWindow
);

上面是官方给的C++的代码,按照表格,我们翻译成C#的代码。

[DllImport("user32.dll")]
static extern IntPtr FindWindowExA(
IntPtr hWndParent, 
IntPtr hWndChildAfter, 
string lpszClass, 
string lpszWindow);

这里解释一下里面不常见的词汇:

extern:因为这个方法不是unity自带的,而是user32.dll里面的,所以如果直接写,就会报错,因为他会在你所有的代码里面查一遍,发现查不到FindWindowExA这个方法,就会报错。(如图5所示),所以在方法中必须标明,这是外部方法,不要在代码里找了,找不到的。

因此,这个单词一般和[DllImport("*****")]一起出现。

图5 方法报错

IntPtr:声明句柄,这里就不多说了


参数解释:

IntPtr hWndParent:父窗口的句柄        窗口也分父子窗口(如图6所示),浏览器就是父窗口,浏览器中,还有好多子窗口。所以查找时候,会问你,要在哪个父窗口下找吗?如果这里填IntPtr.Zero,那就是,查找所有的父窗口。

图6 浏览器

IntPtr hWndChildAfter:从某个子窗口句柄往后开始找 (如图6所示),如果我想从Unity屏幕置顶往后开始找,那我这里就要把这个窗口的句柄传进去,同样,如果填IntPtr.Zero,那就是,查找所有的子窗口。

string lpszClass:窗口类别        窗口是有很多类别的,除了刚看的浏览器这种窗口,开始菜单栏也属于窗口。显然,这不是一个类别的窗口,所以,如果你对窗口类别有限制,就填在这里。如果没有,就填写null

图7 菜单窗口

string lpszWindow: 窗口名称        输入你要找的窗口名称,对unity打包后的软件来说,窗口名称就是软件的名称,就是(如图8所示)。

图8 unity最终打包后的窗口名称

 到此为止,通过使用这个方法,我们就可以拿到软件的句柄了。

    [DllImport("user32.dll")]
    static extern IntPtr FindWindowExA(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow);

    public string projectName;
    IntPtr intPtr;
    void Start()
    {
        intPtr = FindWindowExA(IntPtr.Zero, IntPtr.Zero, null, projectName);
    }

三、窗口置顶

1.窗口置顶的方法

官方链接:SetWindowPos 函数 (winuser.h) - Win32 apps | Microsoft Learn

BOOL SetWindowPos(
  [in]           HWND hWnd,
  [in, optional] HWND hWndInsertAfter,
  [in]           int  X,
  [in]           int  Y,
  [in]           int  cx,
  [in]           int  cy,
  [in]           UINT uFlags
);

改编成C#的方法:

[DllImport("user32.dll")]
    static extern bool SetWindowPos(
IntPtr intPtr, 
int hwndInsertAfter, 
int X, 
int Y, 
int cx, 
int cy, 
uint uFlags);

备注:

如果注意看的小伙伴会问我,为什么 int hwndInsertAfter是int呢?不应该是IntPtr吗?

这个比较特殊,因为在官方文档里备注了。(如图9所示)

图9 hwndInsertAfter注解

注解的意思是:这里要填数字int

1        放在所有窗口最下面

-2       放在置顶窗口以外的第一层

0        单次置顶

-1        永远置顶 

2.参数说明

IntPtr intPtr:                     填写你想要控制的句柄   
int hwndInsertAfter:           前面讲过,按照需求填一下
int X:                                     你打算把窗口放在哪个屏幕的哪个位置中的x   
int Y:                                     你打算把窗口放在哪个屏幕的哪个位置中的y
int cx:                                    你的窗口分辨率宽(如果全屏显示,这个没有意义)
int cy:                                    你的窗口分辨率高(如果全屏显示,这个没有意义)
uint uFlags:                           功能很多(如图10所示)

图10 uFlags

你用哪个,就填写下面的数字就行了。

这次我们选择(如图11所示),意思就是,显示窗口,并且可以操作。

图11 0x0040
3.使用方法 
using System;
using System.Runtime.InteropServices;
using UnityEngine;

public class myWindowMod : MonoBehaviour
{
    [DllImport("user32.dll")]
    static extern IntPtr FindWindowExA(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow);

    //引入设置窗口方法
    [DllImport("user32.dll")]
    static extern bool SetWindowPos(IntPtr intPtr, int hwndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

    public string projectName;
    IntPtr intPtr;
    void Start()
    {
        intPtr = FindWindowExA(IntPtr.Zero, IntPtr.Zero, null, projectName);

        //设置窗口  //句柄   //放在位置(0,0)   //显示窗口并能操作
        SetWindowPos(intPtr, -1,0,0,1920,1080, 0x0040);
                         //永久置顶  //窗口分辨率1920,1080
    }
}

以上就是置顶窗口的全部代码!

四、作者的碎碎念

这一部分涉及到很多内容,确实不太好学,大家加油啊~

在程序这么复杂的环境下,大家也不想失去一个这么努力的把知识讲详细的up吧,多点赞,收藏,关注,就能给我能量哦~谢谢大家。

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 在Unity中将窗口强制置顶,我们可以使用以下代码来实现: 首先,在需要实现强制置顶的脚本中,引入以下命名空间: ```csharp using System; using System.Runtime.InteropServices; ``` 然后,在脚本的Awake或Start方法中,调用下面的方法: ```csharp void Awake() { SetWindowPos(GetUnityWindowHandle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } ``` 接下来,我们需要在脚本中定义这三个调用Win32 API函数的方法: ```csharp [DllImport("user32.dll")] private static extern IntPtr GetActiveWindow(); [DllImport("user32.dll", EntryPoint = "FindWindow")] private static extern IntPtr FindWindow(string className, string windowName); [DllImport("user32.dll")] private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); ``` 最后,我们还需要定义一些常量: ```csharp private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); private static readonly uint SWP_NOMOVE = 0x0002; private static readonly uint SWP_NOSIZE = 0x0001; ``` 这样,当游戏运行时,Unity窗口将会被强制置顶。 需要注意的是,这种方法只适用于Windows平台,而且可能与其他操作系统的窗口管理器产生冲突。另外,强制置顶窗口可能会干扰用户的操作,并且违反了一些用户体验设计原则,所以在使用之前请慎重考虑。 ### 回答2: Unity窗口强制置顶是指将Unity程序窗口设置为始终位于屏幕最顶层的状态。在Unity开发中,有时我们需要保持游戏窗口始终置顶,这样可以确保游戏在其他窗口的前面显示,提供更好的游戏体验。 在Unity中,实现窗口强制置顶的方法有多种途径。以下是其中一种简单的实现方式: 1. 首先,在Unity的脚本中创建一个新的C#脚本文件,命名为"WindowManager"。 2. 打开WindowManager脚本,添加以下代码实现窗口强制置顶的功能: ``` using System; using System.Runtime.InteropServices; using UnityEngine; public class WindowManager : MonoBehaviour { // 导入Windows API库,用于设置窗口的显示状态 [DllImport("user32.dll")] private static extern IntPtr SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags); // 定义常量,用于设置窗口状态和显示层级 private const int HWND_TOPMOST = -1; // 窗口置于最顶层 private const uint SWP_SHOWWINDOW = 0x0040; // 显示窗口的常量值 void Start() { // 获取Unity窗口的句柄(handle) IntPtr handle = GetUnityWindowHandle(); // 将窗口置于最顶层 SetWindowPos(handle, (IntPtr)HWND_TOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW); } // 获取Unity窗口的句柄 private IntPtr GetUnityWindowHandle() { #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN IntPtr handle = GetActiveWindow(); return handle; #else Debug.LogError("平台不支持"); return IntPtr.Zero; #endif } // 导入Windows API库,获取活动窗口句柄 [DllImport("user32.dll")] private static extern IntPtr GetActiveWindow(); } ``` 3. 在Unity编辑器中,将WindowManager脚本添加到一个空的GameObject上。 4. 运行游戏,Unity窗口将会始终置顶显示。 需要注意的是,该方法仅适用于Windows平台和Unity编辑器,对于其他平台可能需要使用不同的方法实现窗口置顶的功能。使用该方法时,要确保在发布游戏之前检查平台兼容性,并提供替代方案以确保在不同平台上能够正确运行。 ### 回答3: Unity可以使用以下代码将窗口强制置顶: ```csharp using System; using System.Runtime.InteropServices; using UnityEngine; public class WindowUtil : MonoBehaviour { #if UNITY_STANDALONE_WIN // 导入Windows API函数 [DllImport("user32.dll", EntryPoint = "SetWindowPos")] private static extern bool SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int flags); // 定义窗口层级 private const int HWND_TOPMOST = -1; private const int SWP_NOMOVE = 0x0002; private const int SWP_NOSIZE = 0x0001; private void Start() { // 获取当前Unity窗口的句柄 IntPtr hwnd = GetUnityWindowHandle(); // 设置窗口大小和位置 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } // 获取Unity窗口句柄 private IntPtr GetUnityWindowHandle() { IntPtr hwnd = IntPtr.Zero; // 获取Unity窗口句柄 if (Application.platform == RuntimePlatform.WindowsEditor) { hwnd = GetForegroundWindow(); } else if (Application.platform == RuntimePlatform.WindowsPlayer) { hwnd = GetActiveWindow(); } return hwnd; } // 导入Windows API函数 [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr GetActiveWindow(); [DllImport("user32.dll", EntryPoint = "GetForegroundWindow")] private static extern IntPtr GetForegroundWindow(); #endif } ``` 以上代码使用Windows API函数SetWindowPos来设置窗口的层级,将其置顶。通过获取Unity窗口的句柄,可以在Windows平台上实现窗口强制置顶的效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菌菌巧乐兹

希望能给大家写更多有用的文章~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值