Синхронизация позиций многострочного текстового поля в C # - PullRequest
6 голосов
/ 24 июля 2010

У меня есть приложение на C #, в котором два многострочных текстовых поля расположены рядом, каждое на одной стороне разделенного контейнера.Я хотел бы синхронизировать их вертикальную прокрутку, чтобы, когда пользователь прокручивает вверх или вниз одно из текстовых полей, другое текстовое поле прокручивает соответственно в том же направлении.Есть ли способ сделать это?Спасибо.

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ - 7/26/10

Я нашел несколько интересных API на сайте MSDN:

Метод TextBox.GetFirstVisibleLineIndex Метод TextBox.GetLastVisibleLineIndex Метод TextBox.ScrollToLine

Документация выглядит многообещающей, но мой компилятор (Microsoft Visual C # 2008 Express Edition) жалуется, когда я пытаюсь его использовать, даже после добавленияPresenationFramework в качестве ссылки и вставка using System.Windows.Controls; в начало файла:

Ошибка 1 «System.Windows.Forms.TextBox» не содержит определения «GetFirstVisibleLineIndex» и не имеет метода расширения »GetFirstVisibleLineIndex ', принимающий первый аргумент типа' System.Windows.Forms.TextBox ', может быть найден (вам не хватает директивы using или ссылки на сборку?)

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ - 7 /27/10

Я работаю над реализацией предложения Джея о внедрении нового элемента управления, но у меня возникают проблемы с привязкой обработчика событий к элементу управления.Вот что у меня есть:

public partial class MyFormApplication : Form
{
  public MyFormApplication() // MyFormApplication constructor
  {
     this.InitializeComponent();

     this.textBox1.Dispose(); // Replacing with textBoxSync1
     this.textBox2.Dispose(); // Replacing with textBoxSync2

     // Draw textBoxSync1
     this.textBoxSync1.AcceptsReturn = true;
     this.textBoxSync1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
        | System.Windows.Forms.AnchorStyles.Left)
        | System.Windows.Forms.AnchorStyles.Right)));
     this.textBoxSync1.BackColor = System.Drawing.SystemColors.Control;
     this.textBoxSync1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
     this.textBoxSync1.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
     this.textBoxSync1.Location = new System.Drawing.Point(0, 19);
     this.textBoxSync1.Multiline = true;
     this.textBoxSync1.Name = "textBoxSync1";
     this.textBoxSync1.ReadOnly = true;
     this.textBoxSync1.ScrollBars = System.Windows.Forms.ScrollBars.Both;
     this.textBoxSync1.Size = new System.Drawing.Size(338, 231);
     this.textBoxSync1.TabIndex = 0;
     this.textBoxSync1.TabStop = false;
     this.textBoxSync1.WordWrap = false;
     this.splitContainer1.Panel1.Controls.Remove(this.textBox1);
     this.splitContainer1.Panel1.Controls.Add(this.textBoxSync1);

     // Draw textBoxSync2
     this.textBoxSync2.AcceptsReturn = true;
     this.textBoxSync2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
        | System.Windows.Forms.AnchorStyles.Left)
        | System.Windows.Forms.AnchorStyles.Right)));
     this.textBoxSync2.BackColor = System.Drawing.SystemColors.Control;
     this.textBoxSync2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
     this.textBoxSync2.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
     this.textBoxSync2.Location = new System.Drawing.Point(0, 19);
     this.textBoxSync2.Multiline = true;
     this.textBoxSync2.Name = "textBoxSync2";
     this.textBoxSync2.ReadOnly = true;
     this.textBoxSync2.ScrollBars = System.Windows.Forms.ScrollBars.Both;
     this.textBoxSync2.Size = new System.Drawing.Size(113, 231);
     this.textBoxSync2.TabIndex = 30;
     this.textBoxSync2.TabStop = false;
     this.textBoxSync2.WordWrap = false;
     this.splitContainer1.Panel2.Controls.Remove(this.textBox2);
     this.splitContainer1.Panel2.Controls.Add(this.textBoxSync2);

     /* Goes on to perform other initializations... */

  }

  private void textBoxSync1_VerticalScroll(Message msg)
  {
     msg.HWnd = this.textBoxSync2.Handle;
     this.textBoxSync2.PubWndProc(ref msg);
  }

  private void textBoxSync2_VerticalScroll(Message msg)
  {
     msg.HWnd = this.textBoxSync1.Handle;
     this.textBoxSync1.PubWndProc(ref msg);
  }
}

public class TextBoxSynchronizedScroll : System.Windows.Forms.TextBox
{
  public event vScrollEventHandler VerticalScroll;
  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 (VerticalScroll != null)
        {
           VerticalScroll(msg);
        }
     }

     base.WndProc(ref msg);
  }

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

Я должен подумать, что что-то вроде ...

this.textBoxSync1.VerticalScroll += new System.EventHandler(this.textBoxSync1_VerticalScroll);

... понадобится, чтобы подключить событие вертикальной прокрутки к элементу управления, но, как вы, вероятно, видите, это не работает.Мы ценим любые предложения.Спасибо.

Ответы [ 2 ]

4 голосов
/ 23 сентября 2010

На основании существующего кода я придумал следующее.Кажется, работает на меня.

class TextBoxSynchronizedScroll : TextBox
{
    public const int WM_VSCROLL = 0x115;

    List<TextBoxSynchronizedScroll> peers = new List<TextBoxSynchronizedScroll>();

    public void AddPeer(TextBoxSynchronizedScroll peer)
    {
        this.peers.Add(peer);
    }

    private void DirectWndProc(ref Message m)
    {
        base.WndProc(ref m);
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_VSCROLL)
        {
            foreach (var peer in this.peers)
            {
                var peerMessage = Message.Create(peer.Handle, m.Msg, m.WParam, m.LParam);
                peer.DirectWndProc(ref peerMessage);
            }
        }

        base.WndProc(ref m);
    }
}

http://gist.github.com/593809

4 голосов
/ 24 июля 2010

I подклассифицировал RichTextBox и прослушал сообщение WM_VSCROLL, чтобы сделать то, что вы пытаетесь сделать.Возможно, вы можете сделать это вместо использования TextBox.

ОТВЕТ НА ВАШЕ РЕДАКТИРОВАНИЕ:

Примечание. Я предполагаю, что вы допустили небольшую ошибку вскопируйте и вставьте в форму заявки и этот textBoxSyncBusTraffic == textBoxSync1

Проблема заключается в объявлении события VerticalScroll вашего элемента управления в следующей строке:

this.textBoxSyncBusTraffic.VerticalScroll += new System.EventHandler(this.textBoxSyncBusTraffic_VerticalScroll); 
  1. Ваши пользовательские элементы управления должны подписаться на события TextBoxSynchronizedScroll.vScrollEventHandler ваших элементов управления (не для System.EventHandler).
  2. Метод, указанный в вашем обработчике событий, не существует (по крайней мере, в коде, который вы опубликовали).

Так что измените это:

this.textBoxSyncBusTraffic.VerticalScroll += new System.EventHandler(this.textBoxSyncBusTraffic_VerticalScroll); 

На это:

this.textBoxSync1.VerticalScroll += new TextBoxSynchronizedScroll.vScrollEventHandler(textBoxSync1_VerticalScroll);

Используется правильный обработчик событий и ссылки на метод, который вам нужен и уже есть.

Кроме того, убедитесь, что объявление для события VerticalScroll в textBoxSync2 выглядит следующим образом:

this.textBoxSync2.VerticalScroll += new TextBoxSynchronizedScroll.vScrollEventHandler(textBoxSync2_VerticalScroll);

Кстати, есть несколько методов, которые можно использовать, чтобыsier для объявления событий:

Первое - использовать конструктор форм.Если вы откроете окно «События» в окне «Свойства» экземпляра вашего расширенного элемента управления в конструкторе форм, вы увидите событие с именем VerticalScroll.Дважды щелкните этот элемент, чтобы Visual Studio объявил событие и создал метод для вызова при возникновении события.

Существует также ярлык, который можно использовать при настройке события в коде.Вы обнаружите, что после ввода следующего кода:

youtextBoxSync1.VerticalScroll +=

Вам будет предложено нажать клавишу Tab, чтобы завершить объявление.Если вы сделаете это, Visual Studio создаст метод с правильной подписью.

...