订阅表单中所有控件的鼠标事件

Gal*_*eck 6 mouse events winforms

如何轻松捕捉表单中所有控件的"鼠标按下"事件,而无需手动订阅每个事件?(C#)类似于"KeyPreview"功能,但适用于鼠标事件.

Mik*_*e J 1

解决方案1

订阅表单中每个控件上的每个事件无疑是最简单的方法,因为您只需使用 Ramesh 给出的代码。

然而,另一种技术涉及重写父控件(在本例中为包含所有控件的窗体)上的默认 Windows 消息处理方法(“WndProc”)。这有一个副作用,当鼠标光标移动到另一个父控件中包含的控件上时,您将无法检测到该副作用。

例如,您将无法检测鼠标光标何时位于TextBox中包含的 a 上TabControl。这是因为它将TabControl继续处理所有鼠标事件。

解决方案2

以下解决方案将克服尝试使用称为Windows 挂钩的技术检测鼠标光标位于哪个控件上时遇到的所有问题。

钩子本质上允许我们在将鼠标和键盘事件分派到具有焦点的窗口之前捕获它们。

这是一个示例:

  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);
   }
  }
Run Code Online (Sandbox Code Playgroud)