2010-10-13 47 views
6

我在我的窗體中有一個面板,帶有單擊事件處理程序。我還在面板中有一些其他控件(標籤,其他面板等)。如果您點擊面板內的任何位置,我希望點擊事件可以註冊。只要我不點擊面板內的任何控件,點擊事件就會發揮作用,但無論您在面板內點擊哪個位置,我都想要觸發該事件。這可能沒有添加相同的點擊事件面板內的所有控件?在C中的面板內的任何地方處理單擊事件#

+0

這是WPF .....? – 2010-10-13 18:21:12

+1

不,只是一個普通的Windows窗體應用程序 – 2010-10-13 18:26:11

回答

1

我需要完全相同的功能的今天,所以這是測試和工程:

1:創建一個subclasser可以搶奪你的鼠標點擊:

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:消息的綁架者將得到WM_PARENTNOTIFY如果你點擊一個卡ld控制。

5

從技術上講它是可能的,雖然它是非常難看醜。您需要在之前收到消息,並將其發送給點擊的控件。您可以使用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; 
    } 
} 
+0

+1我也做了這個,並同意它應該很好地工作。我唯一的警告是,它基本上附加到應用程序事件消息泵,因此請確保無論您在「對此執行任何操作......」位中做什麼,都要快速高效地進行。 – 2010-10-13 19:46:32

+1

呃,它已經過濾面板和消息。此代碼在人類運行。 – 2010-10-13 19:57:31

0

位遲到了,但我所做的就是映射所有控件的所有點擊事件的面板,面板中單擊事件的內部。我知道它討厭的做法。但嘿!