2009-11-01 2 views
4

Je suis sous-classe d'une liste déroulante WTL et je dessine les éléments de la liste déroulante. Le contrôle a les attributs CBS_DROPDOWNLIST | CBS_HASSTRINGS | CBS_OWNERDRAWVARIABLE et j'utilise la classe de mélange COwnerDraw pour implémenter DrawItem() et MeasureItem(). Lorsque la liste déroulante est désactivée, les éléments sont dessinés correctement. Toutefois, lorsque la liste déroulante est en haut, le contrôle de zone de liste déroulante est vide et l'élément n'est pas dessiné. Qu'est-ce que je fais mal?Pourquoi mon combobox dessiné par le propriétaire est-il vide?

La classe WTL ressemble à ceci:

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; 
    } 
}; 

La classe est utilisée sur une boîte de dialogue et est sous-comme ceci:

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

Modification des attributs de contrôle à CBS_OWNERDRAWFIXED ne change rien.


Edit: Merci à l'aide de Najmeddine je me suis dit que je dois gérer WM_PAINT pour dessiner la combobox réelle, et non seulement les éléments dans la liste déroulante. Malheureusement maintenant je dois aussi dessiner le contrôle combobox tout seul. Y a-t-il un moyen de laisser le GDI dessiner la bordure et de laisser tomber la flèche pour que je n'aie qu'à dessiner les "faces" du contrôle?

+0

J'essaye de faire la même chose, avec un succès mitigé (utilisant actuellement DrawThemeBackground). Pourriez-vous trouver une solution fiable pour dessiner la flèche de la liste déroulante? – phimuemue

+1

Je n'ai pas implémenté la suggestion de David M, je n'ai traité que le message WM_PAINT pour dessiner la combobox moi-même. – vividos

Répondre

6

Pour dessiner le contrôle combobox vous devez utiliser les API de thème dans votre gestionnaire WM_PAINT (dans XP + - vous ne dites pas ce que les versions Windows, vous devez prendre en charge.) Plus précisément, utilisez DrawThemeBackground et passer dans l'un des CB_ values for iPartId. Vous aurez également besoin d'utiliser le buffered paint APIs pour gérer les transitions sur Vista, ce qui peut compliquer votre gestionnaire de peinture - cela et d'autres problèmes de dessin lorsque la peinture personnalisée d'un contrôle de zone de liste déroulante est explained here avec beaucoup de détails. Je suggère d'utiliser ce fil de discussion comme référence principale pour implémenter ceci.

+0

Pour référence future: DrawThemeBackground propose différentes parties à dessiner, entre autres 'CP_READONLY' (d'après ce que j'ai vu, correspondant à' CBS_DROPDOWNLIST'). Malheureusement, 'CP_READONLY' n'incorpore pas la flèche de la liste déroulante. Mais il y a toujours 'CP_DROPDOWNBUTTONRIGHT', mais ceci n'est pas seulement la flèche, mais contient une bordure, donc il ne peut pas être utilisé avec' CP_READONLY' tout de suite (voir https://stackoverflow.com/questions/47199120/ draw-themed-combobox-on-windows? noredirect = 1 # comment81352380_47199120). – phimuemue

0

Sur DrawItem, vous remplissez un rect avec de la couleur. Mais où est DrawText ou quelque chose comme ça?

Example of custom DrawItem.

+0

C'est mon dessin personnalisé, remplissant le rect. Pas besoin de sortir du texte. – vividos

0

Pour dessiner le contrôle comboBox (pas la liste), vous devez également gérer le message WM_PAINT et y peindre. L'événement DrawItem peint uniquement la liste déroulante et ses éléments.

+0

va essayer ça ... – vividos

Questions connexes