从C#WInForm上的每个组件捕获鼠标事件
我的WinForm C#应用程序上的MouseEvents有问题。 我希望鼠标点击我的应用程序,但我不想在每个子组件中放置一个监听器既不使用Windows鼠标挂钩。
在Flash上我可以在舞台上放置一个监听器来获取电影上的所有MouseEvent。 C#上有这样的东西吗? 全局MouseListener?
编辑:我从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);
感谢您的帮助!
一种直接的方法是通过调用Application.AddMessageFilter
并编写实现IMessageFilter
接口的类来添加消息循环filter。
通过IMessageFilter.PreFilterMessage
,您的类可以看到通过应用程序的消息循环传递的任何输入消息。 PreFilterMessage
还可以决定是否将这些消息传递给它们所指定的特定控件。
这种方法引入的一个复杂性是必须通过传递给PreFilterMessage
方法的Message结构来处理Windows消息。 这意味着参考WM\_LBUTTONDOWN, WM\_MOUSEMOVE
, WM\_LBUTTONUP
等上的Win32文档,而不是传统的MouseDown
, MouseMove
和MouseUp
事件。
样本类
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 }
如果您不想通过重写Form.PreProcessMessage或Form.WndProc来处理消息,那么您可以inheritanceForm以将事件处理程序挂钩到窗体上各种控件的所有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派生。
看看这篇文章 。 它递归地挂起所有控制事件并广播它们。 您也可以在表单中覆盖WndProc 。