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

cpp 复制代码
HWND FindWindowExA(
  [in, optional] HWND   hWndParent,
  [in, optional] HWND   hWndChildAfter,
  [in, optional] LPCSTR lpszClass,
  [in, optional] LPCSTR lpszWindow
);

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

cs 复制代码
[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最终打包后的窗口名称

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

cs 复制代码
    [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

cpp 复制代码
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#的方法:

cs 复制代码
[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.使用方法
cs 复制代码
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吧,多点赞,收藏,关注,就能给我能量哦~谢谢大家。

相关推荐
一个笔记本13 小时前
godot log | 修改main scene
游戏引擎·godot
nnsix14 小时前
Unity PicoVR开发 实时预览Unity场景 在Pico设备中(串流)
unity·游戏引擎
一只一只20 小时前
Unity之UGUI Button按钮组件详细使用教程
unity·游戏引擎·ugui·button·ugui button
神米米1 天前
Maya快速安装UE4 布料权重绘制插件PhysX导出apx
游戏引擎·ue4·maya
WarPigs1 天前
Unity阴影
unity·游戏引擎
一只一只1 天前
Unity之Invoke
unity·游戏引擎·invoke
技术小甜甜1 天前
【Godot】【入门】信号系统从 0 到 1(UI/玩法彻底解耦的通用写法)
ui·游戏引擎·godot
技术小甜甜1 天前
【Godot】【入门】节点生命周期怎么用(避免帧循环乱写导致卡顿的范式)
游戏引擎·godot
tealcwu1 天前
【Unity踩坑】Simulate Touch Input From Mouse or Pen 导致检测不到鼠标点击和滚轮
unity·计算机外设·游戏引擎
ThreePointsHeat1 天前
Unity WebGL打包后启动方法,部署本地服务器
unity·游戏引擎·webgl