Page 1 of 1

Prevent LWin opening Start Menu when pressed for too long, but keep modifying functionality

Posted: 07 May 2020, 08:21
by WalterRoberts
Hello, I am using the Windows Key for a lot of custom system wide hotkeys, so basically I am trying to achieve the following behavior: When pressed and released quickly I would still like the Start Menu to appear, but when pressed for a longer period of time I would like it to send nothing to avoid the Start Menu unintentionally popping up. This is especially for the times where I think I am going to perform a certain hotkey related with the Windows Logo Key but midway through I change my mind and thus depress LWin without having pressed any other key.
By looking at other posts I have come so far with my code, but there is one big problem:

Code: Select all

$LWin::
    startTime := A_TickCount ;record the time the key was pressed
    KeyWait, LWin, U ;wait for the key to be released
    keypressDuration := A_TickCount-startTime ;calculate the duration the key was pressed down
    if (keypressDuration > 200) ;if the key was pressed down for more than 200ms send >
    {
         Return
    }
    else ;if the key was pressed down for less than 200ms send LWin
    {
         Send {LWin} 
    }

return
At first glance this works as you would think, but it actually disables the entire modifier functionality of LWin which is of course pointless, so i.e. #d [to show desktop] stops working. Adding a tilde {~} at the beginning like so " $~LWin " does not work either as this results in long presses still sending the Start Menu once again.
I have absolutely no idea how I can achieve my desired behavior and am not even sure if I have taken the right approach to begin with. I am hoping someone here knows the solution to this problem as I am a bit lost.
Cheers!

Re: Prevent LWin opening Start Menu when pressed for too long, but keep modifying functionality

Posted: 07 May 2020, 15:51
by GEV
Try

Code: Select all

#NoEnv
#SingleInstance Force

; create an array/object of the keys you want combine with LWin:
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","1","2","3","4","5","6","7","8","9","0","F1","F2"] ;...

; create a hotkey once for each key in this object, using a For-Loop:
For each, key in Keys
{
	Hotkey, %key%, LWin_Key
	Hotkey, ~%key% Up, Up_Key 
}
return

LWin::
	startTime := A_TickCount
	KeyWait, LWin
	keypressDuration := A_TickCount-startTime
	If (keypressDuration > 300)
		return
	else
		Send {LWin Down}{LWin Up}
return

LWin_Key:
	If GetKeyState("LWin","P")
	{
		Send {Blind}{LWin Up}
		If (A_ThisHotkey = "F1")
			MsgBox, LWin+F1
		else
		If (A_ThisHotkey = "F2")
			MsgBox, LWin+F2
		else
			Send #{%A_ThisHotkey%}
	}
	else
		Send {%A_ThisHotkey%}
return

Up_Key:
return

Re: Prevent LWin opening Start Menu when pressed for too long, but keep modifying functionality

Posted: 07 May 2020, 16:33
by WalterRoberts
Thank you for helping me! Unfortunately I am a noob and your code currently exceeds my understanding of AHK.
I have tested your version and at first everything seemed to work great. Meanwhile I have encountered three bugs:

1) Win+Tab completely stopped working, also after adding "Tab" to the array.
2) When pressing for instance Win+D very rapidly the start menu pops up.
3) When right-clicking the AHK TrayIcon followed by a typed "R" for reload nothing happens. Oddly this is still working for literally any other context menu.

I was just curious if this was possible. It seems like it's more complicated than I thought.

Re: Prevent LWin opening Start Menu when pressed for too long, but keep modifying functionality

Posted: 07 May 2020, 17:17
by GEV
%A_ThisHotkey% has to be in curly braces in the Send command. I corrected it.

Re: Prevent LWin opening Start Menu when pressed for too long, but keep modifying functionality

Posted: 10 May 2020, 09:26
by WalterRoberts
Someone on Discord has found a working solution which involves simply pressing the {Esc} key, if {LWin} was the only key pressed and it was pressed for more than 2 seconds:

Code: Select all

#If !GetKeyState("LWin", "P")
~LWin::start := A_TickCount 
#If 


$LWin UP:: 
If ((A_TickCount - start) > 2000) && (A_Priorkey = "~LWin") 
     Send, {esc}
else 
    Send {LWin UP}
return

This is working great, but it seems the value entered in milliseconds does not get recognized at all. For testing purposes, I entered 6000 for 6 seconds and there is no difference whatsoever. The actual value is around 250ms (a quarter of a second) after which the start menu won't show anymore, which is incidentally exactly what I wanted it to be.

I am still curious though, what is the exact reason why the timing is not working as it should. Maybe someone here will know the answer to this.