Input handler program
Input handler program
I'd like to make a program that performs a certain task when I press a key (for example F12). Which is the best way to achieve this ? To open an invisible window with a normal event handling loop ? Does Windows offer a better method ? I'm thinking of something like an input-handler in AmigaOS. Thank you in advance
Hi,
Regards, milan1612
Code: Select all
Repeat
Delay(1)
;your code...
If GetAsyncKeyState_(#VK_F12) : Break : EndIf
ForEver
End
Windows 7 & PureBasic 4.4
To perform the code when a key is pressed you need...
Although I expect there are better ways. 
Code: Select all
Repeat
Repeat
Delay(1)
If GetAsyncKeyState_(#VK_F12) : Break : EndIf
ForEver
;your code...
ForEver

Code: Select all
Repeat
Delay(1)
If GetAsyncKeyState_(#VK_F12)
;your code
EndIf
ForEver

Windows 7 & PureBasic 4.4
This is the correct way:
Code: Select all
Procedure HotKey(Key, Modifiers)
Static ID
If RegisterHotKey_(0, ID, Modifiers, Key) = 0
ProcedureReturn -1
EndIf
ID + 1
ProcedureReturn ID
EndProcedure
Msg.MSG
hk = HotKey(#VK_F1, 0)
Repeat
GetMessage_(@Msg, 0, 0, 0)
If MSG\message = #WM_HOTKEY
Debug "press"
Break
EndIf
ForEver
- Rook Zimbabwe
- Addict
- Posts: 4322
- Joined: Tue Jan 02, 2007 8:16 pm
- Location: Cypress TX
- Contact:
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
This is how I'd do it:
Compile this code to a shared dll called F12_Hook.dll :
Compile this code to a Windows exe called Testhook.exe, place it in same folder as F12_Hook.dll:
Run the Testhook.exe program and press F12 from anywhere in the system, then press F11 to end the test session and unload the hook and test program.
Note that my dll is returning 1 when the key is trapped, which prevents the application having the keyboard focus from getting it at all. If you want the keypress not to lose its effect in other apps, return 0 instead and it will send your window the message while still allowing the other app to process the key normally.
Compile this code to a shared dll called F12_Hook.dll :
Code: Select all
#PerformActionMessage = #WM_APP + 1
#UnhookandEndMessage = #WM_APP + 2
Global KeyboardHook, CallingWindow
ProcedureDLL Attachprocess(instance)
CompilerIf Defined(KBDLLHOOKSTRUCT, #PB_Structure) = 0
Structure KBDLLHOOKSTRUCT
vkCode.l
scanCode.l
flags.l
time.l
dwExtraInfo.l
EndStructure
CompilerEndIf
EndProcedure
ProcedureDLL KeyboardProc(ncode,wparam,lparam)
*keycode.KBDLLHOOKSTRUCT=lparam
If wParam = #WM_KEYDOWN
Select *keycode\vkCode
Case #VK_F12
PostMessage_(CallingWindow, #PerformActionMessage, 0, 0)
ProcedureReturn 1
Case #VK_F11
PostMessage_(CallingWindow, #UnhookandEndMessage, 0, 0)
ProcedureReturn 1
EndSelect
EndIf
ProcedureReturn CallNextHookEx_( KeyboardHook, nCode, wParam, lParam )
EndProcedure
ProcedureDLL InitHook(hwnd, hook)
CallingWindow = hwnd
KeyboardHook = hook
EndProcedure
Code: Select all
;=====================================================================================================
; Offtopic: Sets up the timed messagebox for status display
;=====================================================================================================
OpenLibrary (0, "user32.dll")
Prototype MessageBoxTimed(hWnd.l, lpText.s,lpCaption.s, uType.l, wLanguageID.w, dwMilliseconds.l)
Global MessageBoxTimed.MessageBoxTimed = GetFunction(0,"MessageBoxTimeoutA")
;=====================================================================================================
; End of Offtopic section
;=====================================================================================================
#PerformActionMessage = #WM_APP + 1
#UnhookandEndMessage = #WM_APP + 2
OpenWindow(0,0,0,0,0,"Testhook",#PB_Window_BorderLess|#PB_Window_Invisible)
hooklib = OpenLibrary(0, "F12_Hook.dll")
If hooklib
keyproc=GetFunction(0, "KeyboardProc")
KeyboardHook=SetWindowsHookEx_(#WH_KEYBOARD_LL, keyproc, hooklib, 0)
CallFunction(0, "InitHook", WindowID(0), KeyboardHook)
MessageRequester("Notice:","Press F12 to perform action, F11 to unhook and unload this program",#MB_OK|#MB_ICONINFORMATION)
EndIf
Repeat
ev = WaitWindowEvent()
Select ev
Case #WM_CLOSE, #UnhookandEndMessage
MessageBoxTimed(0,"Unhooking and ending, thanks for testing!","Action:",#MB_OK|#MB_SYSTEMMODAL|#MB_ICONINFORMATION, 0, 1000)
Break
Case #PerformActionMessage
MessageBoxTimed(0,"Performing the keyboard hook action","Action:",#MB_OK|#MB_SYSTEMMODAL|#MB_ICONINFORMATION, 0, 1000)
EndSelect
ForEver
UnhookWindowsHookEx_(KeyboardHook)
Note that my dll is returning 1 when the key is trapped, which prevents the application having the keyboard focus from getting it at all. If you want the keypress not to lose its effect in other apps, return 0 instead and it will send your window the message while still allowing the other app to process the key normally.
BERESHEIT
Here is a little fix for your example, Trond. Your procedure was returning the incorrect ID.
Code: Select all
Procedure HotKey(Key, Modifiers)
Static ID
If RegisterHotKey_(0, ID, Modifiers, Key) = 0
ProcedureReturn -1
EndIf
ID+1
ProcedureReturn ID-1
EndProcedure
Re: Input handler program
From MSDN regarding the F12 key:
this potential problem. In fact, the RegisterHotKey API won't allow you to set
the F12 hotkey alone on those systems:
So always make sure you set the F12 key with Shift, Control or Alt to avoidWindows NT4 and Windows 2000/XP: The F12 key is reserved for use
by the debugger at all times, so it should not be registered as a hot key.
Even when you are not debugging an application, F12 is reserved in case
a kernel-mode debugger or a just-in-time debugger is resident.
this potential problem. In fact, the RegisterHotKey API won't allow you to set
the F12 hotkey alone on those systems:
Code: Select all
If OpenWindow(0,0,0,0,0,"test")
Debug RegisterHotKey_(WindowID(0),1,0,#VK_F12) ; Fails.
Debug RegisterHotKey_(WindowID(0),2,#MOD_SHIFT|#MOD_CONTROL,#VK_F12) ; Works.
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf