2009-12-01 57 views
15

在我的申請表中,我有兩個RichTextBox對象。它們都將具有相同數量的文本行。我想「同步」這兩者之間的垂直滾動,以便當用戶更改一個垂直滾動位置時,另一個滾動相同的數量。我該如何去做這件事?C#:同步兩個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)通過「page down」或「page up」鍵滾動時滾動條不同步 - 按箭頭鍵滾動 – twnaing 2011-05-30 03:54:03

+0

@Jay riggs'System.Windows.Forms.RichTextBox'不包含'PubWndProc'的定義,並且沒有找到接受類型'System.Windows.Forms.RichTextBox'的第一個參數的擴展方法'PubWndProc'(可以找到缺少使用指令或程序集引用嗎?) – Pomster 2012-06-06 06:59:17

18

感謝周杰倫的回答;經過一番更多的搜索後,我也發現了here的描述方法。我會在下面概述任何感興趣的人。


首先,聲明如下枚舉:

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 
} 

下一步,添加外部引用GetScrollPosSendMessage

[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); 

最後,添加的事件處理程序的事件VScroll適當RichTextBox的:

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

偉大的總結。節省了我很多時間。謝謝! – 2012-08-15 11:33:16

+1

什麼是WM_HSCROLL的十六進制代碼? – Logerfo 2016-11-09 18:19:31

1

Jay的子類方法的變體可以在Joseph Kingry的帖子中找到:Synchronizing Multiline Textbox Positions in C#。 Joseph的方法也是子類,但不需要_VScroll事件處理程序。我使用這種方法在3個盒子之間做了3方向的綁定,並添加了WM_HSCROLL。

3

[Visual Studio的C#2010 Express中,在Windows 7 64位安裝v10.0.30319]

我用甜甜圈的解決方案張貼以上,但滾動到包含許多行RichTextBoxes結束的時候發現了一個問題。

如果GetScrollPos()的結果是>0x7FFF那麼當nPos被移位時,最高位被設置。創建IntPtr與生成的wParam變量然後將失敗,並顯示OverflowException。您可以輕鬆地用下面的測試這個(第二行會失敗):

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

的使用UIntPtr似乎是一個解決方案,但我不能得到那個工作SendMessage()一個版本。所以,我使用以下命令:

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

這應該是好的可達0xffff,但之後會失敗。我還沒有遇到GetScrollPos()>0xffff結果,並且假定User32.dll不可能有SendCommand()的64位版本,但任何解決該問題的方法都將不勝感激。