• 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

    1. HWND FindWindowExA(
    2. [in, optional] HWND hWndParent,
    3. [in, optional] HWND hWndChildAfter,
    4. [in, optional] LPCSTR lpszClass,
    5. [in, optional] LPCSTR lpszWindow
    6. );

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

    1. [DllImport("user32.dll")]
    2. static extern IntPtr FindWindowExA(
    3. IntPtr hWndParent,
    4. IntPtr hWndChildAfter,
    5. string lpszClass,
    6. 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最终打包后的窗口名称

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

    1. [DllImport("user32.dll")]
    2. static extern IntPtr FindWindowExA(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow);
    3. public string projectName;
    4. IntPtr intPtr;
    5. void Start()
    6. {
    7. intPtr = FindWindowExA(IntPtr.Zero, IntPtr.Zero, null, projectName);
    8. }

    三、窗口置顶

    1.窗口置顶的方法

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

    1. BOOL SetWindowPos(
    2. [in] HWND hWnd,
    3. [in, optional] HWND hWndInsertAfter,
    4. [in] int X,
    5. [in] int Y,
    6. [in] int cx,
    7. [in] int cy,
    8. [in] UINT uFlags
    9. );

    改编成C#的方法:

    1. [DllImport("user32.dll")]
    2. static extern bool SetWindowPos(
    3. IntPtr intPtr,
    4. int hwndInsertAfter,
    5. int X,
    6. int Y,
    7. int cx,
    8. int cy,
    9. 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.使用方法 
    1. using System;
    2. using System.Runtime.InteropServices;
    3. using UnityEngine;
    4. public class myWindowMod : MonoBehaviour
    5. {
    6. [DllImport("user32.dll")]
    7. static extern IntPtr FindWindowExA(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow);
    8. //引入设置窗口方法
    9. [DllImport("user32.dll")]
    10. static extern bool SetWindowPos(IntPtr intPtr, int hwndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
    11. public string projectName;
    12. IntPtr intPtr;
    13. void Start()
    14. {
    15. intPtr = FindWindowExA(IntPtr.Zero, IntPtr.Zero, null, projectName);
    16. //设置窗口 //句柄 //放在位置(0,0) //显示窗口并能操作
    17. SetWindowPos(intPtr, -1,0,0,1920,1080, 0x0040);
    18. //永久置顶 //窗口分辨率1920,1080
    19. }
    20. }

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

    四、作者的碎碎念

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

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

  • 相关阅读:
    【GEE】7、利用GEE进行遥感影像分类【随机森林分类】
    N点标定-坐标系变换
    Python 中的随机 IP 地址生成器
    数据分析-费米问题
    Springboot学习笔记——3
    flink的window和windowAll的区别
    shell脚本之环境变量
    【限时免费】20天拿下华为OD笔试之【哈希集合】2023B-明明的随机数【欧弟算法】全网注释最详细分类最全的华为OD真题题解
    测试人员为什么也要学习Linux操作系统
    Maven的安装与配置与使用
  • 原文地址:https://blog.csdn.net/weixin_49427945/article/details/139649067