' Global hotkeys, allows you program to intercept key presses 
' even when your app is not focussed or in the background

$TYPECHECK ON

$IFNDEF __WIN32API
'get a hotkey ID
Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" (ByVal lpString As String) As Short
Declare Function GlobalDeleteAtom Lib "kernel32" Alias "GlobalDeleteAtom" (ByVal nAtom As Short) As Short

DECLARE FUNCTION RegisterHotKey LIB "USER32" ALIAS "RegisterHotKey" _
                 (hWnd AS LONG, ID AS LONG, fsModifiers AS LONG, vk AS LONG) AS LONG
DECLARE FUNCTION UnRegisterHotKey LIB "USER32" ALIAS "UnregisterHotKey" (hWnd AS LONG, ID AS LONG) AS LONG
DECLARE SUB SetForegroundWindow LIB "USER32" ALIAS "SetForegroundWindow" (HWnd AS LONG)

$DEFINE WM_HOTKEY   &H312
$DEFINE MOD_ALT     &H1
$DEFINE MOD_CTRL    &H2
$DEFINE MOD_SHFT    &H4
$DEFINE MOD_WIN     &H8

$ENDIF



DECLARE SUB FormWndProc (hWnd&, uMsg&, wParam&, lParam&)

Dim CtrlA_ID As Short
Dim CtrlB_ID As Short

CREATE Form AS QFORM
    Center
    Caption = "Global hotkeys"
    WndProc = FormWndProc
END CREATE


' use GlobalAddAtom to get a unique ID for the hotkey (as suggested by MSDN docs)
' our exe name and handle should do
DEFSTR atomName = STR$(Application.Handle)+Application.ExeName

'-- CTRL+A
CtrlA_ID = GlobalAddAtom(atomName)
IF CtrlA_ID <> 0 THEN           'we have a hotkey ID
    IF RegisterHotKey(Form.Handle, CtrlA_ID, MOD_CTRL, ASC("A")) = 0 THEN
        ShowMessage("Sorry, hot key CTRL+A already taken!")
    END IF
END IF

'-- CTRL+SHIFT+B
CtrlB_ID = GlobalAddAtom(atomName+"2")  'make another unique name
IF CtrlB_ID <> 0 THEN           'we have a hotkey ID
    IF RegisterHotKey(Form.Handle, CtrlB_ID, MOD_CTRL OR MOD_SHFT, ASC("B")) = 0 THEN
        ShowMessage("Sorry, hot key CTRL+SHIFT+B already taken!")
    END IF
END IF

IF (CtrlA_ID AND CtrlB_ID) = 0 THEN
    Showmessage "Unable to generate unique hotkey ID."
    Application.Terminate
END IF



Form.ShowModal

'program ends, clean up
UnRegisterHotKey(Form.Handle, CtrlA_ID)
GlobalDeleteAtom(CtrlA_ID)
UnRegisterHotKey(Form.Handle, CtrlB_ID)
GlobalDeleteAtom(CtrlB_ID)

SUB FormWndProc (hWnd&, uMsg&, wParam&, lParam&)
    IF uMsg& = WM_HOTKEY THEN
       SetForeGroundWindow(hWnd&)
        IF wParam& = CtrlA_ID THEN ShowMessage("Ctrl-A hit!")
        IF wParam& = CtrlB_ID THEN ShowMessage("Ctrl-B hit!")
    END IF
END SUB
