
I got really tired of having to add all items in the InitDialog function, which can be really annoying in the case where you have several CAdvComboBox in one page. This class will now look for an entry in the stringtable with the same ID as the CAdvComboBox control has in the resource editor. The demo project has been upgraded to display this feature. More information about this has been added under Installation. If you want to add another stringtable entry, just call the new function LoadString(UINT nID) where nID refers to the stringtable entry.
In this version, I have added the code so the CAdvComboBox can be used with the macro RUNTIME_CLASS. Requested by Krishna.
I've also added the missing functionality that opens the dropdown window by pressing Alt-Down or Alt-Up. This was requested by Thomas Freudenberg.
I started to work on a control that I was going to use in another program that had combo boxes within a
CListBox. The first criteria that I wanted was that the combobox should be
flat (no shadows). I looked around for a while and could not find any suitable so I had to create my own somehow. When I had started to work on the flat combobox, I come to think of another cool feature that would be nice to have. How many times have you wanted the same functionality as the address bar in IE. When you type an address and the
IAutoComplete COM-object goes to work. Wonderful!...or not. I wanted the same functionality in a my combobox, and especially the resizeable dropdown window. And so, back to the drawing board. After many long nights and several different approaches, I got it to work.
This ComboBox is not subclassing the MFC's CComboBox mostly because I wanted to be able to resize the drop-down window. Instead, I created a
CWnd object that looks almost the same as MFC's CComboBox. The tricky part was to get the dropdown window to react the same way as
CComboBox. First of all, the dropdown window has to be a child to the desktop, and then there is the nasty problem with the mouse and keyboard capture. The solution to that problem was to have one window that has a listbox and a scrollbar within itself. The scrollbar that the
CListBox class uses could not be used due to the capture problem.
During the development more features were added; checked items and disabled items in the dropdown window.
Below is a picture over the class structure.

Picture 1
The dropdown window of the AdvComboBox is of an autosize style, that is, it calculates the size it needs to show all items in the list.
So the result is a combobox that acts almost the same as the MFC's CComboBox. You should not have to change any code that are already in use, besides that you have to change the resource from the standard combobox to a custom control. I have tested on W2K and XP. Now I turn to CodeProject's members and other to help me test and find bugs, and maybe some new features to add.
Installation Index
Create a new project
Upgrade your current project
Use CAdvComboBox in a MFC DLL
This article contains of three different ways of implementing the CAdvComboBox class into your project.
One describes the workorder for a new project, and the second how to upgrade your current projects, and the last how
to implement the CAdvComboBox in a MFC DLL.
AdvComboBox.h
AdvComboBox.cpp
DropWnd.h
DropWnd.cpp
DropListBox.h
DropListBox.cpp
DropScrollBar.h
DropScrollBar.cpp
VisualStylesXP.h
VisualStylesXP.h
CAdvComboBox custom control class name is AdvComboBoxCtrl which is defined in
AdvComboBox.h.

Picture 2
| Combo style | Value in property window |
| CBS_DROPDOWN | 0x_____002 |
| CBS_DROPDOWNLIST | 0x_____103 |
| CBS_AUTOHSCROLL | 0x_____043 |
| CBS_SORT | 0x_____103 |
CBS_DROPDOWN,
CBS_AUTOHSCROLL, and CBS_SORT
the style value should end with 142(as seen in picture 2). You can also edit the resource file in text mode and add the styles
there. The resouce editor then translate the style you have choosen into this value.
The following styles has not been implemented yet:
CBS_DISABLENOSCROLL
CBS_HASSTRINGS
CBS_LOWERCASE
CBS_NOINTEGRALHEIGHT
CBS_OEMCONVERT
CBS_OWNERDRAWFIXED
CBS_OWNERDRAWVARIABLE
CBS_SIMPLE
CBS_UPPERCASE
CAdvComboBox m_ctlAdvCombo;
DDX_Control(pDX, IDC_ADV_COMBO, m_ctlAdvCombo);Add it outside of
AFX_DATA_MAP to
avoid any mishaps in the future. DoDataExchange(...) should look like this:
void CAdvCBDemoDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAdvCBDemoDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP DDX_Control(pDX, IDC_ADV_COMBO, m_ctlAdvCombo); }
Another feature that still has to be implemented is how to get and set data from the control. This is described below.
DDX_CBIndex and DDX_CBString should be changed to DDX_ACBIndex and
DDX_ACBString for it to work. These functions can be found in the AdvComboBox.cpp file.
To add functionality to get and set data add one of, or both, the following variables in your AdvCBDemoDlg.h file
int m_nAdvCombo;
CString m_strAdvCombo;
You also have to initialize the value to these variables in the constructor of CAdvCBDemoDlg.
Add the following code outside AFX_DATA_INIT.
m_nAdvCombo = -1; m_strAdvCombo = "";Add also the DDX_ calls in the function
DoDataExchange(...) in AdvCBDemoDlg.cpp file below the
DDX_Control that you added in step 6.
DDX_ACBIndex( pDX, IDC_ADV_COMBO, m_nAdvCombo ); DDX_ACBString( pDX, IDC_ADV_COMBO, m_strAdvCombo );
You should now be able to use the AdvComboBox control in the same way as the MFC's CComboBox.
The following was added in version 2.1
CAdvComboBox list.'\n') represents the ending of one item in the combobox list. Please look into the demo project for further information on how to implement this.

Picture 3
AdvComboBox.h
AdvComboBox.cpp
DropWnd.h
DropWnd.cpp
DropListBox.h
DropListBox.cpp
DropScrollBar.h
DropScrollBar.cpp
VisualStylesXP.h
VisualStylesXP.h
CComboBox variable definitions to CAdvComboBox in your header file.Tip! Use the same ID for your custom controls as you had for the comboboxes. This makes it a lot easier
further on so that you won't have to change ID's for all your events(ON_CBN_SELCHANGE, etc.) currectly assigned
to the standard comboboxes.
DDX_CBIndex and DDX_CBString to DDX_ACBIndex and
DDX_ACBString in your .cpp file. Change the ID's in these calls if you didn't set the same ID's on
your new custom controls as you had on the old comboboxes.
CAdvComboBox.
CAdvComboBox. To be able to register the class, you have to change the code somewhat.
The HINSTANCE in the structure WNDCLASS must have the DLL's HINSTANCE, and not the
calling applications HINSTANCE.CAdvComboBox m_ctlAdvCombo( TRUE )
HINSTANCE variable the the DLL project.HINSTANCE g_hDLLInstance = NULL;Then, add the
extern definition in the StdAfx.h file like this:
extern HINSTANCE g_hDLLInstance;
hDllInstance in the DllMain function.
g_hDLLInstance = hInstance;
RegisterWindowClass() in the AdvComboBox.cpp file. Change the
function so it looks like this:
BOOL CAdvComboBox::RegisterWindowClass()
{
WNDCLASS wndcls;
HINSTANCE hInst;
if( m_bInst )
{
hInst = g_hDLLInstance;
}
else
{
hInst = AfxGetInstanceHandle();
}
ASSERT( hInst != 0 );
...
return TRUE;
}
class __declspec(dllexport) CAdvComboBox : public CWndDDX_ Definitions:
_declspec(dllexport) void AFXAPI DDX_ACBIndex( CDataExchange* pDX, int nIDC, int& index ); _declspec(dllexport) void AFXAPI DDX_ACBString( CDataExchange* pDX, int nIDC, CString& value );
CAdvComboBox class are the same as in MFC's CComboBox. For mor help on
those, look in MSDN.| Description: | Retrieve the pos and size of the combobox with this function |
| Definition: | CRect& GetComboRect() |
| Returns: | Rect of the AdvComboBox |
| Description: | Returns the default number of visible items of the dropdown window.
To set the default number, use SetDefaultVisibleItems(int) |
| Definition: | int GetDefaultVisibleItems() |
| Returns: | Number of items. |
| Description: | Get the checked status of an item |
| Definition: | BOOL GetItemChecked( int nIndex ) |
| Parameter: | nIndexItem index in list |
| Returns: | TRUE if item nIndex is checked, or CB_ERR if an error occurred. |
| Description: | Get the disabled status of an item |
| Definition: | BOOL GetItemDisabled( int nIndex ) |
| Parameter: | nIndexItem index in list |
| Returns: | TRUE if item nIndex is disabled, or CB_ERR if an error occurred. |
| Description: | Get the minimum visible listbox items in the dropwindow, before the dropwindow will be placed above the combobox. |
| Definition: | int GetMinVisibleItems() |
| Returns: | Number of minimum visible listbox item. |
| Description: | Load an entry from the stringtable and add the items in that entry in the dropwindow list. |
| Definition: | void LoadString( UINT nStringID ) |
| Parameter: | nStringIDID of the string to load. |
| Returns: | void |
| Description: | Modify the style of the CAdvComboBox. The available styles can be found here. This function handles only the ACBS_ styles. It work as MFC's ModifyStyle. |
| Definition: | void ModifyACBStyle(UINT nRemoveStyle, UINT nAddStyle) |
| Parameter: | nRemoveStyleACBS style to remove. |
| Parameter: | nAddStyleACBS style to add. |
| Returns: | void |
| Description: | Is a CPoint within the combobox rect? |
| Definition: | BOOL PointInWindow( CPoint ptScreenPoint ) |
| Parameter: | ptScreenPointIs this point within the combobox. |
| Returns: | TRUE if the point is in combobox window. |
| Description: | Set the default visible number of items in the dropdown window. |
| Definition: | void SetDefaultVisibleItems( int nItems = -1 ); |
| Parameter: | nItemsNumber of items to be visible when the dropdown window is shown. Set this to -1 if the style should be autosize. |
| Returns: | void |
| Description: | Set an item in combo to either check or un-checked. |
| Definition: | void SetItemChecked( int nIndex, BOOL bChecked ) |
| Parameter: | nIndexZero-based item index to the item to set. |
| Parameter: | bCheckedNew state of the item to set. |
| Returns: | void |
| Description: | Set an item in combo to either disabled or enabled. |
| Definition: | void SetItemDisabled(int nIndex, BOOL bDisabled) |
| Parameter: | nIndexZero-based item index to the item to set. |
| Parameter: | bDisabledNew state of the item to set. |
| Returns: | void |
| Description: | Set the minimum visible listbox items in the dropwindow, before the dropwindow will be placed above the combobox. The default is five items. |
| Definition: | void SetMinVisibleItems(int nMinItems) |
| Parameter: | nMinItemsNumber of minimum listbox items. |
| Returns: | void |
| Description: | Use this function to get and set data with MFC's UpdateData(...) |
| Definition: | void AFXAPI DDX_ACBIndex( CDataExchange* pDX, int nIDC, int& index ) |
| Description: | Use this function to get and set data with MFC's UpdateData(...) |
| Definition: | void AFXAPI DDX_ACBString( CDataExchange* pDX, int nIDC, CString& value ) |
Below is a list of CComboBox functions implemented in CAdvComboBox.
AddStringDeleteStringFindStringFindStringExactGetCountGetCurSelGetDroppedControlRectGetDroppedStateGetEditSelGetItemDataGetItemDataPtrGetLBTextGetLBTextLenGetTopIndexInsertStringLimitText New in ver 1.2ResetContentSelectStringSetCurSelSetEditSelSetItemDataSetItemDataPtrSetTopIndexShowDropDownThe following CComboBox functions are not implemented in CAdvComboBox
ClearCompareItemCopyCutDirDrawItemDeleteItemGetDroppedWidthGetExtendedUIGetHorizontalExtentGetItemHeightGetLocaleMeasureItemPasteSetDroppedWidthSetExtendedUISetHorizontalExtentSetItemHeightSetLocaleCAdvComboBox sends the following notifications to the parent, as MFC's CComboBox does.
CBN_CLOSEUPCBN_DROPDOWNCBN_EDITCHANGECBN_EDITUPDATECBN_KILLFOCUSCBN_SELCHANGECBN_SELENDCANCELCBN_SELENDOKCBN_SETFOCUSThe following notifications are not sent.
CBN_DBLCLK CBS_SIMPLE and CAdvComboBox does not support this style.
CBN_ERRSPACECAdvComboBox has its own styles. They are described here.
ACBS_FLATACBS_STANDARDACBS_CHECKEDACBS_AUTOAPPENDACBS_AUTOSUGGESTThe CAdvComboBox supports the following CComboBox styles
CBS_AUTOHSCROLLCBS_DROPDOWNCBS_DROPDOWNLISTCBS_SORT
The following CComboBox styles are not supported
CBS_DISABLENOSCROLLCBS_HASSTRINGSCBS_LOWERCASECBS_NOINTEGRALHEIGHTCBS_OEMCONVERTCBS_OWNERDRAWFIXEDCBS_OWNERDRAWVARIABLECBS_SIMPLECBS_UPPERCASECComboBox so the ClassWizard can help you with notification implementation like
ON_CBN_SELCHANGE. When you have created all events for the combobox, change to CAdvComboBox.
This is the easiest and fastest way to implement this class.OnInitDialog() to ModifyACBStyle(...) like this:m_ctlAdvCombo.ModifyACBStyle( 0, ACBS_FLAT );
CComboBox please.
LoadString(UINT)RUNTIME_CLASS can now be used.CAdvComboBox can be used with the macro RUNTIME_CLASS. Requested by Krishna.GetDefaultVisibleItems()SetDefaultVisibleItems(int)CAdvComboBox style ACBS_AUTOAPPENDCAdvComboBox style ACBS_AUTOSUGGESTCAdvComboBox is now also compatible with CommCtrl 6.0 manifest.CVisualStylesXP as the working ground, but I have added some functionality like the functions fetched from the DLL is now static functions, and a function that checks the CommCtrl DLL version to see if we are able to use visual styles. If a manifest is not used, this function will tell us just that even if we're running on WinXP.CAdvCombBox class with the function Create(...)
and the style was CBS_DROPDOWN. Thanx for finding this bug.CComboBox function LimitText is now implemented._WIN32_WINNT is removed.SetMinVisibleItems(int) in CAdvComboBox class.| You must Sign In to use this message board. | |||||
|
|||||
|
|||||