C# Windows窗体同时滚动多个列表框
我正在使用WindowsForms,我有两个列表框。我可以分别成功滚动两个列表框,但我想“同步”滚动。因此,当我滚动C# Windows窗体同时滚动多个列表框,c#,.net,winforms,listbox,C#,.net,Winforms,Listbox,我正在使用WindowsForms,我有两个列表框。我可以分别成功滚动两个列表框,但我想“同步”滚动。因此,当我滚动ListBox1时,我想同时滚动ListBox2,选择ListBox2的相应字段,并将其与ListBox1对齐。 我已经查过了,还有很多其他的帖子 下面是它的外观: 以下是我努力实现的目标: 这似乎是一项复杂的任务。然而,在的帮助下,我设法找到了这个解决方案 您必须创建一个类似于listBox的新控件,该控件的事件已滚动,这可以使用此方法完成 在项目内部,右键单击项目节点并选择添
ListBox1
时,我想同时滚动ListBox2
,选择ListBox2
的相应字段,并将其与ListBox1
对齐。
我已经查过了,还有很多其他的帖子
下面是它的外观:
以下是我努力实现的目标:
这似乎是一项复杂的任务。然而,在的帮助下,我设法找到了这个解决方案 您必须创建一个类似于
listBox
的新控件,该控件的事件已滚动
,这可以使用此方法完成
在项目内部,右键单击项目节点并选择添加用户控件(Windows窗体),将其命名为ScrollingListBox.cs。它将与名为“ScrollingListBox.Designer.cs”的文件一起出现在解决方案资源管理器中,右键单击后一个文件并将其删除,然后选择“ScrollingListBox.cs”,右键单击它并选择“查看代码”,或按F7,然后用以下代码替换其内容:
using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Scroll
{
public partial class ScrollingListBox : ListBox
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
[Category("Action")]
public event ScrollEventHandler Scrolled = null;
private const int WM_VSCROLL = 0x115;
private const int SB_ENDSCROLL = 0x8;
private const int SIF_RANGE = 0x1;
private const int SIF_PAGE = 0x2;
private const int SIF_POS = 0x4;
private const int SIF_TRACKPOS = 0x10;
private const int SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;
private struct ScrollInfoStruct
{
public int cbSize;
public int fMask;
public int nMin;
public int nMax;
public int nPage;
public int nPos;
public int nTrackPos;
}
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetScrollInfo(IntPtr hWnd, int n, ref ScrollInfoStruct lpScrollInfo);
protected override void WndProc(ref System.Windows.Forms.Message msg)
{
if (msg.Msg == WM_VSCROLL)
{
if (Scrolled != null)
{
ScrollInfoStruct si = new ScrollInfoStruct();
si.fMask = SIF_ALL;
si.cbSize = Marshal.SizeOf(si);
GetScrollInfo(msg.HWnd, 0, ref si);
if (msg.WParam.ToInt32() == SB_ENDSCROLL)
{
ScrollEventArgs sargs = new ScrollEventArgs(ScrollEventType.EndScroll, si.nPos);
Scrolled(this, sargs);
}
}
}
base.WndProc(ref msg);
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
}
}
到
还有这条线和类似的线,
this.listBox1 = new System.Windows.Forms.ListBox();
private System.Windows.Forms.ListBox listBox1;
到
现在,您可以使用此事件检测一个框中发生的滚动,并相应地修改另一个框,如下所示:
private void listBox1_Scrolled(object sender, ScrollEventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_Scrolled(object sender, ScrollEventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
private void listBox1_MouseHover(object sender, EventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_MouseHover(object sender, EventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
private void listBox1_MouseMove(object sender, EventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_MouseMove(object sender, EventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
这可以通过单击滚动条的箭头或用鼠标抓图来滚动滚动条,但不适用于在框内使用鼠标滚轮。我尝试使用事件mouseweel
来解决此问题,但不幸的是,它没有按预期工作,因此我找到的唯一选项是使用事件MouseHover
和MouseMove
来完成此操作,如下所示:
private void listBox1_Scrolled(object sender, ScrollEventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_Scrolled(object sender, ScrollEventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
private void listBox1_MouseHover(object sender, EventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_MouseHover(object sender, EventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
private void listBox1_MouseMove(object sender, EventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_MouseMove(object sender, EventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
如果您在框的白色区域内的任何位置使用鼠标滚轮,这将起作用。不幸的是,如果您在滚动条上使用鼠标滚轮,这将不起作用
这可能足以解决您的问题,但如果您需要同时在两个框中选择相应索引的代码,请参阅:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
listBox2.SelectedIndex = listBox1.SelectedIndex;
}
private void listBox2_SelectedIndexChanged(object sender, EventArgs e)
{
listBox1.SelectedIndex = listBox2.SelectedIndex;
}
这似乎是一项复杂的任务。然而,在的帮助下,我设法找到了这个解决方案 您必须创建一个类似于
listBox
的新控件,该控件的事件已滚动
,这可以使用此方法完成
在项目内部,右键单击项目节点并选择添加用户控件(Windows窗体),将其命名为ScrollingListBox.cs。它将与名为“ScrollingListBox.Designer.cs”的文件一起出现在解决方案资源管理器中,右键单击后一个文件并将其删除,然后选择“ScrollingListBox.cs”,右键单击它并选择“查看代码”,或按F7,然后用以下代码替换其内容:
using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Scroll
{
public partial class ScrollingListBox : ListBox
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
[Category("Action")]
public event ScrollEventHandler Scrolled = null;
private const int WM_VSCROLL = 0x115;
private const int SB_ENDSCROLL = 0x8;
private const int SIF_RANGE = 0x1;
private const int SIF_PAGE = 0x2;
private const int SIF_POS = 0x4;
private const int SIF_TRACKPOS = 0x10;
private const int SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;
private struct ScrollInfoStruct
{
public int cbSize;
public int fMask;
public int nMin;
public int nMax;
public int nPage;
public int nPos;
public int nTrackPos;
}
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetScrollInfo(IntPtr hWnd, int n, ref ScrollInfoStruct lpScrollInfo);
protected override void WndProc(ref System.Windows.Forms.Message msg)
{
if (msg.Msg == WM_VSCROLL)
{
if (Scrolled != null)
{
ScrollInfoStruct si = new ScrollInfoStruct();
si.fMask = SIF_ALL;
si.cbSize = Marshal.SizeOf(si);
GetScrollInfo(msg.HWnd, 0, ref si);
if (msg.WParam.ToInt32() == SB_ENDSCROLL)
{
ScrollEventArgs sargs = new ScrollEventArgs(ScrollEventType.EndScroll, si.nPos);
Scrolled(this, sargs);
}
}
}
base.WndProc(ref msg);
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
}
}
到
还有这条线和类似的线,
this.listBox1 = new System.Windows.Forms.ListBox();
private System.Windows.Forms.ListBox listBox1;
到
现在,您可以使用此事件检测一个框中发生的滚动,并相应地修改另一个框,如下所示:
private void listBox1_Scrolled(object sender, ScrollEventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_Scrolled(object sender, ScrollEventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
private void listBox1_MouseHover(object sender, EventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_MouseHover(object sender, EventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
private void listBox1_MouseMove(object sender, EventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_MouseMove(object sender, EventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
这可以通过单击滚动条的箭头或用鼠标抓图来滚动滚动条,但不适用于在框内使用鼠标滚轮。我尝试使用事件mouseweel
来解决此问题,但不幸的是,它没有按预期工作,因此我找到的唯一选项是使用事件MouseHover
和MouseMove
来完成此操作,如下所示:
private void listBox1_Scrolled(object sender, ScrollEventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_Scrolled(object sender, ScrollEventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
private void listBox1_MouseHover(object sender, EventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_MouseHover(object sender, EventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
private void listBox1_MouseMove(object sender, EventArgs e)
{
listBox2.TopIndex = listBox1.TopIndex;
}
private void listBox2_MouseMove(object sender, EventArgs e)
{
listBox1.TopIndex = listBox2.TopIndex;
}
如果您在框的白色区域内的任何位置使用鼠标滚轮,这将起作用。不幸的是,如果您在滚动条上使用鼠标滚轮,这将不起作用
这可能足以解决您的问题,但如果您需要同时在两个框中选择相应索引的代码,请参阅:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
listBox2.SelectedIndex = listBox1.SelectedIndex;
}
private void listBox2_SelectedIndexChanged(object sender, EventArgs e)
{
listBox1.SelectedIndex = listBox2.SelectedIndex;
}
好的,谢谢你们帮我。我使用了带有两列的
DataGridView
,正如@41686d6564所建议的那样,它就像一个符咒
好的,谢谢你们帮助我。我使用了带有两列的
DataGridView
,正如@41686d6564所建议的那样,它就像一个符咒
这是可行的,但为什么要重新发明轮子呢?改为使用带有两列的DataGridView。那么您检查了其他帖子,什么不起作用?您的问题的当前状态将与您所指的帖子重复。@41686d6564确实DataGridView可以工作,但这需要在项目中进行大量更改。我将检查并尝试实施它。能否请您也指导我关于如何同步两个列表框滚动的初始问题?@nilsK我的项目中缺少了他们所指的许多东西(例如syncListView1_OnVerticalScroll)。@很好奇,很抱歉,我现在没有时间编写和测试一些我认为没有用的代码。同样,不要试图重新发明轮子。使用DataGridView、ListView或任何可以包含列的控件,而不是试图模仿行为。这是可行的,但为什么要重新发明轮子呢?改为使用带有两列的DataGridView。那么您检查了其他帖子,什么不起作用?您的问题的当前状态将与您所指的帖子重复。@41686d6564确实DataGridView可以工作,但这需要在项目中进行大量更改。我将检查并尝试实施它。能否请您也指导我关于如何同步两个列表框滚动的初始问题?@nilsK我的项目中缺少了他们所指的许多东西(例如syncListView1_OnVerticalScroll)。@很好奇,很抱歉,我现在没有时间编写和测试一些我认为没有用的代码。再次强调,不要试图重新投资