在C#中的面板内的任何位置处理click事件

我的表单中有一个面板,带有一个单击事件处理程序。 我在面板内还有一些其他控件(标签,其他面板等)。 如果您单击面板内的任何位置,我希望单击事件进行注册。 只要我没有点击面板内的任何控件,点击事件就会起作用,但无论你在面板内部点击什么,我都想触发事件。 这是否可以在不向面板内的所有控件添加相同的单击事件的情况下实现?

从技术上讲,这是可能的,虽然它非常难看。 您需要在将消息发送到单击的控件之前捕获该消息。 您可以使用IMessageFilter执行此操作,您可以在调度之前嗅探从消息队列中删除的输入消息。 像这样:

using System; using System.Drawing; using System.Windows.Forms; class MyPanel : Panel, IMessageFilter { public MyPanel() { Application.AddMessageFilter(this); } protected override void Dispose(bool disposing) { if (disposing) Application.RemoveMessageFilter(this); base.Dispose(disposing); } public bool PreFilterMessage(ref Message m) { if (m.HWnd == this.Handle) { if (m.Msg == 0x201) { // Trap WM_LBUTTONDOWN Point pos = new Point(m.LParam.ToInt32()); // Do something with this, return true if the control shouldn't see it //... // return true } } return false; } } 

我今天需要完全相同的function,因此经过测试和运行:

1:创建一个子抓取器,可以抓取你的鼠标点击:

 internal class MessageSnatcher : NativeWindow { public event EventHandler LeftMouseClickOccured = delegate{}; private const int WM_LBUTTONDOWN = 0x201; private const int WM_PARENTNOTIFY = 0x210; private readonly Control _control; public MessageSnatcher(Control control) { if (control.Handle != IntPtr.Zero) AssignHandle(control.Handle); else control.HandleCreated += OnHandleCreated; control.HandleDestroyed += OnHandleDestroyed; _control = control; } protected override void WndProc(ref Message m) { if (m.Msg == WM_PARENTNOTIFY) { if (m.WParam.ToInt64() == WM_LBUTTONDOWN) LeftMouseClickOccured(this, EventArgs.Empty); } base.WndProc(ref m); } private void OnHandleCreated(object sender, EventArgs e) { AssignHandle(_control.Handle); } private void OnHandleDestroyed(object sender, EventArgs e) { ReleaseHandle(); } } 

2:初始化捕获器以挂钩到面板WndProc:

  private MessageSnatcher _snatcher; public Form1() { InitializeComponent(); _snatcher = new MessageSnatcher(this.panel1); } 

3:如果单击子控件,Message snatcher将获取WM_PARENTNOTIFY。

您曾经能够覆盖控件上的OnBubbleEvent方法。 在WPF中,该机制称为路由事件: http : //weblogs.asp.net/vblasberg/archive/2010/03/30/wpf-routed-events-bubbling-several-layers-up.aspx

派对迟到了,但我做的是将面板内所有控件的所有点击事件映射到面板点击事件。 我知道它讨厌的做法。 但是嘿!!