控制Unity发布的PC包的窗体

  大家好,我是阿赵。
  用Unity发布PC包接入某些渠道时,有时候会收到一些特殊的需求,比如控制窗口最大化(比如某些情况强制显示窗体)、最小化(比如老板键)、强制规定窗体置顶等。虽然我一直认为这些需求都是流氓软件行为,但作为一个弱小的技术人员,别人有规定,我也只能去做。
  所以这里分享一下一些简单的控制窗体的方法。
在这里插入图片描述

这里写了个测试demo,然后还有一个归纳的工具类:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class WindowCtrl : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}void OnGUI(){if (OneButton("最大化")){WindowsHelper.ShowMaxWindow();}if (OneButton("最小化")){WindowsHelper.ShowMinWindow();}if (OneButton("还原")){WindowsHelper.ShowRestoreWindow();}if (OneButton("锁定置顶")){WindowsHelper.ShowTopWindow();}if (OneButton("取消置顶")){WindowsHelper.CancelTopWindow();}}private bool OneButton(string content){return GUILayout.Button(content, GUILayout.Width(100), GUILayout.Height(60));}}

上面这个是demo的代码,运行的时候会出现上面截图所示的几个按钮,可以控制窗体。

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;public class WindowsHelper
{public delegate bool WNDENUMPROC(IntPtr hwnd, uint lParam);[DllImport("user32.dll", SetLastError = true)]public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, uint lParam);[DllImport("user32.dll", SetLastError = true)]public static extern IntPtr GetParent(IntPtr hWnd);[DllImport("user32.dll")]public static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref uint lpdwProcessId);[DllImport("kernel32.dll")]public static extern void SetLastError(uint dwErrCode);[DllImport("user32.dll")]public static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);[DllImport("user32.dll", CharSet = CharSet.Auto)]public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hPos, int x, int y, int cx, int cy, uint nflags);const int SW_SHOWMINIMIZED = 2; //{最小化, 激活}const int SW_SHOWMAXIMIZED = 3;//最大化const int SW_SHOWRESTORE = 1;//还原static IntPtr HWND_TOP = new IntPtr(0);static IntPtr HWND_TOPMOST = new IntPtr(-1);static IntPtr HWND_NORMAL = new IntPtr(-2);private const uint SWP_NOSIZE = 0x0001;//表示此次设置不改变大小private const uint SWP_NOMOVE = 0x0002;//表示此次设置不改变位置private static IntPtr selfWindow;//获取当前进程的窗体句柄public static IntPtr GetProcessWnd(){IntPtr ptrWnd = IntPtr.Zero;uint pid = (uint)Process.GetCurrentProcess().Id;  // 当前进程 IDbool bResult = EnumWindows(new WNDENUMPROC(delegate (IntPtr hwnd, uint lParam){uint id = 0;if (GetParent(hwnd) == IntPtr.Zero){GetWindowThreadProcessId(hwnd, ref id);if (id == lParam)    // 找到进程对应的主窗口句柄{ptrWnd = hwnd;   // 把句柄缓存起来SetLastError(0);    // 设置无错误return false;   // 返回 false 以终止枚举窗口}}return true;}), pid);return (!bResult && Marshal.GetLastWin32Error() == 0) ? ptrWnd : IntPtr.Zero;}//获取缓存的当前窗口private static IntPtr GetSelfWindow(){if(selfWindow == null||selfWindow == IntPtr.Zero){selfWindow = GetProcessWnd();}return selfWindow;}//最大化窗口public static void ShowMaxWindow(){ShowWindow(GetSelfWindow(), SW_SHOWMAXIMIZED);}//最小化窗口public static void ShowMinWindow(){ShowWindow(GetSelfWindow(), SW_SHOWMINIMIZED);}//还原窗口public static void ShowRestoreWindow(){ShowWindow(GetSelfWindow(), SW_SHOWRESTORE);}//锁定窗口置顶public static void ShowTopWindow(){IntPtr hWnd = WindowsHelper.GetProcessWnd();SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);}//取消锁定窗口置顶public static void CancelTopWindow(){IntPtr hWnd = WindowsHelper.GetProcessWnd();SetWindowPos(hWnd, HWND_NORMAL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);}
}

这个是工具类,主要用到了user32.dll,所以只能在Windows系统使用。
其中有几个方法是比较重要的,单独拿出来说一下:
1、GetProcessWnd方法
  这个方法是通过当前的进程ID去获取当前应用的窗口句柄。
  我从网上看了很多其他人的文章,发现有些是通过获取当前焦点的窗口,或者是通过Find方法指定窗体名称去获取窗口句柄。我觉得这些方法都不是特别的理想。
  通过当前焦点获取窗口,在某些情况下是获取不到我们这个应用的窗体的,比如360游戏大厅,它的插件接入运行方式是把游戏嵌入到浏览器窗体里面的,在调用sdk初始化之前,连窗口都不显示的,更别说获取到焦点窗口了。
  通过名字来获取窗体,原理上问题不大,但如果窗口不是单例,就可能会获取错误。然后把某些名字写死在代码里面,总感觉过不了自己那一关,感觉很low。

2、ShowWindow方法
这个方法可以设置窗口最大化最小化,可以通过以下枚举来指定:

const int SW_SHOWMINIMIZED = 2; //{最小化, 激活}
const int SW_SHOWMAXIMIZED = 3;//最大化
const int SW_SHOWRESTORE = 1;//还原

3、SetWindowPos
这个方法可以控制窗体的Z排序层级、位置、大小。
1.其中Z排序的参数枚举有:
HWND_BOTTOM:值为1,将窗口置于Z序的底部。如果参数hWnd标识了一个顶层窗口,则窗口失去顶级位置,并且被置在其他窗口的底部。
HWND_NOTOPMOST:值为-2,将窗口置于所有非顶层窗口之上(即在所有顶层窗口之后)。如果窗口已经是非顶层窗口则该标志不起作用。
HWND_TOP:值为0,将窗口置于Z序的顶部。
HWND_TOPMOST:值为-1,将窗口置于所有非顶层窗口之上。即使窗口未被激活窗口也将保持顶级位置。
SetWindowPos的Z排序参数有多个重载,我自己试了一下,Z参数是long类型的那种重载似乎不能达到效果,而参数类型是IntPtr 的重载是可以使用的,所以在引用方法的时候,要用

[DllImport("user32.dll", CharSet = CharSet.Auto)]public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hPos, int x, int y, int cx, int cy, uint nflags);

而定义枚举的时候,要这样定义:

static IntPtr HWND_TOP = new IntPtr(0);
static IntPtr HWND_TOPMOST = new IntPtr(-1);
static IntPtr HWND_NORMAL = new IntPtr(-2);

2.最后一个参数是可选项,完整的枚举有这些:

const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_NOZORDER = 0x0004;
const UInt32 SWP_NOREDRAW = 0x0008;
const UInt32 SWP_NOACTIVATE = 0x0010;
const UInt32 SWP_FRAMECHANGED = 0x0020;
const UInt32 SWP_SHOWWINDOW = 0x0040;
const UInt32 SWP_HIDEWINDOW = 0x0080;
const UInt32 SWP_NOCOPYBITS = 0x0100;
const UInt32 SWP_NOOWNERZORDER = 0x0200;
const UInt32 SWP_NOSENDCHANGING = 0x0400;

这些参数可以同时选择多个,用|号连接多个参数即可。比如SWP_NOSIZE | SWP_NOMOVE,这代表不改变大小,也不改变坐标。
通过不同的参数配搭,可以做出各种效果的窗体控制,各位有兴趣可以试试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/50906.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Spark+django的国漫推荐系统--计算机毕业设计项目

近年来,随着互联网的蓬勃发展,企事业单位对信息的管理提出了更高的要求。以传统的管理方式已无法满足现代人们的需求。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,随着各行业的不断发展,基…

【Java架构-包管理工具】-Maven基础(一)

本文摘要 Maven作为Java后端使用频率非常高的一款依赖管理工具,在此咱们由浅入深,分三篇文章(Maven基础、Maven进阶、私服搭建)来深入学习Maven,此篇为开篇主要介绍Maven概念、模型、安装配置、基本命令 文章目录 本文…

Nexus(Maven管理器)下载和安装

我们以 Nexus 2.x 为例,演示 Nexus 的安装过程。 官方下载地址 1. 进入 Nexus 2.x 下载页面,根据本机操作系统,选择对应的版本进行下载,如下图所示。 2. 将下载 Nexus 安装包解压到本地磁盘,可获得 nexus-2.14.20-0…

内网穿透实战应用-windwos10系统搭建我的世界服务器,内网穿透实现联机游戏Minecraft

文章目录 1. Java环境搭建2.安装我的世界Minecraft服务3. 启动我的世界服务4.局域网测试连接我的世界服务器5. 安装cpolar内网穿透6. 创建隧道映射内网端口7. 测试公网远程联机8. 配置固定TCP端口地址8.1 保留一个固定tcp地址8.2 配置固定tcp地址 9. 使用固定公网地址远程联机 …

【c语言】文件操作 万字详解

目录 一,为什么使用文件 二,什么是文件 1,程序文件 2,数据文件 3,文件名 三,文件的打开和关闭 1,文件指针 2,文件的打开和关闭 四, 文件的顺序读写 1,顺序…

stm32控制蜂鸣器源代码(附带proteus线路图)

说明: 1 PB0输出0时,蜂鸣器发生; 2 蜂鸣器电阻值如果太大会导致电流太小,发不出声音; 3蜂鸣器额定电压需要设置得低一点,可以是2V,但不能高于3V,这更右上角的电阻值有关系&#x…

【算法专题突破】双指针 - 移动零(1)

目录 写在前面 1. 题目解析 2. 算法原理 3. 代码编写 写在最后: 写在前面 在进行了剑指Offer和LeetCode hot100的毒打之后, 我决心系统地学习一些经典算法,增强我的综合算法能力。 1. 题目解析 题目链接:283. 移动零 - 力…

一网打尽java注解-克隆-面向对象设计原则-设计模式

文章目录 注解内置注解元注解 对象克隆为什么要克隆?如何克隆浅克隆深克隆 Java设计模式什么是设计模式?为什么要学习设计模式? 建模语言类接口类之间的关系依赖关系关联关系聚合关系组合关系继承关系实现关系 面向对象设计原则单一职责开闭原…

无涯教程-PHP - 移除的扩展

以下扩展已从PHP 7开始删除- eregmssqlmysqlsybase_ct 以下SAPI已从PHP 7开始删除- aolserverapacheapache_hooksapache2filtercaudiumcontinuityisapimilternsapiphttpdpi3webroxenthttpdtuxwebjames PHP - 移除的扩展 - 无涯教程网无涯教程网提供以下扩展已从PHP 7开始删除…

【SVN内网穿透】远程访问Linux SVN服务

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

jvm-运行时数据区概述及线程

1.运行时数据区内部结构 不同的jvm对于内存的划分方式和管理机制存在着部分差异 java虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机的启动而创建,随着虚拟机的退出而销毁,另外一些则是与线程一一对应的&…

渗透测试漏洞原理之---【SQL注入】

文章目录 1、SQL注入原理1.1、SQL注入原理1.2、SQL注入危害1.3、SQL注入分类1.4、SQL注入漏洞挖掘1.4.1、注入点判断1.4.2、主要关注的问题1.4.3、sql-lib靶场第一关注入点 1.5、知识补充 2、SQL注入基本手法2.1、联合查询判断注入类型判断列数判断显示位数据库中的敏感信息获取…

Unity shader 入门之渲染管线一、总览

如下示意图 应用阶段(ApplicationStage):准备场景信息(视景体,摄像机参数)、粗粒度剔除、定义每个模型的渲染命令(材质,shader)——由开发者定义,不做讨论。几何阶段(GemetryStage)&…

Resnet模型详解

1、Resnet是什么? Resnet是一种深度神经网络架构,被广泛用于计算机视觉任务,特别是图像分类。它是由微软研究院的研究员于2015年提出的,是深度学习领域的重要里程碑之一。 2、网络退化问题 理论上来讲,随着网络的层…

基于springboot的社区生活缴费系统/基于javaweb的水电缴费系统

摘 要 网络的广泛应用给生活带来了十分的便利。所以把社区生活缴费管理与现在网络相结合,利用java语言建设社区生活缴费系统,实现社区生活缴费管理的信息化。则对于进一步提高社区生活缴费管理发展,丰富社区生活缴费管理经验能起到不少的促进…

使用Python搭建服务器公网展示本地电脑文件

文章目录 1.前言2.本地http服务器搭建2.1.Python的安装和设置2.2.Python服务器设置和测试 3.cpolar的安装和注册3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 Python作为热度比较高的编程语言,其语法简单且语句清晰,而且python有…

UE4/5Niagara粒子特效之Niagara_Particles官方案例:1.5->2.3

目录 之前的文章: 1.5 Blend Attributes by Value 发射器更新 粒子生成 粒子更新 2.1 Static Beams ​编辑 发射器更新: 粒子生成 粒子更新 2.2 Dynamic Beams 没有开始模拟前的效果是: 开始模拟后的效果是: 发射器更新 …

python模拟登入某平台+破解验证码

概述 python模拟登录平台,遇见验证码识别!用最简单的方法seleniumda破解验证码,来自动登录平台 详细 python用seleniumxpath模拟登录破解验证码 先随便找个小说平台用户登陆 - 书海小说网用户登陆 - 书海小说网用户登陆 - 书海小说网 准…

【网络安全】跨站脚本(xss)攻击

跨站点脚本(也称为 XSS)是一种 Web 安全漏洞,允许攻击者破坏用户与易受攻击的应用程序的交互。它允许攻击者绕过同源策略,该策略旨在将不同的网站彼此隔离。跨站点脚本漏洞通常允许攻击者伪装成受害者用户,执行用户能够…

七夕学算法

目录 P1031 [NOIP2002 提高组] 均分纸牌 原题链接 : 题面 : 思路 : 代码 : P1036 [NOIP2002 普及组] 选数 原题链接 : 题面 : 思路 : 代码 : P1060 [NOIP2006 普及组] 开心的金明 原题链接 : 题面 : 思路 : 01背包例题 : 代码 : P1100 高低位交换 原题…