2017-10-11 9 views
2

J'ai une boîte de dialogue contenant deux zones de liste déroulante, une zone de propriété et une zone non propriétaire.Taille verticale de la zone de liste déroulante propriété du propriétaire plus grande que celle de la zone de liste déroulante non propriétaire

Voici comment ils sont définis dans le fichier .rc:

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 

Ils ont exactement la même hauteur dans le fichier .rc, mais le propriétaire dessiner un (celui du côté gauche) est légèrement supérieur à celui dessiné par le non-propriétaire:

enter image description here.

+0

Vous devez spécifier le style de zone de liste déroulante [CBS_NOINTEGRALHEIGHT] (https://msdn.microsoft.com/en-us/library/windows/desktop/bb775796.aspx), idéalement pour les deux. La différence de hauteur peut être due à une liste déroulante standard utilisant différentes valeurs par défaut d'un propriétaire dessiner un. C'est de la spéculation, cependant. – IInspectable

+0

@IInspectable CBS_NOINTEGRALHEIGHT n'est pas lié, j'ai essayé mais ça ne change rien. Je suppose que c'est seulement pour la liste déroulante. –

Répondre

4

D'abord, la hauteur donnée dans la ressource est la hauteur de la zone de liste déroulante dans l'état déroulant. Ce comportement est par conception. La taille de la hauteur de l'objet combobox est, je crois, déterminée par la hauteur de police de la police affectée au contrôle. Avec une combobox owner-draw, le système n'a aucune idée, donc il vous envoie un WM_MEASUREITEM initialisé avec la taille par défaut de la combobox (probablement en fonction de la police système plutôt que de la police gui).

Vous avez donc besoin de gérer WM_MEASUREITEM dans la boîte de dialogue parent ...

Quelque chose comme cela pourrait aider (le code non validé contre un compilateur):

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); 
} 
+0

Excellent, vous avez sauvé ma journée! J'ai juste laissé tomber dans ce morceau de code et cela fonctionne comme prévu. –

+0

Utile également pour l'utilisation de [__super] (https://msdn.microsoft.com/en-us/library/94dw1w7x.aspx). Je ne savais pas à ce sujet. – acraig5075

+0

Rappelez-vous que __super n'est disponible que dans les compilateurs MS. – xMRi

3

Le combobox est le contrôle le plus horrible Travailler avec Windows lorsqu'il s'agit de taille et de mise en page. Comme il prend également en charge le style "simple" avec des contrôles d'édition et de liste séparés toujours visibles, il n'utilise pas les styles de bordure/bord de fenêtre standard et dessine à la place ses bordures si nécessaire.

La hauteur spécifiée lorsque vous créez le contrôle est en fait la taille utilisée dans l'état déroulant. Il force sa propre taille du contrôle d'édition au moment de l'exécution en fonction de sa police. Parce que tant de gens se sont trompés, l'implémentation thématique ComCtl32 v6 s'assure que la taille de la liste déroulante est saine même si vous lui avez donné une petite taille au départ.

Pour correspondre au système, vous devez essayer de calculer la taille requise dans WM_MEASUREITEM mais la disposition exacte du contrôle par défaut n'est bien sûr pas documentée. C'est probablement la hauteur de la police + la taille métrique du système de SM_C * EDGE et probablement un peu de remplissage.

Si vous avez seulement besoin d'une icône à côté du texte, vous pouvez utiliser le contrôle ComboBoxEx à la place.