
ComboBox Tips, Tricks, Techniques and Samples
There are three
types of standard combo boxes. The first and most simple is the somewhat
redundantly name Simple Combo. The combo’s list is always expanded and the user
is only able to select one of the list members, which is then displayed in the
edit portion of the combo. The edit itself does not accept user input. The
second is a variation on the Simple, the Drop List Combo. Like the Simple, the
edit does not accept user input. The list appears upon user demand and the user
may select one of the members from this list. The third is the Dropdown Combo.
Like the Drop List, the combo’s list appears upon user invocation but, unlike
either of the other two, the user may supply new values through the use of the
combo’s edit.
Getting a String From a Drop List In A Dialog
Box - The DDX for a Drop List ComboBox returns an index, not a string.
Here's the fix.
Sort Warning - Searching for an item in a
ComboBox can return unexpected results. Here's why.
Getting the edit window handle.
Sometimes you need to have the window handle of the edit
box that is associated with a ComboBox. This is not something that is directly
available from the ComboBox class itself but you can take advantage of the fact
that the edit box is always going to reside in a known location within the
rectangle defined by the ComboBox control. Once you have that, everything else
just falls into place.
CComboCox combo;
CEdit edit;
// combobox creation ...
// ...
POINT tmpPoint = {1,1};
edit.SubclassWindow( combo.ChildWindowFromPoint(tmpPoint)->GetSafeHwnd() );
Getting a String From a Drop List In A
Dialog Box.
The Drop List Combo’s support in MFC is somewhat less than
optimal. When the user selects an item in a Drop List Combo, you would expect
that the returned value would be a string. Sadly, this is not the case. Instead,
the standard DDX routine extracts the index of the selected item rather
than the string itself for return to the caller. This is not what we or any
normal person would want but that’s what was built for our use. Fear not, for we
are brave of heart, quick of wit and pure in purpose and can provide thee with
the means of thy salvation. Failing that, here’s how to get the Droplist Combo
box to return a real string.
In the H file, declare the routine we are going to insert.
void AFXAPI
DDX_CBString(CDataExchange *pDX, int nIDC, CString& value);
In
the CPP file, implement the code to be executed.
//
The standard CComboBox DDX_CBString macro has a bug in it that
// causes it to fail with combo boxes with the drop list style.
// Ergo, a need for
a hack, err, ah, an elegant amendment to the normal process.
void AFXAPI CMyDlg::DDX_CBString(CDataExchange* pDX, int nIDC, CString& value)
{
HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
if (pDX->m_bSaveAndValidate)
{
// Get current edit item text (or drop list static)
int nLen = ::GetWindowTextLength(hWndCtrl);
if (nLen != -1 && nLen != 0xFFFF)
{
// Get known length
::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1);
}
else
{
// GetWindowTextLength does not work for drop lists assume
// max of 255 characters
::GetWindowText(hWndCtrl, value.GetBuffer(255), 255+1);
}
value.ReleaseBuffer();
}
else
{
// Set current selection based on model string
if (::SendMessage(hWndCtrl, CB_SELECTSTRING, (WPARAM)-1,
(LPARAM)(LPCTSTR)value) == CB_ERR)
{
// Set the
edit text (will be ignored if DROPDOWNLIST)
::SetWindowText(hWndCtrl, value);
}
}
}
There's one additional little thing to be considered. Now that the combo has
been coerced into returning a string from the drop list, we are going to need to
define a place for that string to go. This is going to have to be done manually
because the Wizard is stuck in its own little world of drop lists return
indexes. There are two approaches that you can do.
1 Go into the dialog template and change all of the drop lists to dropdown
combos. Go into the Wizard and associated CStrings with the combos. Go back into
the dialog editor and change the combos back to drop lists.
2 Manually add a CString with an appropriate name for each combo you want to
support. In the H file, declare a CString variable with an appropriate name for
each combo to be supported. In the CPP file, add a CBString macro to the
AFX_DATA_MAP for each of the supported combos.
Sort Warning
The default behavior of a combo at drop list time is to
search for the first item in the list that is equal to or greater than the value
that is in the combo’s edit. If the list is unsorted then even if an exact match
exists further down, the search will terminate early.
For example, let’s say you have an unsorted drop list with
“ZZZ”
“ZZ”
“ORDERS”
“ORDER”
and “ZZ” is in the edit. When the combo’s drop button is
activated we see the selected row as “ZZZ”, not the expected “ZZ”.

Back to top
Subclassing the listbox portion of the combo.

|