2010-08-14 21 views
5

पर ओवरराइड विधि मेरे पास दो प्रश्न हैं।सी # रनटाइम

1) मुझे how to make a control scroll smoothly के लिए कोड का एक छोटा मणि मिला।

ग्रेट। लेकिन यह WndProc विधि को ओवरराइड करता है, इसलिए इसका उपयोग करने के लिए, मुझे फ्लोलायआउट पैनेल को फाड़ना पड़ा था जिसे मैं डिज़ाइन समय, सबक्लास फ्लोलाउट पैनेल पर फॉर्म पर छोड़ देता था, और फिर आखिरकार मेरी नई कक्षा को तुरंत चालू करता था और सभी गुण मैन्युअल रूप से बना देता था और सभी संदर्भों को बदलता था इसे नियंत्रित करने के लिए। नियंत्रण ["नियंत्रण नाम"]। (या मुझे लगता है कि मैं एक क्लास-स्तरीय वैरिएबल बना सकता हूं जो अनिवार्य रूप से नियंत्रण था, हालांकि, जब भी इसे कहीं भी घोषित नहीं किया जाता है, तो वे इंटेलिजेंस का उपयोग कैसे करते हैं?)

तो अब मैं सोच रहा हूं कि क्या वास्तव में ऐसा करने के लिए एक रनटाइम तरीका था।

मैं कुछ इस रूप में सरल कर सकते हैं, जहां MainPanel नियंत्रण का नाम है:

MainPanel = (SmoothScrollingFlowLayoutPanel)MainPanel 

यह इतना आसान है, यह नहीं कर सकते हो सकता है? फिर भी, यह कष्टप्रद है क्योंकि मुझे अभी भी सबक्लास होना है (जो एक अच्छा डिजाइन निर्णय हो सकता है लेकिन मैं इसे एक-दूसरे से मुक्त करने की स्वतंत्रता चाहता हूं)। तो यह इस तरह FlowLayoutPanel कुछ की मूल में कोड डाल करने के लिए संभव हो जाएगा:

private Delegate void WndProcHandler(ref Message m); 
private WndProcHandler w; 

public void SomeCode() { 
    w = MainPanel.WndProc; // get reference to existing wndproc method 
    MainPanel.WndProc = WndProcSmoothScroll; //replace with new method 
} 

private void WndProcSmoothScroll(ref Message m) { // make smooth scrolling work 
    if (
     (m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL) 
     && (((int)m.WParam & 0xFFFF) == 5) 
    ) { 
     m.WParam = (IntPtr)(((int)m.WParam & ~0xFFFF) | 4); 
    } 
    if (w != null) { w(); } 
    base.WndProc(ref m); 
    } 

मुझे पता है यह शायद बहुत भोली है। मैं WndProc विधि का इलाज कर रहा हूं जैसे कि यह एक घटना है, और यह नहीं है।

2) तो फिर मेरे दूसरे प्रश्न, अगर WndProc था एक विधि के बजाय एक घटना, मैं कैसे एक घटना के लिए एक ही बात-स्टोर संचालकों की मूल सूची की एक प्रति क्या करना होगा, मेरे अपने घटना को स्थापित कर रहा है पहले चलाने के लिए हैंडलर, फिर सभी मूल घटना हैंडलर को कॉल करें?

स्वादिष्ट बिट्स

मामले में किसी को भी मैं आसान स्क्रॉलिंग कोड में एक अनुकूलन संभव देखा रुचि रखता है:

//m.WParam = (IntPtr)(((int)m.WParam & ~0xFFFF) | 4); 
m.WParam = (IntPtr)((int)m.WParam^1); 

के बाद से हम 4 5 से पिछले 16 बिट चालू करना चाहते हैं, हम और फिर या फिर के बजाय अंतिम बिट (एक्सओआर) फ्लिप कर सकते हैं।

उत्तर

8

यदि मैं आपका प्रश्न सही ढंग से समझता हूं, तो आप रनटाइम पर WndProc ओवरराइड करना चाहते हैं। यदि हां, तो आपको बस थोड़ा Win32 जादू चाहिए।

प्रत्येक नियंत्रण में "हैंडल" होता है जो इसकी पहचान करता है ताकि ऑपरेटिंग सिस्टम संदेश भेज सके। यह संभाल हर नियंत्रण पर Handle संपत्ति के माध्यम से उजागर किया जाता है। अंतर्निहित Win32 सिस्टम वास्तव में आपको किसी भी नियंत्रण के WndProc को सुनने की अनुमति देता है जब तक आपके पास हैंडल हो। इसका मतलब है कि Win32 व्यवहार को संशोधित करने के लिए आपको Winforms नियंत्रण से प्राप्त करने की आवश्यकता नहीं है। .NET में System.Windows.Forms.NativeWindow इस अंतर्निहित कार्यक्षमता को लपेटता है।

आप इसे इस तरह पूरा हो सकता है की एक उदाहरण है:

class SmoothScrollIntercept : System.Windows.Forms.NativeWindow 
{ 
    public SmoothScrollIntercept(IntPtr hWnd) 
    { 
     // assign the handle and listen to this control's WndProc 
     this.AssignHandle(hWnd); 
    } 

    protected override void WndProc(ref Message m) 
    { 
     // listen to WndProc here, do things 

     if ((m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL) 
      && (((int)m.WParam & 0xFFFF) == 5)) 
     { 
      m.WParam = (IntPtr)(((int)m.WParam & ~0xFFFF) | 4); 
     } 

     base.WndProc(ref m); 
    } 
} 

फिर पीछे कोड में, नियंत्रित करने के लिए अवरोधन देते हैं:

SmoothScrollIntercept intercept = new SmoothScrollIntercept(myControl.Handle); 

// myControl is now using smooth scrolling, without inheriting from the control 
+0

धन्यवाद जैच, लेकिन मैं पहले से ही अपने विंडोज़ स्क्रॉल को आसानी से पूरा कर चुका हूं। मुझे बस इतना नफरत है कि मुझे डिजाइनर से नियंत्रण कैसे निकालना था और सब कुछ गतिशील रूप से करना था। – ErikE

+0

@Emtucifor: कोई समस्या नहीं, मैं बस आपको यह बताने के लिए चाहता था कि आपको 'फ़्लोलाउट पैनेल' से अपने 'WndProc' को ओवरराइड करने के लिए उत्तराधिकारी नहीं होना पड़ेगा। –

+0

ओह, अब मुझे मिल गया। धन्यवाद। मैं कबूल करता हूं कि मैंने सावधानी से पढ़ा नहीं था जैसा कि मेरे पास होना चाहिए। यह उपयोगी है! वास्तव में, आप 100% सही हैं, यह वह जवाब है जिसे मैं ढूंढ रहा था। (माथे smacks) – ErikE

2

नहीं, आप जो पूछ रहे हैं वह असंभव है। जैसा कि आपने पहले किया था, आपको उप-वर्ग करना होगा।

भले ही यह एक घटना थी, आप जो भी कर रहे हैं वह करने में सक्षम नहीं होंगे। किसी ईवेंट के लिए सार्वजनिक इंटरफ़ेस केवल add और remove का खुलासा करता है; घटना से जुड़े वास्तविक प्रतिनिधि (ओं) को प्राप्त करने या असाइन करने का कोई तरीका नहीं है।

हालांकि, एक अलग नजरिए से समस्या को देखते हुए, आप अंत आप देख रहे हैं परिणाम हासिल करने के लिए में IMessageFilter इंटरफ़ेस का उपयोग करने में सक्षम हो सकता है।

संपादित

, IMessageFilter, काम नहीं करेगा आप PreFilterMessage भीतर संदेश संशोधित नहीं कर सकते के रूप में अपने कोड को देख फिर से करने के बाद; आप केवल इसकी जांच या दबाने कर सकते हैं।इस बिंदु पर आपकी सबसे अच्छी शर्त WndProc को माता-पिता Form में ओवरराइड करना है और वहां अपनी कुशलताएं बनाने का प्रयास करें। ऐसा लगता है कि आपकी समस्या का सामान्य समाधान नहीं है।

+0

धन्यवाद। मुझे कुछ जावास्क्रिप्ट पता है जहां आप इसे विधियों के साथ कर सकते हैं, इसलिए मैं सिर्फ उत्सुक था। अब यह मेरे लिए होता है, क्या मैं फ्लोलाउआउट पैनेल और उपयोगकर्ता नियंत्रण दोनों का वारिस कर सकता हूं ताकि मेरा नया स्मूथस्क्रॉलिंगफ्लोलाउट पैनेल एक ऐसा आइटम बन जाए जिसे मैं डिज़ाइन समय पर फॉर्म पर छोड़ सकता हूं? – ErikE

+0

@Emtucifor: नहीं, .NET भाषाओं में से कोई भी एकाधिक विरासत के लिए अनुमति नहीं देता है। हालांकि, आप 'FlowLayoutPanel' से प्राप्त कर सकते हैं और टूलबॉक्स में अपना नियंत्रण डाल सकते हैं। अगर नियंत्रण आपके प्रोजेक्ट में है, तो यह स्वचालित रूप से वहां दिखाई देना चाहिए। यदि यह किसी अन्य प्रोजेक्ट में है, तो आपको टूलबॉक्स पर राइट-क्लिक करना होगा, "आइटम चुनें ..." पर क्लिक करें, फिर उस .dll पर ब्राउज़ करें और उस तरह से नियंत्रण जोड़ें। –

+0

यह सहायक था। मुझे पता था कि उप-वर्गीकृत UserControls टूलबॉक्स में दिखाए जाएंगे, लेकिन किसी भी तरह से याद किया गया है कि उप-वर्गीकृत नियमित नियंत्रण भी वहां दिखाई देंगे। धन्यवाद। – ErikE