Seminko Posted July 24, 2024 Posted July 24, 2024 When I hold a key down I need it to fire a function which will run until I release the key. I tried using _IsPressed which works, but it continues sending the actual key I'm holding down which is no good. To prevent the key being sent I used HotKeySet. However, when I hold down the key set as a hotkey, it triggers the function continuously until I let go. So back to square one. Is there a way to achieve what I want? #include <Misc.au3> Local $hDLL = DllOpen("user32.dll") HotKeySet("{F8}", "Terminate") HotKeySet("=", "test") Func Terminate() DllClose($hDLL) Exit 0 EndFunc Func test() If _IsPressed("BB", $hDLL) Then ConsoleWrite("_IsPressed - '=' Key was pressed." & @CRLF) While _IsPressed("BB", $hDLL) ConsoleWrite(" '=' Key remains pressed." & @CRLF) Sleep(250) WEnd ConsoleWrite("_IsPressed - '=' Key was released." & @CRLF) EndIf Sleep(250) EndFunc While 1 Sleep(250) WEnd DllClose($hDLL)
Xenobiologist Posted July 24, 2024 Posted July 24, 2024 (edited) What is it, that you are trying to achieve? I changed to key 1 for testing. #include <Misc.au3> Local $hDLL = DllOpen("user32.dll") HotKeySet("{F8}", "Terminate") Func Terminate() DllClose($hDLL) Exit 0 EndFunc Func test() If _IsPressed("31", $hDLL) Then ConsoleWrite("_IsPressed - '=' Key was pressed." & @CRLF) While _IsPressed("31", $hDLL) ConsoleWrite(" '=' Key remains pressed." & @CRLF) Sleep(250) WEnd ConsoleWrite("_IsPressed - '=' Key was released." & @CRLF) EndIf EndFunc While 1 Sleep(250) test() WEnd DllClose($hDLL) Edited July 24, 2024 by Xenobiologist Scripts & functions Organize Includes Let Scite organize the include files Yahtzee The game "Yahtzee" (Kniffel, DiceLion) LoginWrapper Secure scripts by adding a query (authentication) _RunOnlyOnThis UDF Make sure that a script can only be executed on ... (Windows / HD / ...) Internet-Café Server/Client Application Open CD, Start Browser, Lock remote client, etc. MultipleFuncsWithOneHotkey Start different funcs by hitting one hotkey different times
Seminko Posted July 24, 2024 Author Posted July 24, 2024 16 minutes ago, Xenobiologist said: What is it, that you are trying to achieve? I changed to key 1 for testing. #include <Misc.au3> Local $hDLL = DllOpen("user32.dll") HotKeySet("{F8}", "Terminate") Func Terminate() DllClose($hDLL) Exit 0 EndFunc Func test() If _IsPressed("31", $hDLL) Then ConsoleWrite("_IsPressed - '=' Key was pressed." & @CRLF) While _IsPressed("31", $hDLL) ConsoleWrite(" '=' Key remains pressed." & @CRLF) Sleep(250) WEnd ConsoleWrite("_IsPressed - '=' Key was released." & @CRLF) EndIf EndFunc While 1 Sleep(250) test() WEnd DllClose($hDLL) When you run the code, open up notepad, and press and hold 1, the cosole output is correct, but as you will see, AutoIt keeps sending 1 to the notepad. Which is no good, re my initial post: 25 minutes ago, Seminko said: I tried using _IsPressed which works, but it continues sending the actual key I'm holding down which is no good.
Andreik Posted July 24, 2024 Posted July 24, 2024 #include <Misc.au3> Local $hDLL = DllOpen("user32.dll") HotKeySet("{F8}", "Terminate") HotKeySet("=", "test") Func Terminate() DllClose($hDLL) Exit 0 EndFunc Func test() HotKeySet('=') ConsoleWrite("_IsPressed - '=' Key was pressed." & @CRLF) Do ConsoleWrite(" '=' Key remains pressed." & @CRLF) Sleep(250) Until Not _IsPressed('BB', $hDLL) ConsoleWrite("_IsPressed - '=' Key was released." & @CRLF) Sleep(250) HotKeySet("=", "test") EndFunc While 1 Sleep(250) WEnd DllClose($hDLL)
Seminko Posted July 24, 2024 Author Posted July 24, 2024 18 minutes ago, Andreik said: #include <Misc.au3> Local $hDLL = DllOpen("user32.dll") HotKeySet("{F8}", "Terminate") HotKeySet("=", "test") Func Terminate() DllClose($hDLL) Exit 0 EndFunc Func test() HotKeySet('=') ConsoleWrite("_IsPressed - '=' Key was pressed." & @CRLF) Do ConsoleWrite(" '=' Key remains pressed." & @CRLF) Sleep(250) Until Not _IsPressed('BB', $hDLL) ConsoleWrite("_IsPressed - '=' Key was released." & @CRLF) Sleep(250) HotKeySet("=", "test") EndFunc While 1 Sleep(250) WEnd DllClose($hDLL) Thanks for the reply. I tried just that before posting the thread. It suffers from the same unwanted behavior as Xenobiologist's asnwer. Since you remove the hotkey in the function, '=' is being sent during the function execution.
Solution Andreik Posted July 24, 2024 Solution Posted July 24, 2024 (edited) Well, if you want to suppress the key just use a keyboard hook: #include <WindowsConstants.au3> #include <WinAPISys.au3> #include <WinAPIConstants.au3> Global $bExit = False $hKeyboardProc = DllCallbackRegister('KeyboardProc', 'long', 'int;wparam;lparam') $hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($hKeyboardProc), _WinAPI_GetModuleHandle(0)) Do Sleep(10) Until $bExit _WinAPI_UnhookWindowsHookEx($hHook) DllCallbackFree($hKeyboardProc) Func KeyboardProc($nCode, $wParam, $lParam) If $nCode < 0 Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) Local $tKEYHOOKS = DllStructCreate('dword vkCode;dword scanCode;dword flags;dword time;ulong_ptr dwExtraInfo', $lParam) Switch $wParam Case $WM_KEYDOWN If $tKEYHOOKS.vkCode = 0x1B Then $bExit = True If $tKEYHOOKS.vkCode = 0xBB Then ConsoleWrite('= is pressed down' & @CRLF) Return 1 EndIf Case $WM_KEYUP If $tKEYHOOKS.vkCode = 0xBB Then ConsoleWrite('= is released' & @CRLF) Return 1 EndIf EndSwitch Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) EndFunc Edited July 24, 2024 by Andreik
Seminko Posted July 24, 2024 Author Posted July 24, 2024 1 hour ago, Andreik said: Well, if you want to suppress the key just use a keyboard hook: #include <WindowsConstants.au3> #include <WinAPISys.au3> #include <WinAPIConstants.au3> Global $bExit = False $hKeyboardProc = DllCallbackRegister('KeyboardProc', 'long', 'int;wparam;lparam') $hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($hKeyboardProc), _WinAPI_GetModuleHandle(0)) Do Sleep(10) Until $bExit _WinAPI_UnhookWindowsHookEx($hHook) DllCallbackFree($hKeyboardProc) Func KeyboardProc($nCode, $wParam, $lParam) Local Static $LastKey = Null If $nCode < 0 Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) Local $tKEYHOOKS = DllStructCreate('dword vkCode;dword scanCode;dword flags;dword time;ulong_ptr dwExtraInfo', $lParam) Switch $wParam Case $WM_KEYDOWN If $tKEYHOOKS.vkCode = 0x1B Then $bExit = True If $tKEYHOOKS.vkCode = 0xBB Then ConsoleWrite('= is pressed down' & @CRLF) Return 1 EndIf Case $WM_KEYUP If $tKEYHOOKS.vkCode = 0xBB Then ConsoleWrite('= is released' & @CRLF) Return 1 EndIf EndSwitch Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) EndFunc Great stuff! Thank you very much. I'm totally lost when it comes to DLL stuff, though. Would you be willing to comment the code a bit?
Andreik Posted July 24, 2024 Posted July 24, 2024 (edited) expandcollapse popup#include <WindowsConstants.au3> #include <WinAPISys.au3> #include <WinAPIConstants.au3> Global $KeyDown = False ; Register a hotkey to exit the program HotKeySet('{ESC}', 'Quit') ; Set a low level keyboard hook ; KeyboardProc it's a callback function that it's called when keyboard events occurs $hKeyboardProc = DllCallbackRegister('KeyboardProc', 'long', 'int;wparam;lparam') $hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($hKeyboardProc), _WinAPI_GetModuleHandle(0)) Do ; We process the messsage here because it's a good practice to return from ; the callback function as soon as possible and without using any blocking functions If $KeyDown Then ConsoleWrite('= was pressed' & @CRLF) Do ConsoleWrite('= is still pressed' & @CRLF) Sleep(10) Until Not $KeyDown ConsoleWrite('= was released' & @CRLF) EndIf Sleep(10) Until $bExit ; Unset the keyboard hook _WinAPI_UnhookWindowsHookEx($hHook) DllCallbackFree($hKeyboardProc) Func KeyboardProc($nCode, $wParam, $lParam) ; If nCode is less than zero just call the next hook procedure in the current hook chain If $nCode < 0 Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) ; Create a structure that will contain info about the keyboard event ; (lParam it's the pointer to the KBDLLHOOKSTRUCT structure) Local $tKEYHOOKS = DllStructCreate('dword vkCode;dword scanCode;dword flags;dword time;ulong_ptr dwExtraInfo', $lParam) ; wParam contains the identifier of the keyboard message Switch $wParam Case $WM_KEYDOWN ; When = key it's pressed ; set $KeyDown to true, so you don't have to process anything else in the callback function If $tKEYHOOKS.vkCode = 0xBB Then $KeyDown = True ; Return nonzero value to prevent the system from passing the ; message to the rest of the hook chain or the target window procedure Return 1 EndIf Case $WM_KEYUP ; When = key it's released ; set $KeyDown to false, so you don't have to process anything else in the callback function If $tKEYHOOKS.vkCode = 0xBB Then $KeyDown = False ; Return nonzero value to prevent the system from passing the ; message to the rest of the hook chain or the target window procedure Return 1 EndIf EndSwitch ; Call the next hook procedure in the current hook chain Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) EndFunc Func Quit() $bExit = True EndFunc You can read all this stuff in more details here, here and here. Edited July 24, 2024 by Andreik Seminko 1
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now