Disable/pause AHK script while game is minimized

0

I have an AHK script that allows me to bind joystick presses to keystrokes. These keystrokes are used to trigger functions in a trainer that runs in the background while I play a game. The script works fine, but the problem is that the joystick bindings send unwanted input to other programs when the game is minimized.

What I want is either:

  1. disabling the script while the game is minimized.
  2. send keystrokes only to the trainer.

Im not even sure that option 2 is viable as sending keystrokes via joystick with a simple script like Joy13:: Send {T} doesn't seem to work for the intended purpose. The problem is that I don't know how my original script works as someone else made it for me and is no longer available to modify it for this purpose.

Here is the original code:

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----------

Below are examples of different variations of the script that I have tried with no success:

https://paste.ubuntu.com/p/RjVzXXHm6Y/

https://paste.ubuntu.com/p/fQN9mFPWns/

https://paste.ubuntu.com/p/Gxfng2MwbV/

https://paste.ubuntu.com/p/RJWpggt8HK/

Again, the goal is to simply get this script to pause while bio4.exe is minimized. Perhaps I can write a second script to toggle this script?

Perhaps this could work with another .bat file that with something like:

if bio4.exe window minimized, exit script.ahk
if bio4.exe window maximized, run script.ahk
script
autohotkey
asked on Super User Oct 3, 2019 by Kalamalka Kid • edited Oct 3, 2019 by Kalamalka Kid

3 Answers

1

For shortcuts, the usual solutions use #IfWinActive directive.

For finer control use the #If directive in combination with the WinActive/IfWin[Not]Active built-in function. You might also find useful WinExist() / IfWin[Not]Exist.

Example:

    IfWinActive, Untitled - Notepad
    {
        WinMaximize  ; Maximizes the Notepad window found by IfWinActive above.
        Send, Some text.{Enter}
        return
    }
answered on Super User Oct 3, 2019 by harrymc
1

Why the Usual Answers Don't Work

The reason #If or #IfWinActive statements don't work for this code is because this is checking for physical button states and manually implementing hotkey behaviours, vs. using the built-in AutoHotkey hotkey definitions.

I would imagine it's because the class allows more extended behavior mapping (one to two keys, etc)--the original code may be a bit overly-complicated but it mostly works right, so best to leave well enough alone if possible and not re-write it if that's not necessary.

Where To Try and Mod

To that end I would try to mod the run() loop.

I can't test this code easily myself, but if all you want is to "fix it", try placing a conditional in front of the this.processKeys() call. You could put any kind of conditional here:

run() {
    while(!this.abort) {
        If WinActive("ahk_exe bio4.exe")  ; <-- Try a conditional here
            this.processKeys()
        Sleep, 1
    }
}

Side Note #1: If the If WinActive() statement shown below doesn't do the trick, check the title name and/or class or whatnot using the Window Spy program (open from the Tray Icon context menu of any AutoHotkey script), to see what the title, class, exe is for an active window. Start Window Spy then start/activate your program of interest and see what Window Spy displays (and you can 'pause' the display with [Windows Key]+'a' if needed).

Side Note #2: If you do decide to use a plain window title vs. an ahk_exe designation, be aware of SetTitleMatchMode.

Side Note #3: You can also use logic combinations at this point to do any kind of multi-process checks you want, if that were ever needed.

;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")

Side Note #4: You can also use WinExist() if you want to check for window presence, vs. window active. It doesn't sound like this is the case in your example, but wanted to make you aware of this function also.

; 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")
answered on Super User Oct 4, 2019 by JJohnston2
0

I found another script here to minimize and maximize the game. Adding joy12::Pause at the end of the original script above solved the issue since my Joy12 is tasked with minimizing/maximizing the bio4.exe window in another running script:

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

so having these two scripts using the same toggle effectively pauses the script while also minimizing the game.

I would still love to know how to pause a script while the game window is minimized without the workaround.

answered on Super User Oct 3, 2019 by Kalamalka Kid • edited Oct 4, 2019 by Kalamalka Kid

User contributions licensed under CC BY-SA 3.0