隐藏列表框滚动条和同步滚动
Posted
技术标签:
【中文标题】隐藏列表框滚动条和同步滚动【英文标题】:Hide ListBox Scrollbar & Synchronize Scrolling 【发布时间】:2021-09-20 22:10:00 【问题描述】:我正在使用 3 个列表框控件,并且我想删除它们的滚动条,因此它们的外观可能看起来更干净。
我有它,所以当我在其中选择一个项目时,它会在其余部分中选择相同的项目。唯一的问题是我不知道如何让它们一起滚动。 例如,如果我在第一个 Listbox 中向下滚动,其他两个的位置应该与第一个的位置匹配。
我也想知道如何移除滚动条,因为没有这个属性。
【问题讨论】:
那么,你有 3 个 ListBox 控件,而只有一个有滚动条?否则,你如何滚动第一个?都包含相同的对象吗?否则,您在这些 ListBox 中同步什么? -- 根据您需要处理的内容和方式,您可以隐藏滚动条,如Hiding the Scrollbar while allowing scrolling with the Mouse Wheel in a FlowLayoutPanel。或者创建一个新的自定义控件并删除WS_VSCROLL = 0x00200000
样式(在 CreateParams 中)
@Jimi 我希望有 0 个滚动条,或者最好是右边只有一个,滚动同步它们。
【参考方案1】:
下面是一个去掉了 Vertical ScrollBar 的 ListBox 示例,它可以处理鼠标滚轮消息并自行滚动。
Vertical ScrollBar 默认被移除,除非ScrollAlwaysVisible 属性设置为true
或自定义公共VerticalScrollBar
属性设置为true
。
LisBox 滚动设置其TopIndex 属性。 WndProc 中有一个最小/最大检查,其中处理了 WM_MOUSEWHEEL
,以确保列表不会滚动超出其限制。
这是一种冗余检查,但如果您需要执行更复杂的计算来确定当前偏移量,它可能会派上用场。
当 ListBox 滚动时,它会引发自定义公共 Scroll
事件。如果需要,您可以创建自定义 EventArgs 类以将特定值传递给事件处理程序。在这里,我只是使用 TopIndex
属性同步所有 ListBox 控件。
请注意,鼠标滚轮将 ListBox 滚动 1 个项目,同时按下 SHIFT 会将滚动设置为 3 个项目。根据需要修改此行为。
using System.ComponentModel;
using System.Windows.Forms;
[DesignerCategory("code")]
public class ListBoxEx : ListBox
public event EventHandler<EventArgs> Scroll;
private const int WS_VSCROLL = 0x200000;
private const int WM_MOUSEWHEEL = 0x020A;
private const int MK_SHIFT = 0x0004;
private bool m_VerticalScrollBar = false;
public ListBoxEx()
protected override CreateParams CreateParams
get
CreateParams cp = base.CreateParams;
if (!ScrollAlwaysVisible && !m_VerticalScrollBar)
cp.Style &=~WS_VSCROLL;
return cp;
[DefaultValue(false)]
public bool VerticalScrollBar
get => m_VerticalScrollBar;
set
if (value != m_VerticalScrollBar)
m_VerticalScrollBar = value;
RecreateHandle();
protected override void WndProc(ref Message m)
base.WndProc(ref m);
switch (m.Msg)
case WM_MOUSEWHEEL:
var wparm = m.WParam.ToInt64();
int button = (short)wparm;
int delta = (int)(wparm >> 16);
int direction = Math.Sign(delta);
int steps = button == MK_SHIFT ? 3 : 1;
TopIndex = Math.Max(Math.Min(Items.Count - 1, TopIndex - (steps * direction)), 0);
Scroll?.Invoke(this, EventArgs.Empty);
m.Result = IntPtr.Zero;
break;
将此自定义控件的三个实例添加到一个窗体并订阅第一个的SelectedIndexChanged
事件(例如)。例如,
private void listBoxEx1_SelectedIndexChanged(object sender, EventArgs e)
var lb = (sender as ListBox);
if (listBoxEx2.Items.Count > lb.SelectedIndex)
listBoxEx2.SelectedIndex = lb.SelectedIndex;
if (listBoxEx3.Items.Count > lb.SelectedIndex)
listBoxEx3.SelectedIndex = lb.SelectedIndex;
现在,如果你想同步滚动三个控件,订阅第一个的自定义滚动事件:
private void listBoxEx1_Scroll(object sender, EventArgs e)
var lb = sender as ListBox;
listBoxEx2.TopIndex = lb.TopIndex;
listBoxEx3.TopIndex = lb.TopIndex;
它是这样工作的:代码示例还处理具有不同项目数的 ListBox 控件
编辑:
如何使用:ListBoxEx
是一个自定义控件类。
要创建此控件:
Class
文件,将其命名为ListBoxEx
。
用您在此处找到的类内容覆盖该文件中的类定义。
在此代码中添加 2 个 using
指令。
构建项目。
现在,在工具箱中,您可以找到新的 ListBoxEx 控件。 要复制此处显示的内容:
将它的 3 个实例拖放到一个表单上。 在设计器中,选择第一个对象 (listBoxEx1
)。
在 PropertyGrid 中,切换到事件 (⚡) 视图。找到Scroll
和SelectedIndexChanged
事件并双击每个事件。它将为您创建事件处理程序。
将您在此处找到的事件处理程序的内容复制到刚刚创建的新事件处理程序中。
或者,订阅代码中的事件:
复制您在此处找到的 listBoxEx1_Scroll
和 listBoxEx1_SelectedIndexChanged
处理程序(包括它们的内容)并将它们粘贴到包含 ListBoxEx 控件的表单中。
将此添加到表单构造函数中,在InitializeComponent()
之后,以订阅listBoxEx1
的Scroll
和SelectedIndexChanged
事件:
listBoxEx1.Scroll += this.listBoxEx1_Scroll;
listBoxEx1.SelectedIndexChanged += this.listBoxEx1_SelectedIndexChanged;
【讨论】:
我如何子到自定义滚动事件,事件中没有这个事件。我害怕事件的新手 见编辑中的描述。以上是关于隐藏列表框滚动条和同步滚动的主要内容,如果未能解决你的问题,请参考以下文章