How to hook keyboard inputs globally in vb?


I want hook the keyboard inputs made to all applications currently running on the systemby using visual basic. I have some examples but they hook only current thread's inputs. And also it is necessary to put these inputs into text box. Thus, I will be able to behave according to specified command typed by the user.
I know the mains of the this process but it is a little difficult for me to code it. If you help me in solving this problem I will be preciate.

Thanks in advance
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

here's the code from my old program. i know it looks a little too messy... and i had extra stuff specified to my program that you might want to delete: (it detects keyboard input to other apps)

Option Explicit

Private Type POINTAPI
    x As Long
    y As Long
End Type
Public Type EVENTMSG
    message As Long
    paramL As Long
    paramH As Long
    time As Long
    hwnd As Long
End Type
Private Type MSG
    hwnd As Long
    message As Long
    wParam As Long
    lParam As Long
    time As Long
    pt As POINTAPI
End Type
Private Declare Function SetWindowsHookEx Lib "user32" _
    Alias "SetWindowsHookExA" _
    (ByVal idHook As Long, _
    ByVal lpfn As Long, _
    ByVal hmod As Long, _
    ByVal dwThreadId As Long) _
As Long
Private Declare Function CallNextHookEx Lib "user32" _
    (ByVal hHook As Long, _
    ByVal nCode As Long, _
    ByVal wParam As Long, _
    lParam As Any) _
As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" _
    (ByVal hHook As Long) _
As Long
Private Declare Sub CopyMemory Lib "kernel32" _
    Alias "RtlMoveMemory" _
    (Destination As Any, _
    Source As Any, _
    ByVal Length As Long)

Private Declare Function GetAsyncKeyState _
    Lib "user32" _
    (ByVal vKey As Long) _
As Integer

Private Const WH_JOURNALRECORD = 0
Private Const WH_GETMESSAGE = 3
Private Const WH_KEYBOARD = 2
Private Const WM_KEYDOWN = &H100
Private Const WM_KEYUP = &H101
Private Const WM_SYSKEYDOWN = &H104
Private Const WM_SYSKEYUP = &H105

Private hHook As Long

Public Sub StartHook()
    If hHook = 0 Then
        hHook = SetWindowsHookEx(WH_JOURNALRECORD, AddressOf HookProc, 0&, 0&)
    End If
End Sub

Public Sub EndHook()
    If hHook Then UnhookWindowsHookEx hHook
End Sub

Public Function HookProc(ByVal nCode As Long, ByVal wParam As Long, lParam As Long) As Long
    Dim iShift As Integer, iKey As Integer
    iShift = 0
    If GetAsyncKeyState(vbKeyControl) Then iShift = vbCtrlMask
    If GetAsyncKeyState(vbKeyMenu) Then iShift = iShift + vbAltMask
    If GetAsyncKeyState(vbKeyShift) Then iShift = iShift + vbShiftMask
    Dim winMsg As EVENTMSG
    CopyMemory winMsg, lParam, Len(winMsg)
    iKey = CInt(winMsg.paramL And &HFF)
    Select Case winMsg.message
            If iKey <> vbKeyControl And iKey <> vbKeyMenu And iKey <> vbKeyControl Then
                frmMain.KeyTyped iKey, iShift
            End If
    End Select
    HookProc = CallNextHookEx(hHook, nCode, wParam, lParam)
Debug.Print winMsg.message, iKey
End Function

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
monarch_ilhanAuthor Commented:
Hello again,
Thank you very much for you suggestions but unfortunatately it didnt work. May be there is a small trick which I couldnt see.
Please could you check it again and inform me soon??

And for motivating you, I am increasing its point from 100 to 150.

Best Regards
what part of it didn't work? did it give any error messages or it simply did not response? if you leave your email i can send my sample code to you.
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

oh, be sure you call StartHook() in Form_Load() event and EndHook() in Form_Unload() event, and your form should be named "frmMain" and has a public function whose signature is: KeyTyped(Byval KeyCode, Byval Shift)

(the code was originally written in win98, i'll check again to see if it works in win2k)
monarch_ilhanAuthor Commented:
hHook = SetWindowsHookEx(WH_JOURNALRECORD, AddressOf HookProc, 0&, 0&)

The return code of above function becomes Zero (0). So, StartHook process does not start. I did your suggestions but, since the SetWindowsHookEx does not start, it is unable to hook keyboard inputs. I think we may change the above function's parameters.

When I change tha functions as
hHook = SetWindowsHookEx(WH_JOURNALRECORD, AddressOf HookProc, App.hInstance , 0&) it gives a return code and it only hooks in my application not globally.

my email address is

I am looking forward to have your solution suggestions.

A problem with the code, is it's not in a DLL locally nor is it registered that way, so if say, someone hits the Windows key on the keyboard, that program goes dormant and stays that way (the hook is invalidated because the system can't find it after the process change).  I've run into the same situation, only means to fix that is to DLL the testing code and make the DLL locally registered and make sure the threadid is in the SetWindowsHookEx.  That way, any new threads that open up will also include that hook themselves (since a journalrecord is system wide, each thread will hook in if they don't have it present).

To hook the keyboard and mouse directly, you'd really need to write device drivers for them.

>hHook = SetWindowsHookEx(WH_JOURNALRECORD, AddressOf HookProc, App.hInstance , 0&) it gives a return code and it only hooks in my application not globally.

This is what I meant by the threadid being present, if this was in a registered DLL, all future opened threads would also open this hook for their usage and unhook it when they leave.
Sorry monarch_ilhan, the code works fine in win98se, even not in a dll, but not in win2k, not matter acsii or unicode version of the APIs is used...

FunkyMeister, I'll try to put the code in a dll and test in win2k again, thanks for the explanation. btw, since hooking is not recommended except for debugging, do you know of any other methods to hook keyboard/mouse using existing APIs?
Actually, hooking them may not be "recommended", but any mouse driver out there (and Internet keyboard driver as well) does it.  Thought they all use DLL's because each thread must be able to get AT the hook, otherwise it's invalidated and the code stops working (the hook gets "canned").  I've seen it get canned on a 98 machine outside of a dll but not inside of one.  And using a program that shows tasks and module usage, I see my dll listed on every last task (which is what you want).  But the downside is, if you're "late" in the stream, you may be getting sloppy seconds from the system (and may be too late down the list of listeners) and be able to do very little but go, "Oh, thats nice."

What are you hooking the inputs for?  Might help me understand the need.
Hi monarch_ilhan,
It appears that you have forgotten to close this question. I will ask Community Support to close it unless you finalize it within 7 days. I will ask a Community Support Moderator to:

    Split points between: imessvb and FunkyMeister

monarch_ilhan, if you think your question was not answered at all or if you need help, just post a new comment here; Community Support will help you.  DO NOT accept THIS comment as an answer.

EXPERTS: If you disagree with that recommendation, please post an explanatory comment.
DanRollins -- EE database cleanup volunteer
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.