Jump to content

HotKeySet for WIN+SPACE does not get trapped


Recommended Posts

In my test code, I set up several hot key traps using HotHeySet() and some of them fail to be trapped.  These key combinations are trapped correctly if I use AutoHotKey to trap them.
 
The keys I'm trying to trap are:
The '+' key on the numpad
The '-' key on the numpad
The 'Enter' key on the numpad
WIN+SPACE
 
The help text for AutoIT says that it doesn't work for the Enter key on the numpad, but I need to find a way to trap it.
 
So I have 2 problems:
1) Why doesn't AutoIT trap the WIN+SPACE key combination?
 
2) How can I trap the numpad-Enter key (without also trapping the keyboard Enter key)?
 
Here is my AutoIT test code:
_Main()
Exit

Func _Main()
    Local $TrayToolTipHdr, $TrayTipStr

    HotKeySet("{ESC}       ", "Exit2")
    HotKeySet("{NumpadADD}", "NumpadADD") ; The '+' key on the numpad
    HotKeySet("{NumpadSUB}", "NumpadSUB") ; The '-' key on the numpad
    HotKeySet("{NumpadEnter}", "NumpadEnter") ; The 'Enter' key on the numpad
    HotKeySet("#" & "{SPACE}", "WinSpace") ; WIN+SPACE

    While (1)
        Sleep(100)
    WEnd
EndFunc   ;==>_Main

Func Exit2()
    Exit (2)
EndFunc   ;==>Exit2

Func NumpadADD()
    ConsoleWrite("+++: NumpadADD() entered" & @CRLF)
EndFunc   ;==>NumpadADD

Func NumpadSUB()
    ConsoleWrite("+++: NumpadSUB() entered" & @CRLF)
EndFunc   ;==>NumpadSUB

Func NumpadEnter()
    ConsoleWrite("+++: NumpadEnter() entered" & @CRLF)
EndFunc   ;==>NumpadEnter

Func WinSpace()
    ConsoleWrite("+++: WinSpace() entered" & @CRLF)
EndFunc   ;==>WinSpace
 
Here is my AutoHotKey code:
#NoEnv
SendMode Input

NumPadAdd::
     msgbox "NumPadAdd"
    return

NumpadSub::
     msgbox "NumpadSub"
    return

NumpadEnter::
     msgbox "NumpadEnter"
return

#space::
     msgbox "WinSpace"
return
 
Link to comment
Share on other sites

  • Moderators

AndyS01,

The syntax is wrong for the Win-Space line - this works for me:

HotKeySet("#{SPACE}", "WinSpace")
M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

I tried your syntax and it still didn't work for me.  It just briefly displays the rectangles of all of my windows.  (Try it without the scripts running.)

I'm running Windows 7 if that makes a difference.

As I said, the win+space trap works of AutoKotKey, so it's not an issue of remapping windows 7 keys.

With AutoHotKey, I can trap Windows 7 hotkeys without any problem (for instance, I was able to trap WIN+r, with AutoHotKey).  So it looks like an AuToIT limitation.  

How about trapping the numpad Enter key and WIN + Space keys with calls to _isPressed()?  I tried this but was not too successful.  I think I would have to go pretty deep to trap a keydown for the Win key,followed by a keydown for the Space key,. but i couldn't find a way to do it in AutoIt.

Link to comment
Share on other sites

As I said, the win+space trap works of AutoKotKey, so it's not an issue of remapping windows 7 keys.

 

With AutoHotKey, I can trap Windows 7 hotkeys without any problem (for instance, I was able to trap WIN+r, with AutoHotKey).  So it looks like an AuToIT limitation. 

 

Autoit was built this way, it will not re-map hotkey if the hotkey was already set by some other application, you can try it yourself: Map a hotkey, compile script, and start it, then compile 2nd script with same hotkey, but different function, and start it as well. You'll see that the hotkey will call function from script you started first.

 

How about trapping the numpad Enter key and WIN + Space keys with calls to _isPressed()?  I tried this but was not too successful.  I think I would have to go pretty deep to trap a keydown for the Win key,followed by a keydown for the Space key,. but i couldn't find a way to do it in AutoIt.

 

The reason why you can't map numpadEnter is because they're both sending code 13. There's no difference between those ENTER keys when receiving keyboard message. Unlike normal 1 and Numpad1, where normal1 is code: 49, and numpad1 is code: 97.

Left alt = 164

Right alt = 165

-----

left win = 91

right win = 92

-----

Left/Right ctrl = 162/163

-----

left/right shift = 160/161

----

etc....

But the enters are always 13 (ENTER and NUMPADENTER) which is why you cannot map NUMPADENTER, and must use only {ENTER} instead, which stands for code "13" and will hook both enters.

Edited by dragan
Link to comment
Share on other sites

Actually, the keyboard Enter key and the numpad Enter key emit different keycodes, and the keyboard driver translates them to the 13 hex code.  There's no way for AutoIT to get to the keycodes.

Anyway, thanks for your detailed help.  I can now back out of the rat hole I've been down while working this issue.  I'll just have to use AutoHotKey for these keyboard key traps.

Andy

Link to comment
Share on other sites

You might be able to detect Win+Space though (even with them mapped as hotkey by some other app), check the example in your helpfiles for function:

_WinAPI_SetWindowsHookEx

edit:
this works for both, Left WIN +Space and Right WIN +Space (and ESC = exit):

#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>
#include <Array.au3>


Global $isWinDown1 = False
Global $isWinDown2 = False

Global $hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam")
Global $hmod = _WinAPI_GetModuleHandle(0)
Global $hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($hStub_KeyProc), $hmod)

OnAutoItExitRegister("_Cleanup")

While 1
    Sleep(100)
WEnd

Func _Cleanup()
    _WinAPI_UnhookWindowsHookEx($hHook)
    DllCallbackFree($hStub_KeyProc)
EndFunc

Func _MessageWinSpace()
    ConsoleWrite('- you pressed WIN + SPACE, random code: ' & Random(1000, 9999, 1) & @CRLF)
EndFunc

Func _KeyProc($nCode, $wParam, $lParam)
    Local $tKEYHOOKS, $keyCode
    $tKEYHOOKS = DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam)
    If $nCode < 0 Then
        Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
    EndIf
    Switch $wParam
        Case $WM_KEYDOWN
            $keyCode = DllStructGetData($tKEYHOOKS, "vkCode")
            Switch $keyCode
                Case 32
                    If $isWinDown1 OR $isWinDown2 Then
                        _MessageWinSpace()
                    EndIf
                Case 91
                    $isWinDown1 = True
                Case 92
                    $isWinDown2 = True
                Case 27;esc
                    Exit
            EndSwitch
        Case $WM_KEYUP
            $keyCode = DllStructGetData($tKEYHOOKS, "vkCode")
            Switch $keyCode
                Case 91
                    $isWinDown1 = False
                Case 92
                    $isWinDown2 = False
            EndSwitch
    EndSwitch
    Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc


and if you want only one function at a time (Win+Space = calling function only one time, until next Win+Space):

#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>
#include <Array.au3>

Global $isWinDown1 = False
Global $isWinDown2 = False
Global $FunctionActive = False

Global $hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam")
Global $hmod = _WinAPI_GetModuleHandle(0)
Global $hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($hStub_KeyProc), $hmod)

OnAutoItExitRegister("_Cleanup")

While 1
    Sleep(100)
WEnd

Func _Cleanup()
    _WinAPI_UnhookWindowsHookEx($hHook)
    DllCallbackFree($hStub_KeyProc)
EndFunc

Func _MessageWinSpace()
    ConsoleWrite('- you pressed WIN + SPACE, random code: ' & Random(1000, 9999, 1) & @CRLF)
EndFunc

Func _KeyProc($nCode, $wParam, $lParam)
    Local $tKEYHOOKS, $keyCode
    $tKEYHOOKS = DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam)
    If $nCode < 0 Then
        Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
    EndIf
    Switch $wParam
        Case $WM_KEYDOWN
            $keyCode = DllStructGetData($tKEYHOOKS, "vkCode")
            Switch $keyCode
                Case 32
                    If ($isWinDown1 OR $isWinDown2) AND (NOT $FunctionActive) Then
                        $FunctionActive = True
                        _MessageWinSpace()
                    EndIf
                Case 91
                    $isWinDown1 = True
                Case 92
                    $isWinDown2 = True
                Case 27;esc
                    Exit
            EndSwitch
        Case $WM_KEYUP
            $keyCode = DllStructGetData($tKEYHOOKS, "vkCode")
            Switch $keyCode
                Case 32
                    $FunctionActive = False
                Case 91
                    $isWinDown1 = False
                Case 92
                    $isWinDown2 = False
            EndSwitch
    EndSwitch
    Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc
Edited by dragan
Link to comment
Share on other sites

I use the Win key for lots of keymappings in Win7, so I just disable the Microsoft ones altogether.

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer]
"NoWinKeys"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer]
"NoWinKeys"=dword:00000001
Link to comment
Share on other sites

BitOR($VK_LWIN, $VK_SPACE)

It's silly to begin with. Use $CK_...

 

_HotKey_Assign(BitOR($CK_WIN, $VK_SPACE), 'WinSpace')

Also, I didn't see any constants for NumpadADD, NumpadDIV, etc.

$VK_ADD, $VK_DIVIDE, etc.

Edited by Yashied
Link to comment
Share on other sites

dragan, I tried your script and it trapped WIN+SPACE, but passed it along to Windows, so I got the momentary aero display.  I would like to absorb it instead.
 
 
Yashied, That brought me very close.  Every key except the numpad Enter key. Is there a code for this?  I searched for 'enter' but got nothing useful.  Is it named something else?
 
Thank you both for getting involved in this.
 
Andy
 
Link to comment
Share on other sites

OK, I found an ugly solution.  The only difference between keyboard Enter and Numpad Enter appears to be that the 'extended-key' flag is set when the Numpad Enter key is pressed, and not set when the keyboard Enter key is pressed.  This flag is available in the __HK_Hook() function in HotKey.au3.  

To prove it, I made a small modification to HotKey.au3 to set an internal 'extended key' flag for every key press.  Then I added a function call to return the flag to the caller (_HotKey_GetExtKeyFlag()).  Then I made a _HotKey_Assign("{ENTER}", "myfunc".  In myfunc(), I made a call to the _HotKey_GetExtKeyFlag() function and if it returned a non-zero value, it meant the Enter key was the Numpad Enter key.  If not, it meant it was the keyboard Enter key.

Mods to HotKey.au3:

Global $___iLastExtendedKeyFlag = 0

.
.
.

Func __HK_Hook($iCode, $wParam, $lParam)

   If ($iCode > -1) And ($hkTb[0][1] = 0) And ($hkTb[0][3] = 0) Then

   Local $vkCode = DllStructGetData(DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam), 'vkCode')
   Local $flags = DllStructGetData(DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam), 'flags')
   $___iLastExtendedKeyFlag = BitAND($flags, $LLKHF_EXTENDED)
   Local $Return = False


.
.
.
 
func _HotKey_GetExtFlag()
    return($___iLastExtendedKeyFlag)
EndFunc
 

In my test script:

_HotKey_Assign($VK_RETURN, 'EnterKey')

Func EnterKey()
    If (_HotKey_GetExtFlag()) Then
        ConsoleWrite("+++: Numpad Enter key" & @CRLF)
    Else
        ConsoleWrite("+++: Keyboard Enter key" & @CRLF)
    EndIf
EndFunc   ;==>EnterKey

This proved the concept, but is not really good code.  For one thing, it means that while I'm only interested in the Numpad Enter key, I also get the keyboard Enter key, and there's no way to pass it along (saying that I didn't handle it).

A more robust method would be to add a flag you could pass to _HotKey_Assign() that says 'extended key only, or something like that.  I tried adding an additional element to the $hkTb array, but I got hung up in the code because all references to this array are numbers, not global constants.

Perhaps creating a new $VK_xxx definition might be another way to solve this.

I'm going to try to make it work without trapping the keyboard Enter key.  If you have any suggestions, I'd appreciate them.

Andy

 

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...