繁体   English   中英

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

[英]How can I sync the scrolling of two multiline textboxes?

如何在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);
}

然后在形式initilizer中:

// 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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM