I have searched the world wide web without a proper answer.
In my Windows Form application, i want to change the width of a scrollbar that belongs to a FlowLayoutPanel.
The Scrollbar is added "automatically" since the content of the Flow Layout Panel is larger the Form.
From what I've found on the web, it seems to be tricky.
Is there any solution to this?
Cheers!
Cody Gray's answer is 100% correct, though I wanted to add more reference material on the subject matter.
Background
The way that Windows Forms creates scrollbars is through using the window styles
WS_HSCROLL
andWS_VSCROLL
. Respectively, these styles are responsible for enabling the horizontal and vertical scrollbars for a givenHWND
. AnHWND
is a native resource handle to a "window", which in .NET lingo corresponds to aControl
.Thinking from a Windows API perspective, we must set window styles at the time we create the
HWND
. This is done through a call toCreateWindow
,CreateWindowEx
, orSetWindowLong
. Naturally, we may begin to think about using P/Invoke to help us out, but this would be quite a burden as it means we would need to re-implement Windows Forms from scratch.Fortunately, Windows Forms exposes a property,
CreateParams
, that can be overridden to specify the exact window styles, among otherControl
creation parameters. This property is in turn consumed by the .NET framework so that it can create theHWND
with the appropriate styles when theControl
is instantiated.Customizing the Scrollbar
Replacing the Windows API functionality for a scrollbar is actually simpler than it may seem; however, this isn't obvious (well for me anyways, I had to sift through .NET source to find the answer). To do this, we must choose the appropriate
Control
to inherit from to create our own custom ScrollableControl. If we observe the source code forSystem.Windows.Forms.ScrollableControl
, we see the following styles are used:So, in short, when we extend from
ScrollableControl
, the native horizontal and vertical scrollbars are enabled based on its internal logic. We could access theScrollableControl
's window handle and then callSetWindowLong
to hide the scrollbars; however, we would need to keep track of all places thatScrollableControl
interacts with the Windows API. In fact, there is an internal functionControl.UpdateStylesCore()
that is called based on whether or not the scrollbars should be shown. This function effectively reapplies the windows styles above, and it would likely be best not to fight with it. It would be a much cleaner approach to steer away from the Windows API and extend directly fromControl
. We can then provide whatever API's we desire to have.This means we would be looking at re-implementing:
Alternatively, a simple approach might be to create a new
UserControl
. This would allow us to use the Visual Studio designer to simplify configuring our scrollbar buttons and tracks.Whichever path is taken, it will be necessary to see how
ScrollableControl
works internally in order to provide a comfortable user-experience.No, there's no way to change the width of a scrollbar displayed on a single control (although there is a system-wide setting that will affect all scrollbars in all applications).
The ugly truth is that the lowly scrollbar control is far more complicated than it looks. Basically, the scrollbars on the
FlowLayoutPanel
are drawn by Windows itself (rather than the .NET Framework) because of theWS_HSCROLL
and/orWS_VSCROLL
window styles that are set for the control behind the scenes. TheFlowLayoutPanel
doesn't provide any facility to change or modify how these built-in scrollbars are drawn. Unlike other more advanced modifications in WinForms, there are no such messages we can send to the control's window procedure. And to make matters worse, the scrollbars are drawn in the non-client area of theFlowLayoutPanel
, which means we can't just override itsPaint
event and handle drawing the scrollbars ourselves.Unfortunately, if you really want to customize your scrollbars, you're going to have to hide the built-in scrollbars and roll your own. It's not quite as difficult as it sounds, though, if you're up for it. This article on CodeProject provides a good walk-through on creating your own skinnable scrollbar as a user control and use it as a replacement in the container control of your choice.