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:
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
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
}
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")
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.
User contributions licensed under CC BY-SA 3.0