Download source files - 17 Kb
One of the more frustrating aspects of a user interface can be the situation where
you are presented with a list of choices in a combobox, but are unable to view the
choices because the dropdown list is too narrow.
This article presents an extremely simple
CCombobox derived class
that will always present a list that is wide enough to hold the widest string.
A new class
To start we use the ClassWizard to create a new class
Then use the class wizard to add an override for the reflected message CBN_DROPDOWN.
A reflected message is a message that the control sends to its parent, but which the
parent lets the control have a chance at processing first. The "=" before the CBN_DROPDOWN
in the ClassWizard indicates it's a reflected message.
Call the message handler
OnDropDown and add the following code
Then add the function
RecalcDropWidth to your
we are doing is that each time the combo displays it's drop down, we are intercepting the
message and calling a function to quickly check and the size of the control's dropdown
before it gets a chance to display it.
The code for
RecalcDropWidth is as follows
int nNumEntries = GetCount();
int nWidth = 0;
int nSave = dc.SaveDC();
int nScrollWidth = ::GetSystemMetrics(SM_CXVSCROLL);
for (int i = 0; i < nNumEntries; i++)
int nLength = dc.GetTextExtent(str).cx + nScrollWidth;
nWidth = max(nWidth, nLength);
nWidth += dc.GetTextExtent("0").cx;
Thanks to Eugeny Berezkin for pointing out that the combo draws its dropdown list with a
Essentially what we are doing is getting a device context that we can use to calculate
the size of each string to be displayed in the combo. We then ensure that we are performing
these calculations with the correct font, and then iterate through the list and work out
the maximum width. We then add a small margin to replicate the on-screen behaviour of the
drop down. Once that is done we call
CComboBox::SetDroppedWidth to set the
Using the new class
So - we now have a class that does what we want - but how do we use it?
CMyComboBox is a drop-in replacement for
Simply include the MyComboBox.h header file where appropriate, and change your
combobox's class from
Alternatively, you can use the ClassWizard to associate a variable with your combobox.
Go to the Member Variables tab in ClassWizard and select the Form or Dialog class that
contains your combobox control. Choose "Add Variable...", specify a name, set the Category
as "Control" and then set the variable type as
If you used the MyComboBox files from the download files for this article and
simply included them in your project without rebuilding the class file (delete the .clw
file from your directory and hit Ctrl+W) then
CMyComboBox may not appear
in the list of available combobox classes. If this happens simply choose
and then go into your Form or Dialogs header file and manually change
Chris is the Co-founder, Administrator, Architect, Chief Editor and Shameless Hack who wrote and runs The Code Project. He's been programming since 1988 while pretending to be, in various guises, an astrophysicist, mathematician, physicist, hydrologist, geomorphologist, defence intelligence researcher and then, when all that got a bit rough on the nerves, a web developer. He is a Microsoft Visual C++ MVP both globally and for Canada locally.
His programming experience includes C/C++, C#, SQL, MFC, ASP, ASP.NET, and far, far too much FORTRAN. He has worked on PocketPCs, AIX mainframes, Sun workstations, and a CRAY YMP C90 behemoth but finds notebooks take up less desk space.
He dodges, he weaves, and he never gets enough sleep. He is kind to small animals.
Chris was born and bred in Australia but splits his time between Toronto and Melbourne, depending on the weather. For relaxation he is into road cycling, snowboarding, rock climbing, and storm chasing.