Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从每个组件捕获鼠标事件_C#_Winforms_Mouseevent - Fatal编程技术网

C# 从每个组件捕获鼠标事件

C# 从每个组件捕获鼠标事件,c#,winforms,mouseevent,C#,Winforms,Mouseevent,我的WinForm C应用程序上的MouseEvents有问题 我想在我的应用程序上获得所有鼠标点击,但我不想在每个子组件中都放置一个侦听器,也不想使用Windows鼠标挂钩 在Flash中,我可以让一个听众上台,获取电影中所有的鼠标事件 C#上有这样的东西吗?全球鼠标听器 编辑: 我从IMessageFilter ans used Application.AddMessageFilter创建这个类 public class GlobalMouseHandler : IMessageFilte

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

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

在Flash中,我可以让一个听众上台,获取电影中所有的鼠标事件

C#上有这样的东西吗?全球鼠标听器


编辑:

我从IMessageFilter ans used 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);

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

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


这种方法带来的一个复杂性是必须通过传递给
PreFilterMessage
方法的消息结构来处理Windows消息。这意味着在
WM\\u LBUTTONDOWN、WM\\u MOUSEMOVE
WM\\u LBUTTONUP
等上引用Win32文档,而不是传统的
MouseDown
MOUSEMOVE
MouseUp
事件。它递归地hoook所有控制事件并广播它们。也可以在表单中重写

如果您不想通过重写Form.PreProcessMessage或Form.WndProc来处理消息,那么您可以将Form子类化,将事件处理程序挂接到表单上各种控件的所有鼠标单击事件。
编辑:忘记通过窗体上控件的子控件递归

    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派生。

示例类

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
}
class CaptureEvents:IMessageFilter
{
#区域IMessageFilter成员
公共委托无效回调(int消息);
收到公共事件回调消息;
IntPtr所有者窗口;
Hashtable interestedMessages=null;
CaptureEvents(IntPtr句柄,int[]消息)
{
ownerWindow=手柄;
for(int c=0;c
您甚至可以使用Form.OnControlsMouseClick事件应用AllControlsMouseClick处理程序。但我不能只循环遍历表单的第一个子项,我需要深入每个控件,并将AllControlsMouseClick添加到其子项中。子项组件的递归是一个很好的方法。但我不想给每个控件都添加一个侦听器。要使用鼠标移动事件,Application.AddMessageFilter可以工作,但我认为您的想法对其他类型的事件很好。谢谢你的帮助!谢谢你的帮助!一切正常。我将Application.AddMessageFilter与success一起使用。我钩住鼠标事件并创建一个C#MouseEventHandler,以将WinForm级别的事件分派给其他控件。我试图重写WinProc,但最终遇到了相同的问题:鼠标单击仅在我直接单击窗体时被捕获。如果单击子控件,则不会调用Winproc。