views:

467

answers:

3

I'm subclassing a WTL combobox and I'm owner-drawing the items of the combobox. The control has the attributes CBS_DROPDOWNLIST | CBS_HASSTRINGS | CBS_OWNERDRAWVARIABLE and I'm using the mix-in class COwnerDraw to implement DrawItem() and MeasureItem(). When the drop down list is down, the items are drawn correctly. However when the drop down list is up, the combobox control is empty and the item isn't drawn. What am I doing wrong?

The WTL class looks like this:

class CMyComboBox :
   public CWindowImpl<CMyComboBox, CComboBox>,
   public COwnerDraw<CMyComboBox>
{
public:
   BEGIN_MSG_MAP_EX(CMyComboBox)
      CHAIN_MSG_MAP(COwnerDraw<CMyComboBox>)
      CHAIN_MSG_MAP_ALT(COwnerDraw<CMyComboBox>, 1)
   END_MSG_MAP()

   void DrawItem(LPDRAWITEMSTRUCT lpDIS)
   {
      CDCHandle dc = lpDIS->hDC;
      dc.FillSolidRect(&lpDIS->rcItem, lpDIS->itemID == 0 ?
         RGB(255,0,0) : RGB(0,255,0));
   }

   void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
   {
      lpMeasureItemStruct->itemWidth = 12;
      lpMeasureItemStruct->itemHeight = 12;
   }
};

The class is used on a dialog and is subclassed like this:

   m_cbMy.SubclassWindow(GetDlgItem(IDC_COMBO1));
   m_cbMy.AddString(_T("Item 1"));
   m_cbMy.AddString(_T("Item 2"));

Changing the control attributes to CBS_OWNERDRAWFIXED doesn't change anything.


Edit: Thanks to the help of najmeddine I figured out that I have to handle WM_PAINT to draw the actual combobox, and not only the items in the drop-down list. Unfortunately now I have to also draw the combobox control all by myself. Is there a way to let the GDI draw the border and drop arrow so that I only have to draw the "insides" of the control?

A: 

On DrawItem you filling a rect with some color. But where is DrawText or something like it?

Example of custom DrawItem.

silent
That's my custom drawing, filling the rect. No need to output text.
vividos
A: 

To draw the comboBox control (not the list), you should also handle the WM_PAINT message and do your painting there.
the DrawItem event only paints the drop list and it's items.

najmeddine
will try that out...
vividos
+2  A: 

To draw the combobox control you should use the theme APIs in your WM_PAINT handler (in XP+ - you don't say what Windows versions you need to support.) Specifically, use DrawThemeBackground, and pass in one of the CB_ values for iPartId.

You will also need to use the buffered paint APIs to handle transitions on Vista, which can complicate your paint handler - this and other drawing problems when custom painting a combobox control are explained here in a fair amount of detail. I'd suggest using that forum thread as your main reference implementing this.

David M