在 C# 中同步多行文本框位置
我有一个 C# 应用程序,其中有两个并排的多行文本框,每个文本框位于拆分容器的一侧。我想同步它们的垂直滚动,以便当用户向上或向下滚动其中一个文本框时,另一个文本框分别沿相同方向滚动。有办法做到这一点吗?谢谢。
其他信息 - 2010 年 7 月 26 日,
我在 MSDN 网站上发现了一些有趣的 API:
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
我正在努力实施 Jay 的实施建议一个新控件,但我无法将事件处理程序绑定到控件中。这是我到目前为止所得到的:
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);
...的东西才能将垂直滚动事件挂接到控件中,但正如您可能看到的那样,这不起作用。任何建议将不胜感激。谢谢。
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.
ADDITIONAL INFORMATION - 7/26/10
I found some interesting APIs on the MSDN website:
TextBox.GetFirstVisibleLineIndex Method
TextBox.GetLastVisibleLineIndex Method
TextBox.ScrollToLine Method
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:
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?)
ADDITIONAL INFORMATION - 7/27/10
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我 子类化了 RichTextBox 并侦听 WM_VSCROLL 消息来执行您的操作正在努力做。也许您可以这样做,而不是使用文本框。
对您的编辑的回应:
注意:我假设您在申请表中的复制和粘贴过程中犯了一个小错误,并且 textBoxSyncBusTraffic == textBoxSync1
问题出在您的声明控件的 VerticalScroll 事件,如下行:
因此,将其更改为: 改为
:
这使用正确的事件处理程序并引用您需要和已有的方法。
另外,请确保 textBoxSync2 的 VerticalScroll 事件的声明如下所示:
顺便说一句,您可以使用几种技术来更轻松地声明事件:
第一种是使用表单设计器。如果在表单设计器中的扩展控件实例的“属性”窗口中打开“事件”窗口,您将看到一个名为 VerticalScroll 的事件。双击此项可让 Visual Studio 声明事件并创建一个在事件触发时调用的方法。
当您在代码中设置事件时,还可以使用一个快捷方式。键入以下代码后,您会发现:
系统会提示您按 Tab 完成声明。如果执行此操作,Visual Studio 将创建一个具有正确签名的方法。
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.
RESPONSE TO YOUR EDIT:
Note: I'm assuming you made a minor error in the copy and paste in your Application form and that textBoxSyncBusTraffic == textBoxSync1
The problem is in your declaration of your control's VerticalScroll event, in this line:
So change this:
To this:
This uses the correct event handler and references the method you need and already have.
Also, make sure that the declaration for textBoxSync2's VerticalScroll event looks like this:
Incidentally, there are a couple techniques you can use to make it easier to declare events:
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:
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.
根据现有代码,我想出了以下内容。似乎对我有用。
http://gist.github.com/593809
Based of the existing code I came up with the following. Seems to work for me.
http://gist.github.com/593809