Bee Eee Blog

C# capture the mouse — Get a global hook on the mouse.

by brian on Jan.04, 2008, under .NET, GUI, c#, coding

I’m developing a component that is like the sidebar in the Visual C# Express (c). To get it to appear when the mouse is over the control isn’t a problem, however I soon discovered that using the MouseEnter and MouseLeave didn’t work. When I went over child controls the MouseLeave would be called and cause my sidebar to collapse.


Instead I had to create a global mouse hook so that no matter what control the mouse was over I could get a mouse event.

First was the code to import the hook function:

// create a mouse over eventstatic int WH_MOUSE_LL = 14;
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
static extern IntPtr GetModuleHandle(string moduleName);

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);

[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int UnhookWindowsHookEx(IntPtr hhook);

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, uint wParam, IntPtr lParam);
delegate IntPtr HookProc(int nCode, uint wParam, IntPtr lParam);

private HookProc hookProc;
private IntPtr hook;

Here is the event handler

IntPtr LowLevelMouseProc(int nCode, uint wParam, IntPtr lParam)
{
    // get the current mouse position
    Point p = Cursor.Position;

    // convert to client rectangle to screen position
    Rectangle r = RectangleToScreen(ClientRectangle);

    // check to see if mouse is within control bounds
    bool exp = (p.Y > r.Top && p.Y < r.Bottom && p.X > r.Left && p.X < r.Right);

    // adjust the expansion
    if (exp != Expanded)
         Expanded = exp;

    // Finished with this
    return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
}

Then the initialization code I put in the OnLoad event handler:

if (!DesignMode)
{
    hookProc = new HookProc(LowLevelMouseProc);
    hook = SetWindowsHookEx(WH_MOUSE_LL, hookProc, GetModuleHandle(null), 0);
}

And then code for closing in the OnHandleDestroyed event handler:

protected override void OnHandleDestroyed(EventArgs e)
{
        UnhookWindowsHookEx(hook);
        base.OnHandleDestroyed(e);
}

That should just about do it then. Now the UserControl can sense whether the mouse is overhead whether or not the mouse is over a child control.

No comments for this entry yet...

Leave a Reply

You must be logged in to post a comment.

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...