In our WebCopy application we decided to update the User Agent configuration to allow selection from a predefined list of common agents, but still allow the user to enter their own custom agent if required.
Rather than use two separate fields, we choose to use a
ComboBox
in simple mode, which is both a TextBox
and a
ListBox
in a single control. This mode seems somewhat out of
fashion, I think the only place I see it used is in the Font
common dialog, virtually unchanged since Windows 3.1.
The problem was immediately apparent however on firing up WebCopy and going to select a user agent - the agent strings can be very long, far longer than the width of the control.
Unfortunately however, the .NET ComboBox doesn't allow you to directly enable horizontal scrolling. So we'll do it the old fashioned way using the Windows API.
In order for a window to support horizontal scrolling, it needs
to have the WS_HSCROLL
style applied to it. And to setup the
horizontal scrollbar, we need to call the SendMessage
API with
the CB_SETHORIZONTALEXTENT
message.
As usual, we'll be starting off by creating a new Component,
which we'll inherit from ComboBox
.
Traditionally, you would call GetWindowLong
and
SetWindowLong
API's with the GWL_STYLE
or GWL_EXSTYLE
flags. However, we can more simply override the CreateParams
property of our component and set the new style when the control
is created.
With that done, we can now inform Windows of the size of the horizontal scroll area, and it will automatically add the scrollbar if required. To do this, I'll add two new methods to the component. The first will set the horizontal extent to a given value. The second will calculate the length of the longest piece of text in the control and then set the extent to match.
The first overload of SetHorizontalExtent
iterates through all
the items in the control and uses the TextRenderer
object to
measure the size of the text. Once it has found the largest
piece of text, it calls the second overload with the size.
The second overload does the actual work of notifying Windows
using the SendMessage
call, CB_SETHORIZONTALEXTENT
message
and the given width. SendMessage
takes two configuration
parameters per message, but CB_SETHORIZONTALEXTENT
only
requires one, and so we send 0
for the second.
The above function works with all display modes of the ComboBox.
For completeness, here are the API declarations we are using:
As usual, a demonstration project is available from the link below.
Update History
- 2010-07-13 - First published
- 2020-11-21 - Updated formatting
Like what you're reading? Perhaps you like to buy us a coffee?
# ViDom
# ViDom
# Richard Moss
# Max