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