游戏最小化时禁用/暂停 AHK 脚本

游戏最小化时禁用/暂停 AHK 脚本

我有一个 AHK 脚本,允许我将操纵杆按下与按键绑定。这些按键用于触发我在玩游戏时在后台运行的训练器中的功能。该脚本运行正常,但问题是当游戏最小化时,操纵杆绑定会向其他程序发送不必要的输入。

我想要的是:

  1. 在游戏最小化时禁用脚本。
  2. 仅向培训师发送击键信息。

我甚至不确定选项 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

因此,让这两个脚本使用相同的切换按钮可以有效地暂停脚本,同时最小化游戏。

我仍然想知道如何在游戏窗口最小化时暂停脚本,而无需解决方法。

相关内容