How can i easily catch the "mouse down" events of all the controls in a form, without manually subscribing to each and every event? (C#) Something like the "KeyPreview" feature, but for the mouse events.
Other conttrols in the form cannot listen to the Mouse event handlers of the form. Because each control got its own mouse event listners.
But You can subscribe each controls mouse events to the forms mouse events
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MDown);
this.label1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MDown);
this.ListBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MDown);
this way you can have single handler for all the controls mouse events.
Cheers
Ramesh Vel
Solution 1
Subscribing to each and every event on every control within a form is certainly the most simplest approach to take, since you just use the code given by Ramesh.
However, another technique involves overriding the default windows message processing method ("WndProc") on the parent control - in this case, the form that contains all the controls. This has a side effect that you won't be able to detect when the mouse cursor moves over controls contained inside another parent control.
For example, you won't be able to detect when the mouse cursor is over a TextBox
that is contained inside a TabControl
. This is because the TabControl
will continue to process all mouse events.
Solution 2
The following solution will overcome all issues in attemptingto detect which control the mouse cursor is over using technique know as windows hooks.
Hooks essentially allow us to trap mouse and keyboard events even before they are dispatched to the window with focus.
Here's a sample:
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 }
[StructLayout(LayoutKind.Sequential)] public struct POINT { public int X; public int Y; }
[StructLayout(LayoutKind.Sequential)] public struct MouseHookStruct { public POINT pt; public int hwnd; public int hitTestCode; public int dwExtraInfo; }
[DllImport("user32.dll", SetLastError = true)] static extern int SetWindowsHookEx(HookType hook, HookProc callback, IntPtr hInstance, uint dwThreadId);
[DllImport("user32.dll", SetLastError= true)] static extern int CallNextHookEx(int hook, int code, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")] static extern int GetLastError();
[DllImport("kernel32.dll")] static extern int GetCurrentThreadId();
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam); private static int hHook;
public Form1() { InitializeComponent();
hHook = SetWindowsHookEx(HookType.WH_MOUSE, MouseHookProc, IntPtr.Zero, (uint)GetCurrentThreadId()); if (hHook == 0) MessageBox.Show("GetLastError: " + GetLastError()); }
private int MouseHookProc(int code, IntPtr wParam, IntPtr lParam) { //Marshall the data from the callback. MouseHookStruct mouseInfo = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
if (code < 0) { return CallNextHookEx(hHook, code, wParam, lParam); } else { //Create a string variable that shows the current mouse coordinates. String strCaption = "x = " + mouseInfo.pt.X.ToString("d") + " y = " + mouseInfo.pt.Y.ToString("d");
//You must get the active form because it is a static function.
Form tempForm = Form.ActiveForm;
Control c = Control.FromHandle((IntPtr)mouseInfo.hwnd);
if (c != null)
label1.Text = c.Name;
else
label1.Text = "Control not found";
//Set the caption of the form.
tempForm.Text = strCaption;
return CallNextHookEx(hHook, code, wParam, lParam);
} }