MFC: how to create an Aero combo box for drawing owner?

I inherited a large MFC application that contains a subclass CComboBox

that overrides OnPaint

. It currently does all of its drawings by hand (with lines and rectangles) and displays a combo box that looks explicitly Windows 98 style. Otherwise, it works fine, and provides a lot of useful custom features that we rely on and rewriting the whole control is probably not an option.

I would like to modernize it to OnPaint

paint in the Aero style where it was available (going back to old code when modern theme is not available). I did it with some other custom controls like buttons and it works great for our purposes. I know there are a few tiny behaviors that won't get right, like subtle tints on hover, but that's not very important for this application.

I have access to the CVisualStylesXP

cascade, so I already have a framework to make calls like OpenThemeData

, GetThemeColor

or DrawThemeBackground

fairly easy (via LoadLibrary

, so we don't force Vista as a mini-system). Unfortunately I don't know the correct call sequence to get a nice combo box with a theme-appropriate border and a dropdown button.

Does anyone know what to do here?


source to share

3 answers

To be honest, I don't know why they originally tried to override OnPaint. Is there a good reason? I think at least 99% of the time you just want to override the drawing of the items in the ComboBox. To do this, you can override DrawItem, MeasureItem, and CompareItem in a derived combo box to get the functionality you want. In this case, the OS correctly draws the non-user content specific to each OS.



I think it is best to shoot without diving deep into xp themed and various system metrics is to look at this project:

Check out the OnPaint of the CAdvComboBox class - there is a complete implementation of repainting controls, including issues related to the xp theme.



Not sure if in the same situation - but when I ran into this problem (in my case with subclass CButtons), solving it required only changing the declaration of the control to a pointer and dynamically creating the control.

Let's assume your subclass control is named CComboBoxExt.
Where are you

CComboBoxExt m_cComboBoxExt;


Now you will have

CComboBoxExt* m_pcComboBoxExt; 


And in the OnInitDialog of the window that the control is in, you create it with

m_pcComboBoxExt = new CComboBoxExt();  


Since this is now a pointer, remember to call DestroyWindow()

and delete the pointer on completion.

This solved my specific problem - if your control is declared in the same way, try giving it a try.



All Articles