Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Using hooks in VB?

Posted on 1998-04-01
19
Medium Priority
?
400 Views
Last Modified: 2012-06-21
Hi,

  Can anyone tell me how to use hooks in VB? I want to write a screen capture program and want to detect the key pressed message even when the user is using another application so that I know when to start screen capturing?
  It would be great if you can give me some sample codes...
  Thanks.

sun jian
0
Comment
Question by:sunjian061197
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
  • 3
  • +2
19 Comments
 
LVL 39

Expert Comment

by:abel
ID: 1460202
What key do you want to detect? Do you mean the PrtScrn? Or do you want a key, let's say F12, to activate your program/capture function? If your app is to run on that key, you can also set a hotkey for a shortcut. That hotkey will be systemwide.
Hooks are most easily implemented using the MsgHoo32.ocx from Mabry Software. It's freeware and can be used for distribution. With that control you can select a window (hwnd) and messages you want to hook and the _Message event will be called whenever a message is send to the window you specified. The problem is that you will need a systemwide hook, and as far as I know, it isn't possible using that ocx.
0
 
LVL 6

Expert Comment

by:clifABB
ID: 1460203
What version of VB are you using?
0
 

Author Comment

by:sunjian061197
ID: 1460204
Hi abel,

  I went to Mabry Software's website and found lots of controlls but I didn't find the MsgHoo32.ocx you mentioned. Can you tell me where I can find a copy of it?

To clifABB: I am using VB5.0
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 6

Expert Comment

by:clifABB
ID: 1460205
You're in luck with VB5, you don't have to use MsgHook or any of the 3rd party controls.  The AddressOf keyword will give you your hooking:

In a Bas Module (not form or class!) place the following code:

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

Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long

Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Public Const WH_KEYBOARD = 2

Type lParam
  LoVal As Long
  HiVal As Long
End Type

Global g_hHook As Long

Public Sub KeyboardProc(lCode As Long, wPar As Long, lPar As lParam)
  Dim lRes As Long
 
  lRes = CallNextHookEx(g_hHook, lCode, wPar, lPar)

  'Process key strokes here, wPar is the keycode
End Sub


Then when you want to start the hook, use this code:

  g_hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf KeyboardProc, 0&, App.ThreadID)


IMPORTANT!!! You MUST unhook before closing your app with the code:

  lRes = UnhookWindowsHookEx(g_hHook)

0
 

Author Comment

by:sunjian061197
ID: 1460206
Hi clifABB,

  I have tried your code and it compiles well. But when I run it, I got error message 'This program has performed an illegal operation and will be shut down...'. My code is very simple, and actually it just installs the hook function when the form is loaded. The code is below:

------module1---------
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

Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long

Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Public Const WH_KEYBOARD = 2

Type lParam
  LoVal As Long
  HiVal As Long
End Type

Global g_hHook As Long


Public Sub KeyboardProc(lCode As Long, wPar As Long, lPar As lParam)
  Dim lRes As Long
   
  lRes = CallNextHookEx(g_hHook, lCode, wPar, lPar)
  'Process key strokes here, wPar is the keycode
  'I didn't even do anything here!!!
End Sub
---------end of module1-------------

---------form1--------------
Private Sub Form_Load()
  g_hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf KeyboardProc, 0&, App.ThreadID)
End Sub

Private Sub Form_Unload(Cancel As Integer)
  lRes = UnhookWindowsHookEx(g_hHook)
End Sub
---------end of form1------------------

0
 
LVL 2

Expert Comment

by:marti
ID: 1460207
Hi sunjian,
May be you will not appreciate my answer but according to microsoft  Q177992 of KB it's not posible to create keybord hook using 'pure' VB. Please refer to Q177992 of KB(the end of the article)
0
 

Author Comment

by:sunjian061197
ID: 1460208
Hi marti:

  So what do you mean by 'pure' VB? If I have DLL calls in a VB program, is that considered as pure? If not, can u give me an example of some 'impure' VB? :-)
0
 
LVL 2

Expert Comment

by:marti
ID: 1460209
The above article means that for making a system keybord hook the KeyboardProc should be located in DLL not in OLE type DLL(which VB creates). But you can create App hook and the example is given in that article.
0
 
LVL 2

Expert Comment

by:marti
ID: 1460210
The above article means that for making a system keybord hook the KeyboardProc should be located in DLL not in OLE type DLL(which VB creates). But you can create App hook and the example is given in that article.
0
 
LVL 6

Expert Comment

by:clifABB
ID: 1460211
My apologies, I submitted the above code without complete testing.  
I was running NT and, although I didn't get any error, my test app just shut down.  I assumed it was because I was using NT (which requires WH_KEYBOARD_LL).

Spyworks 5 (standard) from Desaware has a hook control.  There web address is www.desaware.com
0
 
LVL 39

Expert Comment

by:abel
ID: 1460212
The answer of clifABB is good, but if you still want to try that msghoo32 thing, here's a link to it:
ftp://ftp.ism.ru/pub/drivers/sound/SB32_FM/RAD_AK1/WIN95/MSGHOO32.OC_

But I'm not 100% sure it's the right one. If not, I can mail you the right one if you want. It's strange that Mabry doesn't supply the ocx anymore and that it's hard to find one on the net. A few months ago I remember that I found several good links and it was downloadable from Mabry as well.

Regards, Abel
0
 
LVL 7

Accepted Solution

by:
kamall earned 800 total points
ID: 1460213
'Message Hooking in VB w/o a custom control
'Hook messages from the system and other applications in VB5 'without the use of a custom control!


Private Const WM_SIZE = &H5
Private Const WM_MOVE = &H3
Private Const WM_WINDOWPOSCHANGED = &H47

Private Declare Function SetWindowLong Lib "user32" Alias
       "SetWindowLongA" (ByVal hWnd As
       Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Declare Function CallWindowProc Lib "user32" Alias
       "CallWindowProcA" (ByVal
       lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal
       wParam As Long,
       ByVal lParam As Long) As Long
       Private Const GWL_WNDPROC = (-4)
       Private OriginalWndProc As Long

Public Sub HookWindow(hWnd As Long)

       OriginalWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf
       MessageSpy)
End Sub


Public Sub FreeWindow(hWnd As Long)

       SetWindowLong hWnd, GWL_WNDPROC, OriginalWndProc
End Sub


Private Function MessageSpy(ByVal hWnd As Long, ByVal Msg As Long,

       ByVal wParam As
       Long, _
       ByVal lParam As Long) As Long
       '     'Test the message received...
       Select Case Msg
        Case WM_SIZE: Debug.Print "WM_Size message."
        Case WM_MOVE: Debug.Print "WM_Move message."
        Case WM_WINDOWPOSCHANGED: Debug.Print "WM_WINDOWPOSCHANGED
       message."
End Select

'     'Pass it on to the normal window processor.
MessageSpy = CallWindowProc(OriginalWndProc, hWnd, Msg, wParam,
lParam)
End Function


0
 

Author Comment

by:sunjian061197
ID: 1460214
Thanks, Kamall, for your answer. But I have two problems here:
1. How do I get the 'hwnd' of a specific window that I want to hook its message?
2. How do I get hooked to the system instead of an application?
0
 
LVL 39

Expert Comment

by:abel
ID: 1460215
A more correct link to the 16 and 32 bit versions of MsgHook from Mabry is found here:
http://www.arcatapet.com/vb.html
or more directly:
http://www.arcatapet.com/msghook.zip

These versions of the msghook controls appear to be the correct ones and the same as the original ones from Mabry.

You can use the api-function FindWindow to find a window to hook to. You can also use EnumWindows in conjunction with AddressOf and EnumWindowsProc to get all the windows at once (I mean one by one: you are enumerating) and then do with it what you like.

To create a SYSTEMWIDE hook, you cannot use SetWindowLong, you must use SetWindowHookEx, but to set that systemwide, you need a DLL. To set it to another window then your own, you must be very carefull. This is what Microsoft's comment is about that in the "Remarks" section of the function:
"The SetWindowLong function fails if the window specified by the hWnd parameter does not belong to the same process as the calling thread."
and:
"Calling SetWindowLong with the GWL_WNDPROC index creates a subclass of the window class used to create the window. An application should not subclass a window created by another process. The SetWindowLong function creates the window subclass by changing the window procedure associated with a particular window, causing Windows to call the new window procedure instead of the previous one. An application must pass any messages not processed by the new window procedure to the previous window procedure by calling CallWindowProc. This allows the application to create a chain of window procedures."

But it the Answer of kamall he already took care of that part.

I'm not sure if the MsgHoo32.ocx can be set to a systemwide hook. The hWnd property should probably be set to 0, but I never tested it.

Regards, Abel
0
 
LVL 39

Expert Comment

by:abel
ID: 1460216
BTW The SpyWorks 5.0 tool, mentioned by clifABB, is definitely able to set systemwide hooks via VB and has lots of demo-projects to explain the pitfalls you can encounter when setting a hook to detect key-presses. BUT the control is not freeware (msghook is).
0
 

Author Comment

by:sunjian061197
ID: 1460217
Thank you very much abel! I am going to start right away...

sun jian
0
 
LVL 39

Expert Comment

by:abel
ID: 1460218
Sun jian,
Not that I really mind, but accepting kamalls answer locks the question for me unless I pay 10 percent of the points (20 points in this case), which I did, to read your comment. If you think the thread is not yet to it's end (you may still encounter some problems) you better wait a while before accepting an answer and only post comments. Only to kamall the answer is free of points, which will prevent other experts to add their contributions to your thread.
But you probably know all that already. I hope the solution(s) work out well enough for you.

Regards, Abel
0
 
LVL 7

Expert Comment

by:kamall
ID: 1460219
sunjian,
Regarding your last two questions, abel has provided worthy information, and I actually have no more to add.

abel,
Thank you very much for your comments.
Regards to all.
0
 
LVL 39

Expert Comment

by:abel
ID: 1460220
One thing to add here (I thought I'd posted it already, but probably not, or on another thread). MsgHoo32.ocx CANNOT be used to set a systemwide hook. Just thought I had to let you know...

Regards, Abel
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Suggested Courses

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question