30

我的 WinForm C# 应用程序上的 MouseEvents 有问题。

我想在我的应用程序上获得所有鼠标点击,但我不想在每个子组件中都放置一个侦听器,也不使用 Windows 鼠标钩子。

在 Flash 上,我可以在舞台上放置一个侦听器来获取电影中的所有 MouseEvent。

C#上有这样的东西吗?一个全局鼠标监听器?


编辑:

我从 IMessageFilter 和使用的 Application.AddMessageFilter 创建这个类。

public class GlobalMouseHandler : IMessageFilter{

    private const int WM_LBUTTONDOWN = 0x201;

    public bool PreFilterMessage(ref Message m){
        if (m.Msg == WM_LBUTTONDOWN) {
            // Do stuffs
        }
        return false;
    }
}

并将这段代码放在需要监听全局点击的控件上:

GlobalMouseHandler globalClick = new GlobalMouseHandler();
Application.AddMessageFilter(globalClick);
4

4 回答 4

16

一种直接的方法是通过调用Application.AddMessageFilter和编写实现IMessageFilter接口的类来添加消息循环过滤器。

通过IMessageFilter.PreFilterMessage,您的班级可以看到通过应用程序消息循环的任何输入消息。PreFilterMessage还可以决定是否将这些消息传递给它们所指定的特定控件。

这种方法引入的一个复杂性是必须通过传递给您的PreFilterMessage方法的 Message 结构来处理 Windows 消息。这意味着参考 Win32 文档等WM\_LBUTTONDOWN, WM\_MOUSEMOVEWM\_LBUTTONUP而不是传统的MouseDown,MouseMoveMouseUp事件。

于 2009-04-29T21:42:52.447 回答
5

样本类

class CaptureEvents : IMessageFilter
{
    #region IMessageFilter Members
    public delegate void Callback(int message);
    public event Callback MessageReceived;

    IntPtr ownerWindow;
    Hashtable interestedMessages = null;
    CaptureEvents(IntPtr handle, int[] messages)
    {
        ownerWindow = handle;
        for(int c = 0; c < messages.Length ; c++)
        {
            interestedMessages[messages[c]] = 0;
        }
    }
    public bool PreFilterMessage(ref Message m)
    {
        if (m.HWnd == ownerWindow && interestedMessages.ContainsKey(m.Msg))
        {
            MessageReceived(m.Msg);
        }
        return true;
    }

    #endregion
}
于 2010-12-10T16:39:47.127 回答
3

看看这篇文章。它递归地挂钩所有控制事件并广播它们。您还可以在表单中覆盖WndProc

于 2009-04-29T21:49:08.453 回答
3

如果您不想通过覆盖 Form.PreProcessMessage 或 Form.WndProc 来处理消息,那么您可以将 Form 子类化以将事件处理程序挂钩到来自表单上各种控件的所有 MouseClick 事件。
编辑:忘记通过表单上控件的子控件进行递归。

    public class MousePreviewForm : Form
    {
      protected override void OnClosed(EventArgs e)
      {
         UnhookControl(this as Control);
         base.OnClosed(e);
      }

      protected override void OnLoad(EventArgs e)
      {
         base.OnLoad(e);

         HookControl(this as Control);
      }

      private void HookControl(Control controlToHook)
      {
         controlToHook.MouseClick += AllControlsMouseClick;
         foreach (Control ctl in controlToHook.Controls)
         {
            HookControl(ctl);
         }      
      }

      private void UnhookControl(Control controlToUnhook)
      {
         controlToUnhook.MouseClick -= AllControlsMouseClick;
         foreach (Control ctl in controlToUnhook.Controls)
         {
            UnhookControl(ctl);
         }
      }

      void AllControlsMouseClick(object sender, MouseEventArgs e)
      {
         //do clever stuff here...
         throw new NotImplementedException();
      }
   }

然后,您的表单将需要从 MousePreviewForm 而不是 System.Windows.Forms.Form 派生。

于 2009-04-29T21:53:51.517 回答