May 282009
 

CComboBox has a function called SetHorizontalExtent which doesn’t work. SDK equivalent is CB_SETHORIZONTALEXTENT which also doesn’t work. The reason for this bug is pretty lame, because WS_HSCROLL style for combo box is not set, which in turn the VS dialog editor does not provide :(. So a workaround is to open .rc file in a text editor and add WS_HSCROLL style manually for this combo.

This is how a combo box will look with a horizontal scrollbar…

Horizontal scrollbar in a combo box

Horizontal scrollbar in a combo box

Here is a sample code from MSDN which is adapted a bit for this purpose…

void CDialoTestDlg::AddHScroll( CComboBox& Cmb )
{
  // Find the longest string in the combo box.
  CString str;
  CSize sz;
  int dx = 0;

  TEXTMETRIC tm = { 0 };
  CDC* pDC = Cmb.GetDC();
  CFont* pFont = Cmb.GetFont();

  // Select the listbox font, save the old font
  CFont* pOldFont = pDC->SelectObject(pFont);

  // Get the text metrics for avg char width
  pDC->GetTextMetrics(&tm);

  for (int i = 0; i < Cmb.GetCount(); i++)
  {
    Cmb.GetLBText(i, str);
    sz = pDC->GetTextExtent(str);

    // Add the avg width to prevent clipping
    sz.cx += tm.tmAveCharWidth;

    if (sz.cx > dx)
      dx = sz.cx;
  }

  // Select the old font back into the DC
  pDC->SelectObject(pOldFont);
  Cmb.ReleaseDC(pDC);

  // Set the horizontal extent so every character of all strings can
  // be scrolled to.
  Cmb.SetHorizontalExtent(dx);
}// End AddHScroll

Setting horizontal extent is useful to prevent the combo’s drop down width from extending beyond screen limits. Note that there is another function called SetDroppedWidth which sets the drop down’s width but with no scrolling.