Welcome to MSDN Blogs Sign in | Join | Help

Low-Level Mouse Hook in C#

After my last post on implementing low-level keyboard hooks in C#, Soumitra asked if it was possible to implement a low-level mouse hook in C#, too.  Sure.  Here is an example that will print out the location of the mouse every time you press the left mouse button down:

class InterceptMouse
{
    private static LowLevelMouseProc _proc = HookCallback;
    private static IntPtr _hookID = IntPtr.Zero;

    public static void Main()
    {
        _hookID = SetHook(_proc);
        Application.Run();
        UnhookWindowsHookEx(_hookID);
    }

    private static IntPtr SetHook(LowLevelMouseProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_MOUSE_LL, proc,
                GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

    private static IntPtr HookCallback(
        int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 &&
            MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
        {
            MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
            Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

    private const int WH_MOUSE_LL = 14;

    private enum MouseMessages
    {
        WM_LBUTTONDOWN = 0x0201,
        WM_LBUTTONUP = 0x0202,
        WM_MOUSEMOVE = 0x0200,
        WM_MOUSEWHEEL = 0x020A,
        WM_RBUTTONDOWN = 0x0204,
        WM_RBUTTONUP = 0x0205
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct POINT
    {
        public int x;
        public int y;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct MSLLHOOKSTRUCT
    {
        public POINT pt;
        public uint mouseData;
        public uint flags;
        public uint time;
        public IntPtr dwExtraInfo;
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook,
        LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
        IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);
}
Published Wednesday, May 03, 2006 5:57 PM by toub
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

Friday, May 05, 2006 12:02 PM by Jason Haley

# Interesting Finds

Thursday, July 06, 2006 4:53 PM by Joe

# re: Low-Level Mouse Hook in C#

I am getting two compiler errors when attempting to run this code:

private static LowLevelMouseProc _proc = HookCallback; -> MouseHook.HookCallback(int, System.IntPtr, System.IntPtr)' referenced without parentheses

if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam) -> MouseHook.cs(86): Cannot convert type 'System.IntPtr' to 'MouseMessages'

Please email joe@jtasoftware.com if you see a way around this.  Thank you.  I am using VS 2003.

Thursday, July 06, 2006 5:02 PM by toub

# re: Low-Level Mouse Hook in C#

That code is using delegate inference, a feature in C# 2.0/Visual Studio 2005.  If you're using C# 1.x/VS2003, just change:
   HookCallback
to be:
   new LowLevelMouseProc(HookCallback)
Thursday, July 06, 2006 5:04 PM by toub

# re: Low-Level Mouse Hook in C#

Oh, and to fix the second issue if you're using a version of C# prior to 2.0, you can change that usage of wParam to be wParam.ToInt32(), and that should fix it.
Thursday, August 24, 2006 12:11 AM by Randy Smart

# re: Low-Level Mouse Hook in C#

Hi Stephen, does the Low Level Mouse hook code work with c# express edition.

I cant seem to get it to work.
I am new to c#.
Monday, August 28, 2006 1:56 PM by Stephen Toub

# re: Low-Level Mouse Hook in C#

Yes, it should.
Friday, December 29, 2006 2:01 PM by Murtaza

# re: Low-Level Mouse Hook in C#

Hello,

How can this class be used for controlling remote  System's desktop.

Regards,

Monday, February 05, 2007 4:01 PM by Jamie

# re: Low-Level Mouse Hook in C#

Would there be a way of controlling the mouse pointer with similar calls?  I've attempted to modify the values before the CallNextHookEx with no joy.

Jamie.

Thursday, February 15, 2007 7:47 AM by bob

# re: Low-Level Mouse Hook in C#

This code doesnt work with visual c# net2.0

Makes the application bug and crach

the CallBack Handler doesn't give anything =(

Thursday, March 01, 2007 5:54 AM by fido

# re: Low-Level Mouse Hook in C#

hello stephen

i want you to provide me with a code that enable's me to monitor all the processes on my PC using C#.

thank you.

Thursday, March 01, 2007 9:39 AM by toub

# re: Low-Level Mouse Hook in C#

You can use the System.Diagnostics.Process class to get information about processes on your machine.

Thursday, March 22, 2007 9:07 AM by Andy.Tao

# re: Low-Level Mouse Hook in C#

Why it it so slow when I click left button in the same application console window?

Tuesday, May 15, 2007 6:12 AM by Anish

# re: Low-Level Mouse Hook in C#

How can we change this code to generate mouse click and double click events?

I can generate a mouse click event on MouseDown event. But I dont know how to generate double click event.

Sunday, June 10, 2007 5:18 PM by Igor Gatis

# re: Low-Level Mouse Hook in C#

I'm using your code to launch an very simple app that allows to copy code snippets from anywhere. It works just fine until I right click on the app tray icon to access its menu. After that, it does fire keyboard events to my app anymore (like it was unhooked).

Is it expected? Or am I doing something that's causing this?

Sunday, June 10, 2007 5:20 PM by Igor Gatis

# re: Low-Level Mouse Hook in C#

Sorry, this was supposed to be posted in the keyboard post.

Thursday, June 14, 2007 10:14 AM by Edard Schoenherr

# re: Low-Level Mouse Hook in C#

I was wondering how to block mouse movements for a period of time and then allow them again.  I.E. if you were writing a script program that interfaces with an application, where the user can click on a dialog box that I create, which will in turn cause my script tto click on things and send keyboard events to a different application - so, once the script is clicking on the application, it would need the mouse movements to be ignored, so the user doesn't move the mouse out of the location that the script is trying to click on.  This would be a very quick off-on and I could possibly just use GetCursorPos - SetCursorPos, but I am trying to avoid the 1/1000000 chance that tthe user still move the mouse fst enough to break the script.

Monday, July 02, 2007 7:22 AM by Ferg

# re: Low-Level Mouse Hook in C#

Mouse hooks and performance?

I've implemented your mouse hook to get mouse events in a Word Add-In. It works great - the mouse messages are coming through loud and clear! One thing I've found though, is that the impact on performance is very noticeable (especially when selecting a large body of text.) Are you aware of any performance tweaks for windows hooks? I'm really only interested in WM_MOUSEMOVE messages as I want to simulate mouseovers, but of course these are the most verbose by a long shot.

Wednesday, July 04, 2007 6:06 PM by Fritz

# re: Low-Level Mouse Hook in C#

Interesting code, but i can't get it to work as i hoped...

Can someone give me a working code example for this mousehook;

Example, user clicks anywhere on the screen and a messagebox pops up indicating if left or right mousebutton was pressed.

Wednesday, July 11, 2007 4:22 PM by petros

# re: Low-Level Mouse Hook in C#

great stuff, great work, great example

how can i hook all windows messages? all i Know is that i have to use  WH_GETMESSAGE

Tuesday, July 31, 2007 6:39 PM by Calin

# re: Low-Level Mouse Hook in C#

Hi,

How can I get the current module handle in HookCallback?

Thank you,

Calin

Tuesday, August 14, 2007 5:16 AM by Stop Mouse Left Key Bringing form to top

# re: Low-Level Mouse Hook in C#

I need to stop my form coming to the top when left mouse button is pressed. In other words, stop, all together, this mouse event from arriving at the form.

Many thanks

Thursday, August 30, 2007 10:29 AM by Dan

# re: Low-Level Mouse Hook in C#

when i run this code on a win2k3 box over remote desktop the mouse movements are recorded correctly but the mouse down and up are recored as WM_MOUSEMOVE where as on vista it is recorded correctly as WM_LBUTTONDOWN and then WM_LBUTTONUP

Friday, August 31, 2007 5:17 AM by nobelo

# re: Low-Level Mouse Hook in C#

Hello,

if you click left slows down the mouse, application remains to hang!! Did you already see that?

Wednesday, January 02, 2008 10:15 PM by DotNetTestMonkey

# Low-Level Mouse Hook in C#

This example and the keyboard hooks example work fine.  Thanks for the info.

Friday, January 11, 2008 1:04 PM by Mike

# re: Low-Level Mouse Hook in C#

There is a post above about blocking mouse movement.  I'd like to do that too.  I need to block mouse movement onto one of the several display devices that make up the desktop.  Do I hook the mouse movements and then eat the messages?  Is there anyway to eat those messages after you've hooked them?

Thanks!

Monday, March 31, 2008 1:43 PM by xp

# re: Low-Level Mouse Hook in C#

Thanks for the code... excellent foundation for my sweet mouse-handling class.

Friday, April 04, 2008 1:27 AM by asnat

# re: Low-Level Mouse Hook in C#

great solution

i need some extra help on getting mouse selected text from any application to my clipboard

i would appriciate any help on the subject

thanks asnat

Monday, April 14, 2008 2:49 AM by Manoj K

# re: Low-Level Mouse Hook in C#

I have implemented mouse hook to get mouse events in a Word Add-In using above code. It is working fine but sometimes I am getting below Exception:

"AccessViolationException :

Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

Whenever this exception occers word stops responding and here I'm not able kill the exception.

any idea or clues?

Monday, April 14, 2008 4:13 AM by Nasir Khan

# re: Low-Level Mouse Hook in C#

Wanted to add something to what Manoj K is trying to address.

We have given Smart UI effect to custom schema part/content control in Word Content area.

Whenever we try to bring Smart UI for few  content control/custom elements, we get the AccessViolationException.

Message : "AccessViolationException : Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

Due to this exception the Tread for SetWindowsHookEx method is alos going into halt state. It is crashing word.

Thanks and Regards,

Nasir Khan

Thursday, May 15, 2008 2:17 AM by minhvc

# re: Low-Level Mouse Hook in C# : Slowdown GUI

After set Low-Level Mouse, mouse click on button Minimize or Maximinze, the GUI sized more slow (delay serveral)than UnHook, how to seedup?

Monday, June 09, 2008 6:48 PM by stojakovich

# re: Low-Level Mouse Hook in C#

how about hooking api of CreateProcess or ExecuteProcess?

Thanks,

Earl

Monday, July 07, 2008 8:00 AM by yosi

# re: Low-Level Mouse Hook in C#

i need a code to add a new item to the pop-up menu of the computer(right click on the mouse)

thanks.

Friday, August 01, 2008 5:12 AM by fazal

# re: Low-Level Mouse Hook in C#

man can you give me a solution to hook keyboard from a windows service.

Saturday, August 09, 2008 1:14 AM by Chris

# re: Low-Level Mouse Hook in C#

Well, it seems that the problem is not with the windows service itself.  I've read many have managed to circumvent that issue by checking "Allow Desktop Interaction" or something along those lines.  The problem I'm having, however, is that Vista won't really allow this.  So, I'm looking for a similar solution that works under vista as a windows service...

Friday, August 29, 2008 3:11 PM by Nate

# re: Low-Level Mouse Hook in C#

I wrote code that works perfect but as soon as I run it under a windows service the event never gets handled. My service runs under Local System and has Allow interact with desktop checked; I have also tried unchecking it with no results. I can step through the code and make sure the handler gets resgitered with += and I can see the line of code being executed but no keystrokes get logged. Has anyone been able to run keyboard hook under a windows ervice?. Is as if the event never gets fired. Please help!

Thursday, October 30, 2008 9:11 AM by Donovan

# re: Low-Level Mouse Hook in C#

Can this be altered to capture the filename of the process that raised the event?

Thursday, October 30, 2008 10:05 AM by Donovan

# re: Low-Level Mouse Hook in C#

Sorry, allow me to be more clear. I am looking to write an app to help with a spyware problem. Basically, when i click on that "You have a serious virus" balloon, i want to get the filename of the program running it. Then go into safemode and wipe it from the system32 folder. It will bridge the cap between what i can clearly see is spyware, and what avg does not yet see as spyware.

Many thanks!

Saturday, January 03, 2009 11:19 AM by Benjamin

# re: Low-Level Mouse Hook in C#

Hi Stephen Toub

Thank you very much for these interceptors. They practically saved my ass :)

Wednesday, March 04, 2009 9:05 AM by contactsrinivasan81

# re: Low-Level Mouse Hook in C#

Toub,

      we used ur low level mouse hook code and it works fine.In our case when ever user right click and select the copy option we need to do some action.how to find it.Is there any way to find it.Please help us.

Thanks in advance.

Saturday, April 04, 2009 3:45 AM by sunitha

# re: Low-Level Mouse Hook in C#

how to dispose mouse hook on application close

Tuesday, June 16, 2009 9:37 AM by Prasad

# re: Low-Level Mouse Hook in C#

Please explain How to raise Mouce click hook

Thursday, June 18, 2009 4:39 AM by Stephen Toub Low Level Mouse Hook in C | pool toys

# Stephen Toub Low Level Mouse Hook in C | pool toys

Tuesday, June 30, 2009 12:36 AM by Hos

# re: Low-Level Mouse Hook in C#

Hi,

I was trying to run this piece of code on Windows Mobile 6.1.

I replaced

using (ProcessModule curModule = curProcess.MainModule) ...

with

return SetWindowsHookEx(WH_MOUSE_LL, proc, curProcess.MainWindowHandle, 0);

I got it compiling but it does not seem to be functioning. Any ideas?

Thanks.

Monday, October 05, 2009 1:47 AM by Nameless

# re: Low-Level Mouse Hook in C#

IF you want more help for C# development ...

Visit this ...

http://mycsharpdotnet.blogspot.com/

Wednesday, October 14, 2009 10:25 PM by Гносис

# re: Low-Level Mouse Hook in C#

How to eat key strokes?

For example, i need to clear key buffer, to avoid print space, when i press WINKEY + SPACE, and perform some operation...

private static IntPtr HookCallback(

   int nCode, IntPtr wParam, IntPtr lParam)

{

  int vkCode = Marshal.ReadInt32(lParam);

  if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)

  {

    if ((Keys)vkCode == Keys.LWin ||

        (Keys)vkCode == Keys.RWin)

    {

      WinKeyStillPressed = true;

    }

  }

  if (nCode >= 0 && wParam == (IntPtr)WM_KEYUP)

 {

   if ((Keys)vkCode == Keys.LWin ||

       (Keys)vkCode == Keys.RWin)

   { //clear flag

     WinKeyStillPressed = false;

   }

   if (WinKeyStillPressed)

   {

     if ((Keys)vkCode == Keys.Space)

     {

       PlayPauseInner(); // My Styff

       return CallNextHookEx((IntPtr)0, 0, wParam, (IntPtr)0); // does not eat key strokes

       return (IntPtr)0; // does not eat key strokes

       return (IntPtr)1; // does not eat key strokes

     }

     if ((Keys)vkCode == Keys.Left)

     {

       PlayRewind(); // My Styff

     }

     if ((Keys)vkCode == Keys.Right)

     {

       PlayForward(); // My Styff

     }

   }

 }

 return CallNextHookEx((IntPtr)0, 0, wParam, (IntPtr)0);

}

Wednesday, December 16, 2009 5:29 PM by Some Schmoe

# re: Low-Level Mouse Hook in C#

Code like this is great... THANK YOU.

However, it would be nice if you included the 'using' clauses for those of us that don't know the ins and outs of every piece of the .NET framework...

Looks like this needs these:

using System;

using System.Collections.Generic;

using System.Runtime.InteropServices;

Feel free to correct me if I guessed wrong :)

Tuesday, December 22, 2009 7:11 PM by Bloodyaugust

# re: Low-Level Mouse Hook in C#

Also, it needs:

using System.Diagnostics;

:)

Wednesday, January 20, 2010 9:51 AM by lqx

# re: Low-Level Mouse Hook in C#

I want to know, when i selected some files with mouse, how to get the file names in the other application??

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker