Click here to Skip to main content
6,292,426 members and growing! (10,005 online)
Email Password   helpLost your password?
Languages » C# » PInvoke     Beginner License: The Code Project Open License (CPOL)

Using Hooks from C#

By Don Kackman

An article on using Windows hooks from .NET, demonstrated with a MouseHook.
C#.NET 1.0, .NET 1.1, Win2K, WinXPVS.NET2003, Dev
Posted:22 Sep 2003
Updated:24 Sep 2003
Views:174,240
Bookmarked:111 times
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
24 votes for this article.
Popularity: 6.12 Rating: 4.43 out of 5

1
2 votes, 8.3%
2
1 vote, 4.2%
3
4 votes, 16.7%
4
17 votes, 70.8%
5

Introduction

MSDN's definition of a Windows hook is:

A hook is a point in the system message-handling mechanism where an application can install a subroutine to monitor the message traffic in the system and process certain types of messages before they reach the target window procedure.

While the .NET framework library has wrapped a significant portion of the Win32 API, there are numerous areas where we have to resort to P/Invoke to get at the functionality we need. Hooks are one of those areas. One likely reason for this is that hooks are pretty low-level things, which most programs rarely need. Another is that they are intimately tied to the message based nature of the Windows API itself. They would likely not be portable to any other operating system.

Windows hooks are implemented using callback functions. The callback procedure has a signature similar to the SendMessage API, so Windows hooks are very generic and are used to extend a number of different types of Windows message processing (see below).

This library provides a C# wrapper around the hook procedure that can be used from a System.Windows.Forms application. If you are trying to write highly portable code, I would stay away from Windows hooks (I've put all of the types in this library in the Microsoft.Win32 namespace, just to reinforce that point).

A MouseHook is a particular type of Windows hook that allows your code to be notified when any window on a particular thread gets a mouse message. This example uses a mouse hook to capture the button up messages for the two navigation buttons on 5-button mice. By using a mouse hook, the application's main Form can control navigation via the mouse, regardless of what child control currently has input focus. If you don't have a 5-button mouse, the demo isn't going to be very exciting for you, but the code demonstrates the basic concepts.

Background

Last summer there was an interesting article, by Dino Esposito, in MSDN magazine about implementing hooks in C#. "Hmmm", I thought to myself, "That's interesting, but why in the world would you ever want to do that?"

Well, the application I'm currently working on uses a web browser-like "forward/back" idiom, wherein the user can navigate between views, much like they would a series of web pages. Each view is a UserControl that gets loaded dynamically as the user moves around the application.

I for one can no longer live without the forward and back buttons on my five button mouse, so I thought I'd add mouse navigation to our app.

I quickly realized that this was not as simple as it first appeared. Because each view UserControl takes up the entire client area of the Form it is hosted on, the Form itself never gets any MouseUp events. I didn't want to deal with this in each and every view we create, so I had to come up with some way to handle the mouse button navigation in one place.

My first idea was to attach to each view's MouseUp event in the Form and do navigation from there. This quickly proved itself to be a kludge as each UserControl has its own child controls, and when they have focus, the UserControl doesn't get any mouse events either. To work, one would need to recursively attach all child control events to the same handler. Sounds messy, so scratch idea #1.

The next thought was to use the WM_PARENTNOTIFY message in the Form's WndProc. This looked promising at first and I had a proof of concept all whipped in no time. Then I thought to myself "The only mouse messages that spawn WM_PARENTNOTIFY are mouse down messages. I wonder when exactly a web browser navigates".

A quick test proved that web browsers navigate on mouse up, not mouse down (as, upon further reflection, one would expect). Scratch idea #2.

That lead me to the implementation I was hoping I wouldn't have to delve into: a MouseHook. I recalled implementing these in VB6 (in what seems like the dark ages now) and the havoc that they could wreck upon the VB6 IDE. Well it seemed like the only solution, so a quick Google search lead me back to Dino's article and after a quick look at the code, it began to appear that it wouldn't be as bad as I had feared.

Windows hooks are thread specific and this implementation uses the thread of the code that calls the Install method, which if you call it synchronously from a Form, will be the main UI thread. This is perfect for my navigation problem because, now I can have code in the Form that will respond to a forward/back mouse click, no matter what control has focus.

The code download includes and uses the LocalWindowHook class which Dino Esposito used to demonstrate the basics of Windows hooks in the MSDN sample code.

Using the code

There are two classes you can use to get at the MouseHook.

The first is a class, MouseHook that inherits directly from LocalWindowHook. Instantiate it, attach to its events, call Install(), and away you go. It will remove the hook when you Dispose it or when its finalizer runs.

private MouseHook hook = new MouseHook();

private void HookUp()
{
    this.hook.Install();
    this.hook.MouseUp += new MouseHookEventHandler( this.hook_MouseUp );
}

private void hook_MouseUp(object sender, MouseHookEventArgs e)
{
    // do some stuff with your exciting new mouse hook data

}

The second class is a System.ComponentModel.Component derived type that can be placed onto a design surface. In addition to making the MouseHook easier to use from the VS.NET IDE, the MouseHookComponent automatically installs the hook from the constructor that the Windows Forms Designer uses.

That means all you really need to do is drop it on a Form and attach to the events you are interested in.

Future enhancements

The are a number of different types of hooks supported by the Windows API. Dino Esposito's LocalWindowsHook class is completely generic and can be used to create any one of those hooks types:

public enum HookType : int
{
    WH_JOURNALRECORD = 0,
    WH_JOURNALPLAYBACK = 1,
    WH_KEYBOARD = 2,
    WH_GETMESSAGE = 3,
    WH_CALLWNDPROC = 4,
    WH_CBT = 5,
    WH_SYSMSGFILTER = 6,
    WH_MOUSE = 7,
    WH_HARDWARE = 8,
    WH_DEBUG = 9,
    WH_SHELL = 10,
    WH_FOREGROUNDIDLE = 11,
    WH_CALLWNDPROCRET = 12,
    WH_KEYBOARD_LL = 13,
    WH_MOUSE_LL = 14
}

The MouseHook class I've created here, is just one example of a derived class that abstracts the complexity of a particular kind of Windows hook. I've also included the CbtLocalHook class from the MSDN sample code.

As time goes on, I'd like to wrap some of the different types of hooks and add them to this library (WH_DEBUG looks especially interesting).

If anybody does an implementation a specific hook type, and is willing to share their code, drop me a note and I'll include it with this project.

References

History

  • 09/19/2003 - Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Don Kackman


Member
The first computer program I ever wrote was in BASIC on a TRS-80 Model I and looked something like:

10 PRINT Don is cool
20 GOTO 10

It only went downhill from there.
Occupation: Team Leader
Company: Starkey Laboratories
Location: United States United States

Other popular C# articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 63 (Total in Forum: 63) (Refresh)FirstPrevNext
GeneralHook ReadFile Pinmemberwei_future22:04 5 Jun '08  
Questionc# DoModal in handler doesn't return?!? Pinmemberjfstephe9:20 1 Nov '07  
GeneralVB.Net Pinmemberwestville_mike5:27 17 Oct '07  
GeneralCancel events? PinmemberJohnny J.23:40 23 Aug '07  
QuestionHook on Insert Smart Card into Smart Card Reader PinmemberIdeazzkds21:21 17 Dec '06  
QuestionHook for copy, cut, paste, delete PinmemberIoBebe8:33 26 Nov '06  
QuestionVisual Studio 2005 - AppDomain.GetCurrentThreadId PinmemberGBerrySqueeze12:38 30 May '06  
AnswerRe: Visual Studio 2005 - AppDomain.GetCurrentThreadId Pinmember_iTcHy_1:03 25 Mar '09  
QuestionkEYBOARD HOOKERS - Local Hooks in C# PinmemberAnnie Fernando22:01 2 Apr '06  
AnswerRe: kEYBOARD HOOKERS - Local Hooks in C# Pinmemberwarrior bard21:20 11 Mar '07  
GeneralBack Forward Button Pinmembermjorg7:42 26 Feb '06  
QuestionLocalWindowsHook Code analysis PinmemberRuth Ivimey-Cook14:21 19 Jan '06  
AnswerRe: LocalWindowsHook Code analysis PinmemberGBerrySqueeze12:07 30 May '06  
GeneralRe: LocalWindowsHook Code analysis [modified] PinmemberRuth Ivimey-Cook23:16 30 May '06  
GeneralHooking API - OpenProcess PinmemberVitoto17:47 2 Jan '06  
GeneralHook on Minimize PinmemberThomasManz3:38 13 Nov '05  
GeneralRe: Hook on Minimize PinmemberRadu Sebastian LAZIN4:09 2 May '06  
GeneralPrevent target form from receiving messages Pinmemberbanal12:22 15 Sep '05  
GeneralSingle Form Mouse Move PinmemberMBursill16:31 14 Aug '05  
GeneralRe: Single Form Mouse Move PinmemberDon Kackman15:11 6 Sep '05  
GeneralRe: Single Form Mouse Move PinmemberMBursill9:01 24 Sep '05  
GeneralRe: Single Form Mouse Move PinmemberDon Kackman9:48 24 Sep '05  
GeneralHow can I handle mouse click? PinsussAnonymous1:38 22 Jul '05  
Generalchanging mouse events Pinmemberveligeti8:54 28 Jun '05  
GeneralWH_JOURNALRECORD and WH_JOURNALPLAYBACK PinmemberDigital Logic Net22:18 7 Sep '04  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 24 Sep 2003
Editor: Smitha Vijayan
Copyright 2003 by Don Kackman
Everything else Copyright © CodeProject, 1999-2009
Web20 | Advertise on the Code Project