Script to modify Windows key, only works after pressing twice.

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
Frosty1234
Posts: 3
Joined: 28 May 2023, 03:18

Script to modify Windows key, only works after pressing twice.

Post by Frosty1234 » 28 May 2023, 03:27

Hey all, i have dug myself a deep hole with this script. It works! it works very nicely! Except almost.
Any help is appreciated, a working solution im willing to paypal bounty of 40 bucks.

The use case is that im using a windows start menu alternative named Flow Launcher. That program wants a Keybinding to open, but it cant be the windows key for whatever reason.
So currently its set to ctrl+space. However my muscle memory often still hits the windows key, and i want to fix that.

So i wrote a script that whenever i press the windows key, it will send ctrl+space.
But if i used the windows key to open file explorer (windows+e) or move windows around (windows+arrowright) i wanted that to still work.
I found that using KeyAwait created problems, so i switched to a manual form of KeyAwait using timers.

Right now the below code works, the only problem is that
- If i press Windows+E , it sends an E in whatever application im in (say an code editor)
- It doesnt work on the first keypress, only after the 2nd. (only Seems to be an issue with windows+e, not with windows+arrowright somehow?)

lwin down
e down
e up
lwin up
result=nothing, except an e typed in whatever app im in]

lwindown
e down
e up
e down
e up
lwin up
result = windows file explorer opens, but an e is left behind in the previous app


I know the below code is probably overengineerd to hell, but if someone could provide some help with a working solution
im willing to send you a bounty of 40 bucks via paypal.



Code: Select all

#InstallKeybdHook
DetectHiddenWindows, On
SetTitleMatchMode, 2

toggleState := false
currentWindowTitle := ""

ProcessExist(Name){
	Process,Exist,%Name%
	return Errorlevel
}

debugToFile(variable) {
	FileAppend, % variable "`n", debug.log
}

keys := "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,0,1,2,3,4,5,6,7,8,9,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,Enter,Space,Tab,Shift,Control,Alt,Escape,Up,Down,Left,Right,Backspace,Delete,Insert,Home,End,PageUp,PageDown,PrintScreen,CapsLock,NumLock,ScrollLock,Pause,Divide,Multiply,Subtract,Add,Enter,Numpad0,Numpad1,Numpad2,Numpad3,Numpad4,Numpad5,Numpad6,Numpad7,Numpad8,Numpad9"

LWin::
	debugToFile("LWin pressed")
	;;Check if we have overflow running, if we do not then just make Lwin behave normally
	if ProcessExist("Flow.Launcher.exe")
	{
		; Start a timer to keep track of how long the windows Key is being held down.
		AnyKeyPressed := false
		PressedKey := "" ; Initialize to empty string
		Duration=0
		Loop
		{
			;Increment the time
			Duration ++

			debugToFile(Duration)
			;;Check if another key is being pressed in combination with the windows key, if so stop the timer
			Loop, Parse, keys, `, ; Loop over keys
			{
				if (A_LoopField != "LWin") && GetKeyState(A_LoopField, "P") ; exclude LWin key
				{
					debugToFile(A_LoopField . " key pressed, stop the 'LWin' timer")
					AnyKeyPressed := true
					PressedKey := A_LoopField ; Store the pressed key
					;;break the subloop
					Break
				}
			}

			;;Break the main loop if another key is pressed in combination with the windows key
			If AnyKeyPressed
			{
				debugToFile("A key was pressed together with the windows key")
				Break
			}

			;;If the windows key is released, stop the timer
			If !GetKeyState("LWin","P")
			{
				debugToFile("LWin key released, stopping the timer, you probably want to open the windows menu")
				Break
			}

			;;This makes the loop check itself every 10 miliseconds
			Sleep, 10
		}

		debugToFile("State of Anykeypressed: " . AnyKeyPressed)
		debugToFile("State of Duration: " . Duration)
		If (Duration <= 20 && AnyKeyPressed == 0)
		{
			debugToFile("Opening overflow search")
			Send ^{space}
		}
		else if (AnyKeyPressed == 1)
		{
			debugToFile("LWin key held for more than 200 milliseconds. duration:[" . Duration . "] anykeypressed: [" . AnyKeyPressed . "] pressedKey: [" . PressedKey . "]")
			; if another key is pressed or LWin is held down for more than 2000 milliseconds, the Windows key willSorry for the abrupt cut-off. Here's the remaining part of the script:

			lastPressedKeyWePressed := "" ; Initialize a variable to remember the last key we pressedeE

			Duration=0
			Loop
			{
				; Check if ANykey is pressed, if so
				Loop, Parse, keys, `, ; Loop over keys
				{
					if (A_LoopField != "LWin") && GetKeyState(A_LoopField, "P") ; exclude LWin key
					{

						; Detect which Anykey was PressedKey
						PressedKey := A_LoopField ; Store the pressed key

						; press that key only if it wasn't the last key we pressed
						if (PressedKey != lastPressedKeyWePressed) {
							; function like normal
							SendInput , {LWin Down}
							debugToFile(A_LoopField . " alternate key pressed while holding down lwin")
							lastPressedKeyWePressed := PressedKey
							SendEvent , {%PressedKey% Down}
						}
					}
				}

				;; in this interval start waiting for the physical keystate to be released for that SPECIFIC key
				; if its released send a PressedKey up
				if (PressedKey != "" && !GetKeyState(PressedKey, "P")) ; If PressedKey is not empty and it's not pressed
				{
					debugToFile("User released the pressed key: [" . PressedKey . "]")
					SendEvent , {%PressedKey% Up}
					PressedKey := "" ; Reset PressedKey
				}

				; Also at the end wait for the keystae of Win to be released and send that up
				if (!GetKeyState("LWin","P")) ; If LWin key is not pressed
				{
					debugToFile("User released the LWin key")
					SendInput , {LWin Up}
					Break ; Exit the loop
				}

				Sleep 10
				Duration ++
			}
		}
		else {
			debugToFile("You probably want to open the windows menu, sending Lwinkeydown, and waiting for Lwin to be released, which is weird because our previous state said it was released.")
			Send, {LWin Down}
			; KeyWait, LWin
			Send, {LWin Up}
		}
	}
	else
	{
		; if the process doesn't exist, the Windows key will function like normal
		Send, {LWin Down}
		KeyWait, LWin
		Send, {LWin Up}
	}
return
[Mod edit: Moved topic to AHK v1 help, since this is not v2 code.]

User avatar
mikeyww
Posts: 26877
Joined: 09 Sep 2014, 18:38

Re: Script to modify Windows key, only works after pressing twice.

Post by mikeyww » 28 May 2023, 06:09

Welcome to this AutoHotkey forum!

One idea is below.

viewtopic.php?p=519984#p519984

User avatar
Frosty1234
Posts: 3
Joined: 28 May 2023, 03:18

Re: Script to modify Windows key, only works after pressing twice.

Post by Frosty1234 » 28 May 2023, 10:13

mikeyww wrote:
28 May 2023, 06:09
Welcome to this AutoHotkey forum!

One idea is below.

viewtopic.php?p=519984#p519984
Ah That does indeed work and almost fits all that i want it todo.
Would you know why my shift+LWin only works when there is a message box statement in there? (Works as in, it uses the Rwin to open the startmenu)
Once i remove the messagebox line, shift+Lwin no longer seems to to anything?

Code: Select all

+LWin::
	MsgBox, "Shift + LWin pressed to force open old start menu"
	Send, {RWin down}
	Send, {RWin up}
return

LWin Up::
	Send % A_PriorKey = "LWin" && A_TickCount - start < 400 ? "^ " : ""
	start := 0
Return

~LWin::
(!start) && start := A_TickCount
	Send {{Blind}{vkE8}}
Return

User avatar
mikeyww
Posts: 26877
Joined: 09 Sep 2014, 18:38

Re: Script to modify Windows key, only works after pressing twice.

Post by mikeyww » 28 May 2023, 10:32

I do not have an RWin key to test your script, but I noticed that you altered the final Send command.

You can examine this through the following demonstration.

Code: Select all

#Requires AutoHotkey v1.1.33
Send {e}
Send {{f}}

Code: Select all

; This script blocks the Start menu alone but leaves it enabled with other keys.
; Briefly tapping LWin sends CTRL-SPACE.
; The script uses a "time marker" to indicate when LWin was pressed.
; This enables the script to distinguish a short hold from a long hold.
#Requires AutoHotkey v1.1.33

~LWin Up::
If (A_PriorKey = "LWin"        ; If no keys were pressed after LWin,
 && A_TickCount - start < 400) ;  and key-up occurred shortly after key-down,
  Send ^{Space}                ;  then send CTRL-SPACE
start := 0                     ; Reset the time marker
Return

~LWin::
If !start                      ; If time marker is not set,
 start := A_TickCount          ;  then set it to the current "time", to mark the start of key-down
Send {Blind}{vkE8}             ; Disable Start menu activation while allowing use of LWin as a modifier
Return                         ; See https://www.autohotkey.com/docs/v1/lib/_MenuMaskKey.htm#Remarks

User avatar
Frosty1234
Posts: 3
Joined: 28 May 2023, 03:18

Re: Script to modify Windows key, only works after pressing twice.

Post by Frosty1234 » 28 May 2023, 12:08

Hmm I have corrected the code to use your latest example

Code: Select all

~+LWin::
	; MsgBox, "Shift + LWin pressed to force open old start menu"
	Send, {RWin down}
	Send, {RWin up}
return

~LWin Up::
	If (A_PriorKey = "LWin" ; If no keys were pressed after LWin,
		&& A_TickCount - start < 400) ;  and key-up occurred shortly after key-down,
		Send ^{Space} ;  then send CTRL-SPACE
	start := 0 ; Reset the time marker
Return

~LWin::
	If !start ; If time marker is not set,
		start := A_TickCount ;  then set it to the current "time", to mark the start of key-down
	Send {Blind}{vkE8} ; Disable Start menu activation while allowing use of LWin as a modifier
Return ; See https://www.autohotkey.com/docs/v1/lib/_MenuMaskKey.htm#Remarks

I still seem to have the same issue as before, that Rwin Down / Up seems todo nothing unless i insert a message box first (Maybe that makes it escape some context?)
- With or without ~ tilde doesnt seem to matter for shift+lwin
- Doesnt work if im in a browser, code editor or just Explorer. (So it isnt that something else is overriding the hotkey

Is there perhaps some other syntax, or ways to detect shift+lwin, or ways to send the Rwin command?

I understand that you cannot reproduce the issue since you do not have a RWin key on your keyboard,
but perhaps the solution kan be modified so that it can send a "clean" LWin via the Shift+Lwin key? All im trying todo is open the normal start menu again via Shift+Lwin.

It seems that even a script that ONLY contains this piece of code does not work

Code: Select all

+LWin::
	Send {LWin}
return

You have been of great help already and i thank you for your time!
I shall continue to fiddle around with it some more.

User avatar
mikeyww
Posts: 26877
Joined: 09 Sep 2014, 18:38

Re: Script to modify Windows key, only works after pressing twice.

Post by mikeyww » 28 May 2023, 17:00

The script that I posted does the following.
Whenever i press the windows key, it will send ctrl+space. But if i used the windows key to open file explorer (windows+e) or move windows around (windows+arrowright) i wanted that to still work.
I'm not sure what your script does, but good luck! :) :wave:

Post Reply

Return to “Ask for Help (v1)”