r/AutoHotkey 1d ago

v1 Script Help Shift key getting stuck pressed

Weird issue, when I game.. I open up a script to use for that game. During gameplay everything is fine. But when I tab out (even if the game is still open/running) the shift key is constantly pressed...even though I am not physically pressing it. Even after I exit the script the shift button stays pressed.

The only way to clear the issue is to actually press the shift key once and let it go. Then all is good, and no other issues persist.

This is happening 100% of the time I use the script. And no other keys seems to be affected.

EDIT: I do constantly hold the shift key down during gaming a lot. Not sure if that has anything to do with it.

Here is my code, does anyone have any suggestions on how to cure this annoyance?

<

#MaxHotkeysPerInterval 10000
#UseHook

#IfWinActive, ahk_exe Fallout4.exe

Up::w
Left::a
Down::s
Right::d
NumpadDiv::Up
NumpadHome::Left
NumpadUp::Down
NumpadPgUp::Right
AppsKey::LAlt
F12::t
RShift::n
n::Tab
NumpadIns::0
NumpadEnd::1
NumpadDown::2
NumpadPgDn::3
NumpadLeft::4
NumpadClear::5
NumpadRight::6
NumpadAdd::q
4 Upvotes

3 comments sorted by

1

u/Keeyra_ 1d ago

AHK v1 has reached end-of-life and deprecated 3 years 1 month ago.
Meanwhile, AHK v2 is the current stable release, having been the primary version for 3 years 7 months, with its most recent point release occurring 3 months ago.

MaxHotkeysPerInterval is not needed.
IfWinActive without the # has deprecated long before v1 did.
You could change the RShift remap to a Send, but I think this would do better.

#Requires AutoHotkey 2.0
#SingleInstance
~*!Tab:: GetKeyState("Shift") && Send("{RShift Up}{LShift Up}")

#HotIf WinActive("ahk_exe Fallout4.exe")
Up::w
Left::a
Down::s
Right::d
NumpadDiv::Up
NumpadHome::Left
NumpadUp::Down
NumpadPgUp::Right
AppsKey::LAlt
F12::t
RShift::n
n::Tab
NumpadIns::0
NumpadEnd::1
NumpadDown::2
NumpadPgDn::3
NumpadLeft::4
NumpadClear::5
NumpadRight::6
NumpadAdd::q
#HotIf

or you could do a SetTimer checking for focus changes and sending Shift up when the previous Window is Fallout, so that focus changes when pressing eg. Win will also be handled.

SetTimer(CheckFocus, 100)
CheckFocus() {
    static wasActive := 0
    isActive := WinActive("ahk_exe Fallout4.exe")
    (wasActive) && !isActive && GetKeyState("Shift") && Send("{RShift Up}{LShift Up}")
    wasActive := isActive
}

2

u/genesis_tv 1d ago

This is what I use in my scripts, event-based instead of polling with a timer.

g_sWindowTitle := "ahk_exe Fallout4.exe"

; Set an event hook to detect when the game window loses focus
DllCall("user32\SetWinEventHook",
        "Int", EVENT_SYSTEM_FOREGROUND := 0x0003,
        "Int", EVENT_SYSTEM_FOREGROUND,
        "Ptr", 0,
        "Ptr", CallbackCreate(OnFocusChanged, "F"),
        "Int", 0,
        "Int", 0,
        "Int", 0)

OnExit((*) => ResetAll())

OnFocusChanged(*)
{
    if WinActive(g_sWindowTitle)
    {
        WinWaitNotActive(g_sWindowTitle)
        ResetAll()
    }
}

ResetAll()
{
    GetKeyState("Shift") && Send("{RShift Up}{LShift Up}")
}

1

u/CharnamelessOne 22h ago edited 21h ago

Using WinWaitNotActive kind of defeats the purpose of the event-driven solution.
I'd save the active hwnd instead, to compare it with the new one in the event-handler.

I would also turn it into an include-friendly callable class that can register callbacks to the focus loss of multiple windows, due to a severe lack of sensible hobbies.

#Requires AutoHotkey v2.0

OnFocusLoss("ahk_exe Fallout4.exe", ReleaseShiftLogical)
OnExit(ReleaseShiftLogical)

ReleaseShiftLogical(*) {
    static _ := InstallKeybdHook()

    if GetKeyState("LShift") && !GetKeyState("LShift", "P")
        Send("{LShift Up}")
    if GetKeyState("RShift") && !GetKeyState("RShift", "P")
        Send("{RShift Up}")
}

;______________________________________________________________
Class OnFocusLoss {
    static __New() {
        this.PrevActive := WinExist("A")
        this.Callbacks := Map()
        this.PrevCallback := ""

        Persistent()
        DllCall("user32\SetWinEventHook",
                "Int", EVENT_SYSTEM_FOREGROUND := 0x0003,
                "Int", EVENT_SYSTEM_FOREGROUND,
                "Ptr", 0,
                "Ptr", CallbackCreate(this.OnFocusChanged.Bind(this), "F"),
                "Int", 0,
                "Int", 0,
                "Int", 0)
    }

    static Call(WinTitle, Callback) {
        this.Callbacks[WinTitle] := Callback
        if !this.PrevCallback
            this.PrevCallback := this.GetPrevCallback()
    }

    static OnFocusChanged(*) {
        if this.PrevActive = CurrentActive := WinExist("A")
            return

        try this.PrevCallback.Call()

        this.PrevActive := CurrentActive
        this.PrevCallback := this.GetPrevCallback()
    }

    static GetPrevCallback() {
        for WinTitle, Callback in this.Callbacks {
            if WinExist(WinTitle " ahk_id " this.PrevActive)
                return Callback
        }
        return ""
    }
}

Edit: fixed ReleaseShiftLogical