Mouse Hook del sistema

Fecha: 02/Dic/2004 (2-Diciembre-2004)
Autor: Alden Torres aldenml@yahoo.com

 


Hola, quería compartir con todos ustedes, una manera bien sencilla de escuchar todos los eventos del mouse, pero a nivel global. Comúnmente estamos acostumbrados a capturar los eventos del mouse dentro de un control en específico, pero cuando queremos extender esta funcionalidad a todo el sistema, tenemos que usar el mecanismo de hooks que nos brinda el sistema operativo. Para ello he usado la tecnología P/Invoke de .NET y marshaling.

A continuación las declaraciones necesarias:

private const int HC_ACTION = 0;
private const int WH_MOUSE_LL = 14;
private const int WM_MOUSEMOVE = 0x0200;

private delegate int HookProc(int nCode, int wParam, int lParam);

struct MSLLHOOKSTRUCT
{
	public POINT pt;
	public uint mouseData;
	public uint flags;
	public uint time;
	public IntPtr dwExtraInfo;
}

public struct POINT
{
	public int x;
	public int y;
}

[DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

[DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall, SetLastError = true)]
private static extern bool UnhookWindowsHookEx(IntPtr hHook);

[DllImport("user32.dll", EntryPoint="CallNextHookEx", CharSet=CharSet.Auto , SetLastError = true)]
public static extern int CallNextHookEx(int hHook, int nCode, int wParam, int lParam);

private IntPtr hHook = IntPtr.Zero;
int n = 0;

private int LowLevelMouseProc(int nCode, int wParam, int lParam)
{
	if (nCode <  0)
		return CallNextHookEx(0, nCode, wParam,lParam);
		
	if (n == 0)
	{
		if (nCode == HC_ACTION)
		{
			if (wParam == WM_MOUSEMOVE)
			{
				MSLLHOOKSTRUCT data = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(new IntPtr(lParam), typeof(MSLLHOOKSTRUCT));
				string s = "X: " + data.pt.x + "\tY:" + data.pt.y + "\r\n";
				textBoxOut.Text = s + textBoxOut.Text;
			}
		}
	}

	n = (n + 1) % 10;

	return CallNextHookEx(0, nCode, wParam, lParam);
}

Con todas estas declaraciones, solo nos queda ubicar lo siguiente en los eventos de la forma principal:

private void MainForm_Load(object sender, System.EventArgs e)
{
	hHook = SetWindowsHookEx(WH_MOUSE_LL, new HookProc(LowLevelMouseProc), Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
}

private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
	UnhookWindowsHookEx(hHook);
}

 


ir al índice

Fichero con el código de ejemplo: aldenml_MouseHook.zip - 7 KB