Bootstrap

【按键精灵】设定窗口大小与位置

一、使用背景

各位有没有遇到过使用脚本挂游戏时,窗口偶尔会发生位置和大小改变,导致一些不太通用的脚本无法正常执行需要的命令的情况?比如你有一个2560x1440的主屏幕,以及一个1280x800的副屏幕,游戏窗口大小1920x1080,有时候你或你的家人会想着关掉屏幕显示,能省电啥的,再次开屏后,就发生了窗口位置大小与原来设定的脚本信息不一致,而且找图的照片也与游戏UI不一致。

二、解决方案

为了应对上面的问题,有没有一种方法可以将窗口信息绑定在一个变量中,后面只要判断窗口信息与设定的变量结果是否一致然后修改窗口属性来达到避免窗口抖动而引起的脚本失效问题?

在 [代码块1] 中的四行代码是本文使用到的核心命令

'[代码块1]
'窗口句柄
Hwnd = Plugin.Window.Find("类名", "标题")
'窗口信息
clientData = Plugin.Window.GetWindowRect(Hwnd) ' "x|y|x_end|y_end"
Plugin.Window.Size("窗口句柄", "设置窗口宽度", "设置窗口高度")
Plugin.Window.Move("窗口句柄", "设置窗口X坐标", "设置窗口Y坐标")

2.1 创建场景

我们在桌面创建一个 test.txt,用记事本打开,如图2-1所示。

图2-1  桌面创建的记事本文件

2.2 获取窗口信息

我们打开按键精灵脚本,打开抓抓工具,在句柄栏拖动准星到窗口图标处,如图2-2所示。

图2-2  获取窗口信息

拖动后可以得到窗口的句柄,类名,标题,位置,大小等信息,我们需要用的是类名和标题。复制类名和标题,在按键精灵脚本编辑器中写上如 [代码块2] 所示的代码,可以得到窗口位置和大小

'[代码块2]
Hwnd = Plugin.Window.Find("Notepad", "test.txt - 记事本") '723032
Arr = Split(Plugin.Window.GetWindowRect(Hwnd), "|") '[窗口x, 窗口y, 窗口x_end, 窗口y_end]

2.3 场景实现

在2.2中获取的窗口数据记下来,得到了我们写脚本前确定的窗口信息,比如我的数据是

clientPosition = Array(2016, 474, 2324, 642)

【窗口位置:x=2016  y=474】;【窗口大小:width=2324-2016=308  height=642-474=168】

这个时候,我们尝试改动窗口到任意位置,任意大小,然后执行 [代码块3] 的命令

'[代码块3]
Call Plugin.Window.Size(Hwnd, clientPosition(2) - clientPosition(0), clientPosition(3) - clientPosition(1))
Call Plugin.Window.Move(Hwnd, clientPosition(0), clientPosition(1))

就会发现,窗口回到了原来的大小和位置。

2.4 场景实现

参考 [代码块4] 的内容,模拟一个游戏单线程主循环的回路,通过自定义变量设定窗口标准位置和大小,每执行一轮循环就检查窗口是否符合规定,或者可以用多线程延时检查。

'[代码块4]
Call setVars() '设定自变量
While isEnd() '判断游戏结束
	Call getInfo() '获取游戏信息
	Call Main() '执行主要脚本
	Call checkClientRect() '检测窗口信息
Wend

Sub checkClientRect()
	Hwnd = Plugin.Window.Find("Notepad", "test.txt - 记事本")
	Arr = Split(Plugin.Window.GetWindowRect(Hwnd), "|")
	If sameWith(myArr, Arr) = False Then '判断窗口改变
		TracePrint "["&time&"] 恢复窗口"
		Call Plugin.Window.Size(Hwnd, myArr(2) - myArr(0), myArr(3) - myArr(1))
		Call Plugin.Window.Move(Hwnd, myArr(0), myArr(1))
	End If
End Sub

Function isEnd
	isEnd = True
End Function
Function sameWith(a, b)
	Dim result
	result = True
	If a(0) <> b(0) Then 
		result = False
	ElseIf a(1) <> b(1) Then
		result = False
	ElseIf a(2) <> b(2) Then 
		result = False
	ElseIf a(3) <> b(3) Then 
		result = False
	End If
	sameWith = result
End Function
Sub setVars()
    UserVar myArr = 0 "我记录的窗口信息"
//    	myArr = Array(2016, 474, 2324, 642) '采用这个需要CInt(a(0))<>CInt(b(0))
    	myArr = Split("2016|474|2324|642", "|") '采用这个是因为sameWith中没有化为同类型判断
    UserVar runCount = 0 "执行次数"
End Sub
Sub getInfo()
	runCount = runCount + 1
	TracePrint "["&time&"] 第"&runCount&"次循环开始。"
End Sub
Sub Main()
	Delay 3000 '模拟脚本执行了3s
End Sub

[代码块4] 模拟了一个脚本,执行一次约3s,也就是每3s检查一次窗口信息,这个时候可以尝试改动窗口大小位置,看看它有没有按我们的设定回到原来的形状。

2.5 实例展示

;