2
votes

I have a dialog containing two combo boxes, one owner draw and one non owner draw.

This is how they are defined in the .rc file:

COMBOBOX        IDC_COMBO2,149,49,77,73,
                CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_SORT | VS_VSCROLL
COMBOBOX        IDC_COMBO3,237,49,48,30,
                CBS_DROPDOWNLIST CBS_SORT | WS_VSCROLL

They have exactly the same height in the .rc file, but the owner draw one (the one on the left side) is slightly higher that the non owner drawn one:

enter image description here.

2
You need to specify the CBS_NOINTEGRALHEIGHT combo box style, ideally for both. The difference in height might be due to a standard combo box using different defaults from an owner draw one. That's speculation, though.IInspectable
@IInspectable CBS_NOINTEGRALHEIGHT is unrelated, I tried but it doesn't change anything. I suppose this is only for the drop down listbox .Jabberwocky

2 Answers

4
votes

First the given height in the resource is the height of the combo box in the dropped down state.

This behavior is by design. The size of the combobox item height is I believe determined by the font height of the font assigned to the control. With an owner-draw combobox the system has no idea so it sends you a WM_MEASUREITEM initialized with the default size of the combobox (probably depending on the system font rather than the gui font).

So you need to handle WM_MEASUREITEM in the parent dialog...

Something like this might help (code not validated against a compiler):

void CMyDlg::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
  CClientDC dc(this);
  CFont* pFont = GetFont();
  CFont* pFontPrev = NULL;

  if (pFont != NULL)
    pFontPrev = dc.SelectObject(pFont);

  int iborder = ::GetSystemMetrics(SM_CYBORDER);
  CSize sz = dc.GetTextExtent(_T("0"));
  lpMeasureItemStruct->itemHeight = sz.cy + 2*iborder;

  if (pFont != NULL)
    dc.SelectObject(pFontPrev);

  __super::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
}
3
votes

The combobox is the most horrible control to work with in Windows when dealing with size and layout. Because it also supports the "simple" style with separate edit and listbox controls always visible it does not use the standard window border/edge styles and instead draws its borders when required.

The height specified when you create the control is actually the size used in the dropped-down state. It forces its own size of the edit control at run-time based on its font. Because so many people got this wrong the themed ComCtl32 v6 implementation makes sure the dropdown size is sane even if you gave it a small size initially.

To match the system you need to try to calculate the required size in WM_MEASUREITEM but the exact layout of the default control is of course not documented. It is probably the height of the font + the system metric size of SM_C*EDGE and probably some padding.

If you only need a icon next to the text you can use the ComboBoxEx control instead.