When searching for strings in Combo boxes, the search is always case-insensitive.
I have a need for a case-sensitive combo box in an application, so I have put
together this class to implement that.
I could have used CComboBoxEx
to give me a case-sensitive ComboBox, but it
wouldn't be a drop-in replacement for a CComboBox
. The methods normally used
in CComboBox
(eg AddString
), are not implemented in CComboBoxEx
. This would
mean a lot of re-coding in order to use it.
How to use it
Using the CComboBoxCS
class is very straightforward. Follow the steps below
to add one to an existing project.
- After putting the source files (ComboBoxCS.cpp and ComboBoxCS.h) into the
directory you wish to use them from, add the files to your Visual Studio project.
- In the resource editor, add a combo where you wish.
- In Class Wizard add a member variable for your combo control, selecting
"Control" from the "Category" list, and selecting "
CComboBoxCS
"
from the "Variable Type" list. (If CComboBoxCS
does not appear in
the list, you may need to delete your class wizard file (.clw) and regenerate
it). I will assume your control variable name is m_combo.
- In order to make the combo case-sensitive, add a handler for
WM_INITDIALOG
in your dialog class if you don't already have one, and add the following code
to it:
m_combo.SetCaseSensitiveSearch();
That's all you need to do.
If you use many Combo boxes which you wish to make them all case-sensitive,
you can set the default for all instances by adding:
m_combo.SetCaseSensitiveSearchDefault();
or alternatively, if you always want this behaviour, you can change the default value in the source code:
BOOL CListBoxCS::ms_bCaseSensitiveSearchDefault = TRUE;
How it works
The list box part of CComboBoxCS
is subclassed to a CListBoxCS
, which provides
the case-sensitivity. (Note that the CListBoxCS
class can be used in place of
a CListBox
should you require a case-sensitive list box). In order to subclass
the list box, there are one or two methods available. One method ('the messy method') is to
handle the WM_CTLCOLOR
message. This is a standard (and well-documented)
method. The other method ('the clean method') is to use the API function GetComboBoxInfo
to ask the combobox for its list control. The drawback with the clean method is that it is only
available on Win98, or WinNT 4.0 SP6, or later. The code uses LoadLibrary/GetProcAddress to
determine whether the function is available. If it is it uses it, else it falls back to the messy method.
One problem with the messy method, is that the list box doesn't get subclassed
until the user drops the list portion of the combo down. This is not good enough
here, as we need the list to have been subclassed at the time we do a FindString
or FindStringExact
. So, we have to cheat.
On receipt of a FindString
, FindStringExact
,
or SelectString
message, we look to see whether we need
to subclass the list. We need to if we are case-sensitive, and the list has not
yet been subclassed. If we don't need to, then we simply pass the message on
to the standard combobox Windows procedure.
Assuming we do need to subclass, we then call the function to drop the list
portion of the combo. This forces the list to be (re)painted, which causes the
required WM_CTLCOLOR
to be sent to the combobox.
A problem with this is that we get the list box flicking up, and then closing
again. To stop the list flickering, we can't just turn off redraw for the combo,
as that doesn't affect the list, nor can we turn if off for the list, as we
don't have it yet. The code I have used shrinks the combo so its list box is
zero pixels high, and then drops it down. It is then resized to where it came
from. This can all be done while the combo has redrawing turned off.
Using the clean method we don't have any of these problems, and can simply ask the
combobox for a handle to the list box, which we then subclass. This is done at the earliest
time it can be, which will be either as the user types in the edit control, as the list is dropped,
or when the combobox receives a FindString
/FindStringExact
/SelectString
message.
History
Version 2.2.1 - 20 Apr 2007
- Updated to build correctly in VC7 (VS2003) and VC8 (VS2005)
Version 2.2 - 23 Jun 2004
- Renamed
FindString()
method to OnFindString()
, as this was preventing the
use of the standard CComboBox::FindString
method
- added trap for owner-draw messages in the subclassed list to make sure
they are handled by the combo-box, to resolve problems with using the
combo with owner-draw, which in turn made the subclassed list owner-drawn
- made the loading of USER32.DLL to provide
GetComboBoxInfo()
function
happen once only for the life of the app, to prevent it happening each
time a combo-box is sub-classed
- changed handlers for
CBN_EDITCHANGE
and CBN_DROPDOWN
to use
ON_CONTROL_REFLECT_EX
, to allow the control's parent to handle them also
- added handler for
LB_SELECTSTRING
to CListBoxCS
Version 2.1 - 09 Jul 2003
- Updated to support Unicode
Version 2 - 12 Jun 2002
- new (clean) method of subclassing - uses API function
GetComboBoxInfo()
if
available, else falls back to 'messy' method
- added handling of
CB_SELECTSTRING
message
- minor changes to the searching code
Version 1 - 11 Sep 2001