2009-04-29 8 views
28

पर प्रत्येक घटक से माउस ईवेंट कैप्चर करना मुझे अपने WinForm C# एप्लिकेशन पर MouseEvents के साथ कोई समस्या है। मैं अपने आवेदन पर सभी माउस क्लिक प्राप्त करना चाहता हूं, लेकिन मैं हर बच्चे के घटक में श्रोता नहीं रखना चाहता हूं और न ही विंडोज माउस हुक का उपयोग करना चाहता हूं।सी # WInForm

फ्लैश पर मैं फिल्म पर सभी माउस एवेन्ट्स प्राप्त करने के लिए स्टेज पर एक श्रोता डाल सकता हूं। क्या सी # पर ऐसी चीज है? एक वैश्विक माउस लिस्टर?


संपादित करें: मैं IMessageFilter ans इस्तेमाल किया 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); 

मदद के लिए धन्यवाद!

उत्तर

14

ऐसा करने का एक सीधा तरीका Application.AddMessageFilter पर कॉल करके एक संदेश लूप फ़िल्टर जोड़ना और IMessageFilter इंटरफ़ेस लागू करने वाली कक्षा लिखना है।

IMessageFilter.PreFilterMessage के माध्यम से, आपकी कक्षा को आपके एप्लिकेशन के संदेश लूप से गुजरने वाले किसी भी इनपुट संदेश को देखने के लिए मिलता है। PreFilterMessage यह भी तय करता है कि इन संदेशों को उस विशिष्ट नियंत्रण पर पास करना है, जिस पर वे नियत हैं।

इस दृष्टिकोण को पेश करने वाली जटिलता का एक टुकड़ा आपके संदेशों को PreFilterMessage विधि में भेजे गए संदेश संरचना के माध्यम से विंडोज संदेशों से निपटने के लिए है। इसका मतलब पारंपरिक MouseDown, MouseMove और MouseUp ईवेंट के बजाय WM\_LBUTTONDOWN, WM\_MOUSEMOVE, WM\_LBUTTONUP आदि पर Win32 डॉक्यूमेंटेशन का जिक्र है।

+0

मदद के लिए धन्यवाद! सब ठीक काम करता है। मैंने एप्लिकेशन का उपयोग किया। Susess के साथ AddMessageFilter। मैं माउस घटनाओं को हुक करता हूं और WinForm स्तर पर अन्य नियंत्रणों पर ईवेंट भेजने के लिए एक C# MouseEventHandler बनाता हूं। –

2

Take a look at this article। यह सभी नियंत्रण घटनाओं को दोबारा जोड़ता है और उन्हें प्रसारित करता है। आप अपने फॉर्म में WndProc ओवरराइड भी कर सकते हैं।

+2

मैंने WinProc को ओवरराइड करने का प्रयास किया, लेकिन एक ही समस्या के साथ समाप्त हुआ: माउस क्लिक केवल तभी पकड़ते थे जब मैंने सीधे फॉर्म पर क्लिक किया था। अगर मैंने एक बच्चे पर क्लिक किया है तो नियंत्रण Winproc नहीं कहा गया था। –

3

यदि आप फॉर्म.प्रोप्रोसेस मैसेज या फॉर्म .ndProc को ओवरराइड करके संदेशों को संभाल नहीं करना चाहते हैं तो आप फॉर्म पर विभिन्न नियंत्रणों से सभी माउसक्लिक घटनाओं में ईवेंट ईवेंट हैंडलर को हुक करने के लिए फॉर्म को उपclass कर सकते हैं।
संपादित करें: फ़ॉर्म पर नियंत्रण के बाल नियंत्रण के माध्यम से पुन: साझा करना भूल गया।

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।

+0

आप AllControlsMouseClick हैंडलर को लागू करने के लिए Form.OnControlAdded ईवेंट का भी उपयोग कर सकते हैं। –

+0

लेकिन मैं न केवल फॉर्म के पहले चाइल्ड्स के माध्यम से लूप कर सकता हूं, मुझे प्रत्येक नियंत्रण में गहराई से जाना होगा और ऑलकंट्रोलसमाउस को अपने बच्चों को भी क्लिक करना होगा। –

+0

बच्चों के componets का पुनरावृत्ति एक अच्छा tatic है। लेकिन मैं हर नियंत्रण में श्रोता नहीं जोड़ना चाहता हूं। माउस घटनाओं के लिए एप्लिकेशन। AddMessageFilter काम करते हैं, लेकिन मुझे लगता है कि आपका विचार अन्य प्रकार की घटनाओं के लिए अच्छा है। सहायता के लिए धनयवाद! –

4

नमूना कक्षा

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 
}