我有一个 AHK 脚本,允许我将操纵杆按下与按键绑定。这些按键用于触发我在玩游戏时在后台运行的训练器中的功能。该脚本运行正常,但问题是当游戏最小化时,操纵杆绑定会向其他程序发送不必要的输入。
我想要的是:
- 在游戏最小化时禁用脚本。
- 仅向培训师发送击键信息。
我甚至不确定选项 2 是否可行,因为使用简单的脚本通过操纵杆发送按键似乎Joy13:: Send {T}
无法达到预期目的。问题是我不知道我的原始脚本是如何工作的,因为其他人为我制作了它,并且不再可以为此目的修改它。
原始代码如下:
pad2KB := New Pad2KB ;Create an instance of Pad2KB class
;----------Change only this section----------
;pad2KB.bindKey2Keys - bind one pad key to two KB keys
;pad2KB.bindKeys2Keys - bind two pad keys to two KB keys
;pad2KB.bindKeys2Key - bind two pad keys to one KB key
;pad2KB.bindKey2Key - bind one pad key to one KB key
pad2KB.bindKey2Keys("Joy11", "CTRL", "U", true) ;"true" in this case means "Use this key as a toggle - press-release to enable and do the same to disable
pad2KB.bindKey2Keys("Joy8", "CTRL", "I") ;when there's no "true" you can press and hold the key
pad2KB.bindKey2Keys("Joy7", "CTRL", "K")
pad2KB.bindKey2Key("Joy13", "T", true)
;pad2KB.bindKey2Key("4","B")
;pad2KB.bindKeys2Keys("5", "6", "CTRL", "U", true)
;----------Change only this section----------
pad2KB.run() ;Start a while loop and check for the keys
;----------Class----------
class Pad2KB
{
mask := 0xFFFFFFFF
hotKeyStruct := {PadKey0: this.mask, PadKey1: this.mask, KBKey0: this.mask, KBKey1: this.mask, Toggle: false, State: false}
hotKeyArray := {}
abort := false
sleep := 50
bindKey2Keys(nPadKey0, nKBKey0, nKBKey1, nToggle:=0)
{
this.addHotKeys(nPadKey0, this.mask, nKBKey0, nKBKey1, nToggle)
}
bindKeys2Keys(nPadKey0, nPadKey1, nKBKey0, nKBKey1, nToggle:=0)
{
this.addHotKeys(nPadKey0, nPadKey1, nKBKey0, nKBKey1, nToggle)
}
bindKey2Key(nPadKey0, nKBKey0, nToggle:=0)
{
this.addHotKeys(nPadKey0, this.mask, nKBKey0, this.mask, nToggle)
}
bindKeys2Key(nPadKey0, nPadKey1 , nKBKey0, nToggle:=0)
{
this.addHotKeys(nPadKey0, nPadKey1, nKBKey0, this.mask, nToggle)
}
addHotKeys(nPadKey0, nPadKey1, nKBKey0, nKBKey1, nToggle)
{
newHotKeyStruct := new this.hotKeyStruct
newHotKeyStruct.PadKey0 := nPadKey0
newHotKeyStruct.PadKey1 := nPadKey1
newHotKeyStruct.KBKey0 := nKBKey0
newHotKeyStruct.KBKey1 := nKBKey1
newHotKeyStruct.Toggle := nToggle
this.hotKeyArray.push(newHotKeyStruct)
}
checkToggle(state, status, iter)
{
if( (state && !status) || (!state) )
{
this.hotKeyArray[iter].State := true
return true
}
return false
}
getState(key0, key1)
{
result0 := getKeyState(key0, "p") ;"p" - check physical state
if(key1 != this.mask)
{
result1 := getKeyState(key1, "p")
return result0 && result1
}
return result0
}
pressKeys(key0, key1)
{
keys := [key0, key1]
if(!this.abort)
{
Loop % keys.Length()
{
var := keys[A_Index]
if(%var% != this.mask)
Send, {%var% down}
}
Sleep, this.sleep
Loop % keys.Length()
{
var := keys[A_Index]
if(%var% != this.mask)
Send, {%var% up}
}
}
else
{
Loop % keys.Length()
{
var := keys[A_Index]
if(%var% != this.mask)
Send, {%var% up}
}
}
}
processKeys()
{
Loop % this.hotKeyArray.Length()
{
if(this.getState(this.hotKeyArray[A_Index].PadKey0, this.hotKeyArray[A_Index].PadKey1))
{
if(this.checkToggle(this.hotKeyArray[A_Index].Toggle, this.hotKeyArray[A_Index].State, A_Index))
this.pressKeys(this.hotKeyArray[A_Index].KBKey0, this.hotKeyArray[A_Index].KBKey1)
}
else
{
this.hotKeyArray[A_Index].State := false
}
}
}
run()
{
while(!this.abort)
{
this.processKeys()
Sleep, 1
}
}
exitFunc(exitReason:=0, exitCode:=0)
{
this.abort := true
this.processKeys()
}
__Delete()
{
this.exitFunc()
}
}
;----------Class----------
下面是我尝试过但没有成功的脚本的不同变体的示例:
https://paste.ubuntu.com/p/RjVzXXHm6Y/
https://paste.ubuntu.com/p/fQN9mFPWns/
https://paste.ubuntu.com/p/Gxfng2MwbV/
https://paste.ubuntu.com/p/RJWpggt8HK/
再次强调,目标是在 bio4.exe 最小化时让此脚本暂停。也许我可以编写第二个脚本来切换此脚本?
也许这可以与另一个 .bat 文件一起使用,其中包含以下内容:
if bio4.exe window minimized, exit script.ahk
if bio4.exe window maximized, run script.ahk
答案1
为什么通常的答案不起作用
此代码不起作用的 原因#If
或语句是因为这正在检查物理按钮状态并手动实现热键行为,而不是使用内置的 AutoHotkey 热键定义。#IfWinActive
我会想象这是因为该类允许更多扩展的行为映射(一到两个键等) - 原始代码可能有点过于复杂但它大多工作正常,所以最好尽可能不要管它,如果没有必要就不要重写它。
在哪里尝试和修改
为此,我会尝试修改run()
循环。
我自己无法轻松测试此代码,但如果您只想“修复它”,请尝试在调用前放置一个条件this.processKeys()
。您可以在此处放置任何类型的条件:
run() {
while(!this.abort) {
If WinActive("ahk_exe bio4.exe") ; <-- Try a conditional here
this.processKeys()
Sleep, 1
}
}
附注 #1:如果If WinActive()
下面显示的语句不起作用,请使用程序检查标题名称和/或类或其他内容Window Spy
(从任何 AutoHotkey 脚本的托盘图标上下文菜单中打开),以查看活动窗口的标题、类、exe 是什么。启动,Window Spy
然后启动/激活您感兴趣的程序并查看Window Spy
显示的内容(如果需要,您可以使用 [Windows 键]+'a' '暂停'显示)。
附注#2:如果您决定使用普通的窗口标题而不是名称ahk_exe
,请注意SetTitleMatchMode
。
附注#3:如果需要的话,您还可以在此时使用逻辑组合来执行任何类型的多进程检查。
;Allow process to run for any window *except* when Chrome or Explorer windows are active
If !WinActive("ahk_exe chrome.exe") && !WinActive("ahk_exe explorer.exe")
附注#4:如果您想要检查窗口是否存在,而不是窗口是否处于活动状态,也可以使用WinExist()
。您的示例中似乎不是这种情况,但我想让您也了解此功能。
; Mapping will pause if a chrome window is running, even if it's not active...
If WinActive("ahk_exe bio4.exe") && !WinExist("ahk_exe chrome.exe")
答案2
对于快捷方式,通常的解决方案是使用 #IfWinActive 指令。
为了更精细的控制使用 #If 指令 结合 WinActive/IfWin[Not]Active 内置函数。您可能还会发现有用的 WinExist() / IfWin[Not]Exist。
Example:
IfWinActive, Untitled - Notepad
{
WinMaximize ; Maximizes the Notepad window found by IfWinActive above.
Send, Some text.{Enter}
return
}
答案3
我在这里找到了另一个脚本来最小化和最大化游戏。joy12::Pause
在上面原始脚本的末尾添加解决了这个问题,因为我的 Joy12 的任务是在另一个正在运行的脚本中最小化/最大化 bio4.exe 窗口:
Joy12::
WinGetPos, X, Y, Width, Height, Resident Evil 4
if (X == -32000)
WinMaximize, Resident Evil 4
else if (X == 0 and Y == 0 and Width == 1920 and Height == 1080)
WinMinimize, Resident Evil 4
return
因此,让这两个脚本使用相同的切换按钮可以有效地暂停脚本,同时最小化游戏。
我仍然想知道如何在游戏窗口最小化时暂停脚本,而无需解决方法。