2009-12-01 15 views
15

मेरे आवेदन के रूप में, मेरे पास दो RichTextBox ऑब्जेक्ट्स हैं। वे दोनों हमेशा टेक्स्ट की समान संख्या में होंगे। मैं इन दोनों के बीच लंबवत स्क्रॉलिंग को "सिंक्रनाइज़" करना चाहता हूं, ताकि जब उपयोगकर्ता एक पर लंबवत स्क्रॉल स्थिति बदलता है, तो दूसरा एक ही राशि को स्क्रॉल करता है। मैं यह करने के बारे में कैसे जा सकता हूं?सी #: दो RichTextBoxes की स्क्रॉल स्थिति सिंक्रनाइज़ करें?

उत्तर

15

मैंने इसे थोड़ी देर पहले एक छोटी परियोजना के लिए किया था, और यहां मुझे सरल समाधान मिला है।

उपवर्गीकरण RichTextBox करके एक नया नियंत्रण बनाएँ:

public class SynchronizedScrollRichTextBox : System.Windows.Forms.RichTextBox 
    { 
     public event vScrollEventHandler vScroll; 
     public delegate void vScrollEventHandler(System.Windows.Forms.Message message); 

     public const int WM_VSCROLL = 0x115; 

     protected override void WndProc(ref System.Windows.Forms.Message msg) { 
      if (msg.Msg == WM_VSCROLL) { 
       if (vScroll != null) { 
        vScroll(msg); 
       } 
      } 
      base.WndProc(ref msg); 
     } 

     public void PubWndProc(ref System.Windows.Forms.Message msg) { 
      base.WndProc(ref msg); 
     } 
    }  

अपने फ़ॉर्म पर और प्रत्येक नियंत्रण स्पष्ट रूप से नियंत्रण है कि इसके vScroll स्थिति बदल गया है के अन्य उदाहरण सूचित के लिए नए नियंत्रण जोड़ें। इस तरह कुछ:

private void scrollSyncTxtBox1_vScroll(Message msg) { 
    msg.HWnd = scrollSyncTxtBox2.Handle; 
    scrollSyncTxtBox2.PubWndProc(ref msg); 
} 

मुझे लगता है कि इस कोड में समस्याएं हैं यदि सभी 'जुड़े' नियंत्रणों में प्रदर्शित करने योग्य रेखाओं की संख्या समान नहीं है।

+0

यह विधि स्क्रॉलबार को स्थानांतरित करके स्क्रॉलिंग के लिए ठीक काम कर रही है। लेकिन स्क्रॉल बार सिंक्रनाइज़ नहीं होते हैं (1) माउस व्हील (2) के साथ स्क्रॉलिंग 'पेज डाउन' या 'पेज अप' कुंजियों द्वारा स्क्रॉल करना - तीर कुंजियों को दबाकर स्क्रॉल करना – twnaing

+0

@Jay riggs 'System.Windows.Forms.RichTextBox' 'PubWndProc' की परिभाषा नहीं है और 'System.Windows.Forms.RichTextBox' के पहले तर्क को स्वीकार करने वाली कोई एक्सटेंशन विधि 'PubWndProc' नहीं मिल सकती है (क्या आप एक निर्देश या निर्देशक संदर्भ का उपयोग कर रहे हैं?) – Pomster

18

धन्यवाद उत्तर आपके उत्तर के लिए; कुछ और खोज के बाद मुझे here वर्णित विधि भी मिली। मैं रुचि रखने वाले किसी और के लिए इसे नीचे रेखांकित कर दूंगा।


पहले, घोषित निम्नलिखित enums:

public enum ScrollBarType : uint { 
    SbHorz = 0, 
    SbVert = 1, 
    SbCtl = 2, 
    SbBoth = 3 
} 

public enum Message : uint { 
    WM_VSCROLL = 0x0115 
} 

public enum ScrollBarCommands : uint { 
    SB_THUMBPOSITION = 4 
} 

इसके बाद, GetScrollPos और SendMessage के लिए बाहरी संदर्भ जोड़ें।

[DllImport("User32.dll")] 
public extern static int GetScrollPos(IntPtr hWnd, int nBar); 

[DllImport("User32.dll")] 
public extern static int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); 

अंत में, उचित RichTextBox की VScroll घटना के लिए एक घटना हैंडलर जोड़ने: इस मामले में

private void myRichTextBox1_VScroll(object sender, EventArgs e) 
{ 
    int nPos = GetScrollPos(richTextBox1.Handle, (int)ScrollBarType.SbVert); 
    nPos <<= 16; 
    uint wParam = (uint)ScrollBarCommands.SB_THUMBPOSITION | (uint)nPos; 
    SendMessage(richTextBox2.Handle, (int)Message.WM_VSCROLL, new IntPtr(wParam), new IntPtr(0)); 
} 

, richTextBox2 के लंबवत स्क्रॉल स्थिति richTextBox1 साथ सिंक्रनाइज़ किया जाएगा।

+0

ग्रेट सारांश । मेरे बहुत समय बचाया। धन्यवाद! –

+1

WM_HSCROLL के लिए हेक्स कोड क्या होगा? – Logerfo

1

जय के उप-वर्ग दृष्टिकोण की एक भिन्नता जोसेफ किंग्री की पोस्ट में यहां देखी जा सकती है: Synchronizing Multiline Textbox Positions in C#। यूसुफ का दृष्टिकोण भी subclasses लेकिन एक _VScroll घटना हैंडलर की आवश्यकता नहीं है। मैंने 3 बक्से के बीच 3-तरफा बांधने के लिए उस दृष्टिकोण का उपयोग किया और WM_HSCROLL जोड़ा।

3

[दृश्य स्टूडियो सी # 2010 एक्सप्रेस, एक विंडोज 7 64 बिट स्थापना पर v10.0.30319]

मैं का उपयोग किया है डोनट के समाधान के ऊपर तैनात है, लेकिन जब RichTextBoxes कि कई पंक्तियाँ हो के अंत तक स्क्रॉल करके एक समस्या पाया।

यदि GetScrollPos() का परिणाम >0x7FFF है तो nPos स्थानांतरित हो गया है, शीर्ष बिट सेट है। परिणामी wParam वैरिएबल के साथ IntPtr का निर्माण OverflowException के साथ विफल हो जाएगा। आप आसानी से निम्नलिखित के साथ इस परीक्षण कर सकते हैं (दूसरी पंक्ति असफल हो जायेगी):

IntPtr ip = new IntPtr(0x7FFF0000); 
    IntPtr ip2 = new IntPtr(0x80000000); 

SendMessage()UIntPtr एक समाधान प्रतीत होता का उपयोग करता है, लेकिन मुझे लगता है कि काम करने के लिए नहीं मिल सका का एक संस्करण।तो, मैं निम्नलिखित का उपयोग कर दिया है:

[DllImport("User32.dll")] 
    public extern static int SendMessage(IntPtr hWnd, uint msg, UInt32 wParam, UInt32 lParam); 

यह 0xffff अप करने के लिए अच्छा होना चाहिए, लेकिन उसके बाद विफल हो जाएगा। मैंने अभी तक >0xffff का अनुभव GetScrollPos() से नहीं किया है, और मान लें कि User32.dll में SendCommand() का 64 बिट संस्करण होने की संभावना नहीं है, लेकिन उस समस्या के किसी भी समाधान की सराहना की जाएगी।

संबंधित मुद्दे