在 C# 中同步多行文本框位置 [英] Synchronizing Multiline Textbox Positions in C#

查看:72
本文介绍了在 C# 中同步多行文本框位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 C# 应用程序,其中有两个并排的多行文本框,每个文本框都位于拆分容器的一侧.我想同步它们的垂直滚动,以便当用户向上或向下滚动其中一个文本框时,另一个文本框分别沿同一方向滚动.有没有办法做到这一点?谢谢.

I have a C# application wherein there are two multiline textboxes side-by-side, each in one side of a split-container. I would like to synchronize their vertical scroll, so that when the user scrolls up or down one of the textboxes, the other textbox scrolls respectively in the same direction. Is there a way to do this? Thanks.

附加信息 - 7/26/10

我在 MSDN 网站上发现了一些有趣的 API:

I found some interesting APIs on the MSDN website:

TextBox.GetFirstVisibleLineIndex 方法
TextBox.GetLastVisibleLineIndex 方法
TextBox.ScrollToLine 方法

那里的文档看起来很有希望,但我的编译器(Microsoft Visual C# 2008 Express Edition)在我尝试使用它时会抱怨,即使在添加 PresenationFramework 作为参考并插入 using System 之后.Windows.Controls; 在文件顶部:

The documentation there looks promising, but my compiler (Microsoft Visual C# 2008 Express Edition) complains when I try to use it, even after adding the PresenationFramework as a Reference and inserting using System.Windows.Controls; at the top of the file:

错误 1 ​​'System.Windows.Forms.TextBox' 不包含 'GetFirstVisibleLineIndex' 的定义,并且找不到接受类型为 'System.Windows.Forms.TextBox' 的第一个参数的扩展方法 'GetFirstVisibleLineIndex'(是您是否缺少 using 指令或程序集引用?)
Error 1 'System.Windows.Forms.TextBox' does not contain a definition for 'GetFirstVisibleLineIndex' and no extension method 'GetFirstVisibleLineIndex' accepting a first argument of type 'System.Windows.Forms.TextBox' could be found (are you missing a using directive or an assembly reference?)

附加信息 - 7/27/10

我正在努力实施 Jay 的关于实施新控件的建议,但我无法将事件处理程序绑定到控件中.这是我到目前为止所拥有的:

I'm working on implementing Jay's suggestion of implementing a new control, but I'm having trouble tying the eventhandler into the control. Here's is what I have so far:

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

我应该认为类似......

I should think that something like...

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

...需要将垂直滚动事件挂钩到控件中,但您可能会看到,这不起作用.任何建议,将不胜感激.谢谢.

...would be needed to hook the vertical scroll event into the control, but as you can probably see, this does not work. Any suggestions would be appreciated. Thanks.

推荐答案

I 子类化 RichTextBox 并监听 WM_VSCROLL 消息以执行您要执行的操作.也许您可以这样做,而不是使用 TextBox.

I subclassed a RichTextBox and listened for the WM_VSCROLL message to do what you're trying to do. Perhaps you can do that instead of using a TextBox.

回应您的

注意:我假设您在复制和粘贴申请表时犯了一个小错误,并且 textBoxSyncBusTraffic == textBoxSync1

问题在于您在此行中声明了控件的 VerticalScroll 事件:

The problem is in your declaration of your control's VerticalScroll event, in this line:

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

这使用了正确的事件处理程序并引用了您需要和已经拥有的方法.

This uses the correct event handler and references the method you need and already have.

此外,请确保 textBoxSync2 的 VerticalScroll 事件的声明如下所示:

Also, make sure that the declaration for textBoxSync2's VerticalScroll event looks like this:

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

顺便说一下,您可以使用几种技术来简化事件声明:

Incidentally, there are a couple techniques you can use to make it easier to declare events:

首先是使用表单设计器.如果您在表单设计器中的扩展控件实例的属性"窗口中打开事件"窗口,您将看到一个名为 VerticalScroll 的事件.双击此项让 Visual Studio 声明事件并创建一个在事件触发时调用的方法.

The first is to use the form designer. If you open the Events window in the Properties window of an instance of your extended control in the forms designer, you'll see an event called VerticalScroll. Double click this item to have Visual Studio declare the event and create a method to call when the event fires.

当您在代码中设置事件时,您还可以使用快捷方式.输入以下代码后,您会发现:

There's also a shortcut you can use when you set up your event in code. You'll find that after you type the following code:

youtextBoxSync1.VerticalScroll +=

系统会提示您按 Tab 完成声明.如果你这样做,Visual Studio 将创建一个具有正确签名的方法.

You'll be prompted to press Tab to finish the declaration. If you do this Visual Studio will create a method with the correct signature.

这篇关于在 C# 中同步多行文本框位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆