Как я могу синхронизировать прокрутку двух многострочных текстовых полей? - PullRequest
14 голосов
/ 29 сентября 2010

Как я могу синхронизировать прокрутку двух многострочных текстовых полей в C # (WinForms)?

Когда вы прокручиваете строку вверх / вниз в TextBox A, TextBox B тоже должен прокручивать вверх / вниз.То же самое наоборот.

Это достижимо без пользовательских элементов управления?

Ответы [ 5 ]

35 голосов
/ 29 сентября 2010

Да, вам придется создать собственное текстовое поле, чтобы вы могли обнаружить его прокрутку.Хитрость заключается в том, чтобы передать сообщение прокрутки в другое текстовое поле, чтобы оно синхронизировалось.Это действительно работает только тогда, когда это другое текстовое поле имеет примерно такой же размер и такое же количество строк.

Добавьте новый класс в свой проект и вставьте код, показанный ниже.Компиляция.Перетащите два новых элемента управления из верхней части панели инструментов на форму.Установите свойство 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);
}
8 голосов
/ 16 ноября 2011

Вы можете изменить эту строку:

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

на эту:

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

, и она также будет поддерживать прокрутку колесиком мыши.

3 голосов
/ 19 июня 2015

Решение Ханса Пассанта было потрясающим. Однако мне нужно было синхронизировать три текстовых поля, а не только два.

Таким образом, я немного изменил его - но все доверие должно идти к Гансу, я бы ни за что не приблизился бы без его работы - я подумал, что опубликую это здесь, если другим понадобится то же самое.

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

Тогда в форме инициализатора:

// add the required controls into scroll sync
Control[] syncedCtrls = new Control[] { ctrl1, ctrl2, ..., ctrln };
foreach (SyncTextBox ctr in syncedCtrls)
{
    ctr.Buddies = syncedCtrls;
}
2 голосов
/ 08 июня 2015

Решение Ханса Пассанта работало как шарм, но мне нужен RichTextBox с горизонтальной и вертикальной полосами прокрутки. Если вы расширяете RichTextBox вместо TextBox, вам нужно соответствующим образом изменить свойство ScrollBars (я использовал RichTextBoxScrollBars.Both).

Если вы хотите синхронизировать горизонтальную прокрутку, найдите (m.Msg == 0x115) || (m.Msg == 0x114).

0 голосов
/ 29 мая 2017

Вот что наконец помогло мне исправить синхронизацию нескольких текстовых полей с помощью колесика мыши.

Я основал это на очень полезном примере Ганса.

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...