Input handler program

Just starting out? Need help? Post your questions and find answers here.
Seldon
Enthusiast
Enthusiast
Posts: 405
Joined: Fri Aug 22, 2003 7:12 am
Location: Italia

Input handler program

Post by Seldon »

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
milan1612
Addict
Addict
Posts: 894
Joined: Thu Apr 05, 2007 12:15 am
Location: Nuremberg, Germany
Contact:

Post by milan1612 »

Hi,

Code: Select all

Repeat 
  Delay(1)
  ;your code...
  If GetAsyncKeyState_(#VK_F12) : Break : EndIf
ForEver
End
Regards, milan1612
Windows 7 & PureBasic 4.4
Derek
Addict
Addict
Posts: 2354
Joined: Wed Apr 07, 2004 12:51 am
Location: England

Post by Derek »

To perform the code when a key is pressed you need...

Code: Select all

Repeat
Repeat 
  Delay(1)
  If GetAsyncKeyState_(#VK_F12) : Break : EndIf
ForEver
;your code...
ForEver
Although I expect there are better ways. :)
milan1612
Addict
Addict
Posts: 894
Joined: Thu Apr 05, 2007 12:15 am
Location: Nuremberg, Germany
Contact:

Post by milan1612 »

Code: Select all

Repeat
  Delay(1)
  If GetAsyncKeyState_(#VK_F12)
    ;your code
  EndIf
ForEver
That's the better way :)
Windows 7 & PureBasic 4.4
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

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
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

Damn... trond beat me to it! :D
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

This is how I'd do it:

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
Compile this code to a Windows exe called Testhook.exe, place it in same folder as F12_Hook.dll:

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)
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.
BERESHEIT
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

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
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: Input handler program

Post by PB »

From MSDN regarding the F12 key:
Windows 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.
So always make sure you set the F12 key with Shift, Control or Alt to avoid
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
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

What does F12 have to do with a debugger?
Post Reply