Oct 072013
Code Snippet to Resize CComboBox Drop Down List
I had this post in my draft for a long time. This code snippet resizes a combo box’s drop down list. Please note an application sends the CB_SETDROPPEDWIDTH message to set the minimum allowable width, in pixels, of the list box of a combo box with the CBS_DROPDOWN or CBS_DROPDOWNLIST style.
Note: MFC function CComboBox::SetDroppedWidth is just a wrapper for CB_SETDROPPEDWIDTH.
// Fill out combo box with strings of random width, for demo purpose only void FillCombo(CComboBox& Combo) { LPCTSTR lpAVeryLongString = _T("This is a very long string, the purpose of which is to test out width calculation of a combo drop down"); TCHAR Buf[200] = {0}; const int Len = _tcslen(lpAVeryLongString); Combo.Clear(); for(int Index = 0; Index < 100; ++Index) { const int TrimLen = rand() % Len; _stprintf_s(Buf, _T("%.*s"), TrimLen, lpAVeryLongString); Combo.AddString(Buf); } } // Resize combo box drop down width based on contents void AutoAdjustComboWidth(CComboBox& Combo) { if(!Combo.GetSafeHwnd() || !::IsWindow(Combo.GetSafeHwnd())) { ASSERT(FALSE); return; } CDC& ComboDC = *Combo.GetDC(); const int RestorePoint = ComboDC.SaveDC(); CFont& ComboFont = *Combo.GetFont(); ComboDC.SelectObject(&ComboFont); int MaxX = -1; const UINT ItemCount = Combo.GetCount(); for(UINT Index = 0; Index < ItemCount; ++Index) { CString Text; Combo.GetLBText(Index, Text); // Get width of item string. const SIZE sz = ComboDC.GetTextExtent(Text); if(sz.cx > MaxX) { MaxX = sz.cx; } }// End for if(MaxX > 0) { const int ScrollWidth = ::GetSystemMetrics(SM_CXVSCROLL); const int Border = ::GetSystemMetrics(SM_CXEDGE) * 2; Combo.SetDroppedWidth(MaxX + ScrollWidth * 2); } ComboDC.RestoreDC(RestorePoint); }
Some people might find this inconvenient as the list box width grows bigger. The way to workaround this issue is to use CComboBox::SetHorizontalExtent function as demonstrated here.
If you see bugs let me know,will fix those.