How to set a hook in Visual Basic .NET

Article translations Article translations
Article ID: 319524 - View products that this article applies to.
This article was previously published under Q319524
For a Microsoft Visual C# version of this article, see 318804.
Expand all | Collapse all

On This Page

SUMMARY

This article describes how to set a hook that is specific to a thread and to a hook procedure. This article uses the mouse hook as an example.

You can use hooks to monitor certain types of events. You can associate these events with a specific thread or with all threads that are in the same desktop as a calling thread.

MORE INFORMATION

Set a mouse hook

To set a hook, call the SetWindowsHookEx function from the User32.dll file. This function installs an application-defined hook procedure in the hook chain that is associated with the hook.

To set a mouse hook and to monitor the mouse events, follow these steps:
  1. Start Microsoft Visual Studio .NET.
  2. On the File menu, point to New, and then click Project.
  3. In the New Project dialog box, click Visual Basic Projects under Project Types. Then, click Windows Application under Templates.
  4. In the Name box, type ThreadSpecificMouseHook. By default, a form that is named Form1 is created.
  5. At the beginning of the Form1.vb file, paste the following code.
    Imports System.Runtime.InteropServices
    Public Delegate Function CallBack( _
        ByVal nCode As Integer, _
        ByVal wParam As IntPtr, _
        ByVal lParam As IntPtr) As Integer
  6. In the Form1 class, paste the following code.
    'Declare the mouse hook constant.
    'For other hook types, obtain these values from Winuser.h in Microsoft SDK.
        Dim WH_MOUSE As Integer = 7
        Shared hHook As Integer = 0
    
        'Keep the reference so that the delegate is not garbage collected.
        Private hookproc As CallBack
    
        'Import for the SetWindowsHookEx function.
        <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
         Public Overloads Shared Function SetWindowsHookEx _
              (ByVal idHook As Integer, ByVal HookProc As CallBack, _
               ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
        End Function
    
        'Import for the CallNextHookEx function.
        <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
         Public Overloads Shared Function CallNextHookEx _
              (ByVal idHook As Integer, ByVal nCode As Integer, _
               ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
        End Function
        'Import for the UnhookWindowsHookEx function.
        <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
             Public Overloads Shared Function UnhookWindowsHookEx _
                  (ByVal idHook As Integer) As Boolean
        End Function
    
        'Point structure declaration.
        <StructLayout(LayoutKind.Sequential)> Public Structure Point
            Public x As Integer
            Public y As Integer
        End Structure
    
        'MouseHookStruct structure declaration.
        <StructLayout(LayoutKind.Sequential)> Public Structure MouseHookStruct
            Public pt As Point
            Public hwnd As Integer
            Public wHitTestCode As Integer
            Public dwExtraInfo As Integer
        End Structure
  7. Add a button to the form. Then, paste the following code in the button1_click procedure.
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
            If hHook.Equals(0) Then
                hookproc = AddressOf MouseHookProc
                hHook = SetWindowsHookEx(WH_MOUSE, _
                                         hookproc, _
                                         IntPtr.Zero, _
    AppDomain.CurrentDomain.GetCurrentThreadId())
                If hHook.Equals(0) Then
                    MsgBox("SetWindowsHookEx Failed")
                    Return
                Else
                    Button1.Text = "UnHook Windows Hook"
                End If
            Else
                Dim ret As Boolean = UnhookWindowsHookEx(hHook)
    
                If ret.Equals(False) Then
                    MsgBox("UnhookWindowsHookEx Failed")
                    Return
                Else
                    hHook = 0
                    Button1.Text = "Set Windows Hook"
                    Me.Text = "Mouse Hook"
                End If
            End If
    
        End Sub
  8. In the Form1 class, paste the following code for the MouseHookProc function.
        Public Shared Function MouseHookProc( _
        ByVal nCode As Integer, _
        ByVal wParam As IntPtr, _
        ByVal lParam As IntPtr) As Integer
    Dim MyMouseHookStruct As New MouseHookStruct()
    
            Dim ret As Integer
    
            If (nCode < 0) Then
                Return CallNextHookEx(hHook, nCode, wParam, lParam)
            End If
    
            MyMouseHookStruct = CType(Marshal.PtrToStructure(lParam, MyMouseHookStruct.GetType()), MouseHookStruct)
    
            Dim tempForm As Form
            tempForm = Form.ActiveForm()
    
            Dim strCaption As String
            strCaption = "x = " & MyMouseHookStruct.pt.x & " y = " & MyMouseHookStruct.pt.y
    
            tempForm.Text = strCaption
            Return CallNextHookEx(hHook, nCode, wParam, lParam)
    
        End Function
  9. Press F5 to run the project. Click the button on the form to set the hook. The pointer coordinates appear on the form caption bar when the pointer moves on the form.
  10. Click the button again to remove the hook.

Global hooks are not supported in the .NET Framework

You cannot implement global hooks in the .NET Framework. Low-level hooks run in the caller's process. These hooks do not require that code is injected into other processes. They can be implemented in managed code, but they might not continue to work. Because each input event must wait for the low-level hook to return before the hook is dispatched, slow hooks can significantly interfere with the responsiveness of the system. Windows silently removes any hook that takes too long to process. Because managed code cannot control at what time the garbage collector runs, there is no guarantee that the hook procedure will always return fast enough to avoid being removed.

REFERENCES

For more information about hooks, visit the following Microsoft Developer Network (MSDN) website:
http://msdn.microsoft.com/en-us/library/ms644959.aspx

Properties

Article ID: 319524 - Last Review: July 19, 2010 - Revision: 4.0
APPLIES TO
  • Microsoft .NET Framework 2.0
  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0
  • Microsoft Visual Basic 2005
  • Microsoft Visual Basic .NET 2003 Standard Edition
  • Microsoft Visual Basic .NET 2002 Standard Edition
Keywords: 
kbhowtomaster KB319524

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com