如何同步两个多行文本框的滚动?

如何在C#(WinForms)中同步两个多行文本框的滚动?

在TextBox A中向上/向下滚动一行时,TextBox B也应向上/向下滚动。 反之亦然。

如果没有自定义控件,这是否可以实现?

是的,您必须创建一个自定义文本框,以便检测它是否滚动。 诀窍是将滚动消息传递给另一个文本框,以便它同步滚动。 这真的只适用于其他文本框大小相同且行数相同的情况。

在项目中添加一个新类并粘贴下面显示的代码。 编译。 将两个新控件从工具箱顶部拖放到表单上。 将Buddy属性设置为两者上的另一个控件。 运行,在两个文本中键入一些文本,并在拖动滚动条时观察它们同步滚动。

using System; using System.Windows.Forms; using System.Runtime.InteropServices; class SyncTextBox : TextBox { public SyncTextBox() { this.Multiline = true; this.ScrollBars = ScrollBars.Vertical; } public Control Buddy { get; set; } private static bool scrolling; // In case buddy tries to scroll us protected override void WndProc(ref Message m) { base.WndProc(ref m); // Trap WM_VSCROLL message and pass to buddy if (m.Msg == 0x115 && !scrolling && Buddy != null && Buddy.IsHandleCreated) { scrolling = true; SendMessage(Buddy.Handle, m.Msg, m.WParam, m.LParam); scrolling = false; } } [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); } 

你可以改变这一行:

 if (m.Msg == 0x115) && !scrolling && Buddy != null && Buddy.IsHandleCreated) 

对此:

 if ((m.Msg == 0x115 || m.Msg==0x20a) && !scrolling && Buddy != null && Buddy.IsHandleCreated) 

并且它也支持使用鼠标滚轮滚动。

Hans Passant的解决方案非常棒。 但是我需要同步三个文本框而不仅仅是两个。

所以我稍微修改了一下 – 但是所有的信任都应该归到汉斯那里,如果没有他的工作我就不可能接近 – 我想我会把它发回去,以防其他人需要同样的东西。

SyncBox类:

 using System; using System.Windows.Forms; using System.Runtime.InteropServices; class SyncTextBox : TextBox { public SyncTextBox() { this.Multiline = true; this.ScrollBars = ScrollBars.Vertical; } public Control[] Buddies { get; set; } private static bool scrolling; // In case buddy tries to scroll us protected override void WndProc(ref Message m) { base.WndProc(ref m); // Trap WM_VSCROLL message and pass to buddy if (Buddies != null) { foreach (Control ctr in Buddies) { if (ctr != this) { if ((m.Msg == 0x115 || m.Msg == 0x20a) && !scrolling && ctr.IsHandleCreated) { scrolling = true; SendMessage(ctr.Handle, m.Msg, m.WParam, m.LParam); scrolling = false; } } } } } [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); } 

然后在formsinitilizer中:

 // add the required controls into scroll sync Control[] syncedCtrls = new Control[] { ctrl1, ctrl2, ..., ctrln }; foreach (SyncTextBox ctr in syncedCtrls) { ctr.Buddies = syncedCtrls; } 

Hans Passant的解决方案就像魅力一样,但我需要一个包含水平和垂直滚动条的RichTextBox。 如果扩展RichTextBox而不是TextBox,则需要相应地更改ScrollBars属性(我使用了RichTextBoxScrollBars.Both)。

如果您想同步水平滚动,请查找(m.Msg == 0x115) || (m.Msg == 0x114) (m.Msg == 0x115) || (m.Msg == 0x114)

这是最终帮助我使用鼠标滚轮修复多个文本框同步的原因。

我基于非常有用的汉斯例子。

 int WM_MOUSEWHEEL = 0x20a; // or 522 int WM_VSCROLL = 0x115; // or 277 protected override void WndProc(ref Message m) { //Trap WM_VSCROLL and WM_MOUSEWHEEL message and pass to buddy if (Buddies != null) { if (m.Msg == WM_MOUSEWHEEL) //mouse wheel { if ((int)m.WParam < 0) //mouse wheel scrolls down SendMessage(this.Handle, (int)0x0115, new IntPtr(1), new IntPtr(0)); //WParam: 1- scroll down, 0- scroll up else if ((int)m.WParam > 0) SendMessage(this.Handle, (int)0x0115, new IntPtr(0), new IntPtr(0)); return; //prevent base.WndProc() from messing synchronization up } else if (m.Msg == WM_VSCROLL) { foreach (Control ctr in Buddies) { if (ctr != this && !scrolling && ctr != null && ctr.IsHandleCreated) { scrolling = true; SendMessage(ctr.Handle, m.Msg, m.WParam, m.LParam); scrolling = false; } } } } //do the usual base.WndProc(ref m); }