我在互联网上搜索了很久,但没有找到合适的答案。
在我的Windows Form应用程序中,我想要改变属于FlowLayoutPanel的滚动条的宽度。
由于Flow Layout Panel的内容比窗体大,所以滚动条是“自动”添加的。
根据我在网上找到的信息,这似乎有点棘手。
有没有什么解决办法呢?
谢谢!
很抱歉,无法更改单个控件上显示的滚动条的宽度(尽管有一个系统范围的设置会影响所有应用程序中的所有滚动条)。
丑陋的事实是,低贱的滚动条控件比它看起来要复杂得多。基本上,FlowLayoutPanel
上的滚动条是由Windows自身绘制的(而不是.NET Framework),因为在幕后为控件设置了WS_HSCROLL
和/或WS_VSCROLL
窗口样式。 FlowLayoutPanel
不提供任何更改或修改这些内置滚动条如何绘制的工具。与WinForms中的其他更高级的修改不同,我们无法向控件的窗口过程发送此类消息。更糟糕的是,滚动条在FlowLayoutPanel
的非客户区域中绘制,这意味着我们不能仅覆盖其Paint
事件并处理自己绘制滚动条。
不幸的是,如果您真的想自定义滚动条,则必须隐藏内置滚动条并自行创建。 如果您愿意,这并不像听起来那么困难。 这篇文章在CodeProject上提供了一个很好的演示,介绍如何创建自己的可自定义外观的滚动条作为用户控件,并将其用作所选容器控件中的替代品。
Cody Gray的回答是100%正确的,但我想添加更多有关此主题的参考资料。
Windows Forms创建滚动条的方式是通过使用窗口样式WS_HSCROLL
和WS_VSCROLL
。分别对应于启用给定HWND
的水平和垂直滚动条。 HWND
是到"窗口"的本地资源句柄,其在.NET语言中对应于Control
。
从Windows API角度思考,我们必须在创建HWND
时设置窗口样式。这是通过调用CreateWindow
,CreateWindowEx
或SetWindowLong
来完成的。自然而然地,我们可以考虑使用P / Invoke来帮助我们,但这将是相当繁琐的,因为这意味着我们需要从头开始重新实现Windows Forms。
幸运的是,Windows Forms公开了一个属性CreateParams
,该属性可以被覆盖以指定精确的窗口样式,以及其他Control
创建参数。 .NET框架会使用此属性,以便在实例化Control
时能够创建具有适当样式的HWND
。
替换Windows API滚动条的功能实际上比看起来要简单得多;然而,这并不是很明显(至少对我来说是这样,我必须查阅.NET源代码才能找到答案)。为了做到这一点,我们必须选择适当的Control
作为继承对象,以创建我们自己的自定义ScrollableControl。如果我们观察System.Windows.Forms.ScrollableControl
的源代码,我们会发现使用了以下样式:
CreateParams cp = base.CreateParams;
if (HScroll || HorizontalScroll.Visible) {
cp.Style |= NativeMethods.WS_HSCROLL;
}
else {
cp.Style &= (~NativeMethods.WS_HSCROLL);
}
if (VScroll || VerticalScroll.Visible) {
cp.Style |= NativeMethods.WS_VSCROLL;
}
else {
cp.Style &= (~NativeMethods.WS_VSCROLL);
}
ScrollableControl
扩展时,原生的水平和垂直滚动条是基于其内部逻辑启用的。我们可以访问ScrollableControl
的窗口句柄,然后调用SetWindowLong
来隐藏滚动条;但是,我们需要跟踪所有与Windows API交互的地方。实际上,有一个内部函数Control.UpdateStylesCore()
,根据是否应显示滚动条来调用它。这个函数有效地重新应用了窗口样式,最好不要与它争执。更清晰的方法是避免使用Windows API,直接从Control
扩展。然后我们可以提供任何所需的API。UserControl
。这将允许我们使用Visual Studio设计器来简化配置滚动条按钮和轨道。ScrollableControl
的内部工作方式,以提供舒适的用户体验。 panel1.AutoScroll = false;
panel1.VerticalScroll.Maximum = 0;
panel1.VerticalScroll.Visible = false;
panel1.HorizontalScroll.Maximum = 0;
panel1.HorizontalScroll.Visible = false;
panel1.AutoScroll = true;