[MFC] Resize CComboBox drop down list based on contents

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, I’ll be glad to fix those.

Appreciate your comments...