Skip to content

Instantly share code, notes, and snippets.

@dawsontoth
Created February 11, 2011 20:42
Show Gist options
  • Save dawsontoth/822983 to your computer and use it in GitHub Desktop.
Save dawsontoth/822983 to your computer and use it in GitHub Desktop.
Adds some low level mouse hooks to a WPF app, turning any left click into a double click.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Dawson.Accessibility
{
/// <summary>
/// Interaction logic for MouseHooker.xaml
/// Derived from http://blogs.msdn.com/b/toub/archive/2006/05/03/589468.aspx
/// </summary>
public partial class MouseHooker
{
public MouseHooker()
{
_hookID = SetHook(_proc);
InitializeComponent();
}
private static readonly LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
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);
[Flags]
private enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 &&
MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
var hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
Console.WriteLine(@"Left clicked: " + hookStruct.pt.x + @", " + hookStruct.pt.y);
UnhookWindowsHookEx(_hookID);
mouse_event((int)(MouseEventFlags.LEFTDOWN), 0, 0, 0, 0);
mouse_event((int)(MouseEventFlags.LEFTUP), 0, 0, 0, 0);
_hookID = SetHook(_proc);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private const int WH_MOUSE_LL = 14;
[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")]
static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int 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);
}
}
@MarqueIV
Copy link

Hey! This looks like it may be exactly what I've been searching for. Any chance you can add some sample code showing how to use it? Trying to figure it out but I have a few questions. All I'm trying to do is see if a person clicked in the client area of any window on the system, hence the need for hooks.

@Naeemullah1
Copy link

The response from this code is very slow and laggy. How can this be made super fast?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment