2008-10-18 11 views
3

Lorsque j'accepte le support de style visuel de contrôle commun (InitCommonControls()) et que j'utilise un thème autre que Windows Classic Theme, les boutons d'une boîte de groupe apparaissent avec une bordure noire avec des coins carrés.Comment placer des sous-contrôles dans une boîte de groupe?

Le thème Windows Classic apparaît normal, de même que lorsque j'éteins le style visuel.

J'utilise le code suivant:

group_box = CreateWindow(TEXT("BUTTON"), TEXT("BS_GROUPBOX"), 
    WS_CHILD | WS_VISIBLE | BS_GROUPBOX | WS_GROUP, 
    10, 10, 200, 300, 
    hwnd, NULL, hInstance, 0); 

push_button = CreateWindow(TEXT("BUTTON"), TEXT("BS_PUSHBUTTON"), 
    WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 
    40, 40, 100, 22, 
    group_box, NULL, hInstance, 0); 

EDIT: Le problème se produit avec des boutons radio et

EDIT: Je n'utilise pas les boîtes de dialogue/ressources, seulement CreateWindow/Ex.

Je compile sous Visual C++ 2008 Express SP1, avec un fichier manifest générique

Screenshot http://img.ispankcode.com/black_border_issue.png

+0

La bordure noire apparaît-elle autour de tous les boutons, ou seulement celle de l'image que vous avez fournie? – RobS

+0

Tous les boutons. Si j'utilise Windows Classic Theme, ils apparaissent normalement. –

+0

À quoi ressemble l'appel CreateWindow pour la boîte de dialogue parent elle-même? Je me demande simplement s'il y a une sorte d'héritage qui se passe. – RobS

Répondre

4

Le problème est que la zone de groupe est le parent des contrôles. Les Groupbox ne sont pas censés avoir d'enfants et leur utilisation en tant que parents entraînera toutes sortes d'erreurs (y compris la peinture, la navigation au clavier et la propagation de messages). Changez simplement le parent dans l'appel CreateWindow des boutons de group_box à hwnd (c'est-à-dire la boîte de dialogue).

Je suppose que vous avez utilisé la zone de groupe comme parent afin de positionner les autres contrôles facilement à l'intérieur. La bonne façon de procéder est d'obtenir la position de la zone client de la zone de groupe et de la mapper à la zone client de la boîte de dialogue. Tout ce qui est placé dans RECT apparaîtra alors dans la zone de groupe. Étant donné que ne sont pas les boîtes de groupe en fait un espace client, il peut être calculé avec quelque chose comme ceci:

// Calculate the client area of a dialog that corresponds to the perceived 
// client area of a groupbox control. An extra padding in dialog units can 
// be specified (preferably in multiples of 4). 
// 
RECT getClientAreaInGroupBox(HWND dlg, int id, int padding = 0) { 
    HWND group = GetDlgItem(dlg, id); 
    RECT rc; 
    GetWindowRect(group, &rc); 
    MapWindowPoints(0, dlg, (POINT*)&rc, 2); 

    // Note that the top DUs should be 9 to completely avoid overlapping the 
    // groupbox label, but 8 is used instead for better alignment on a 4x4 
    // design grid. 
    RECT border = { 4, 8, 4, 4 }; 
    OffsetRect(&border, padding, padding); 
    MapDialogRect(dlg, &border); 

    rc.left += border.left; 
    rc.right -= border.right; 
    rc.top += border.top; 
    rc.bottom -= border.bottom; 
    return rc; 
} 

Notez que la même pour les contrôles des onglets. Eux aussi ne sont pas conçus pour être des parents et présenteront un comportement similaire.

+0

Comment exactement "obtenez-vous la position de la zone client groupbox"? 'GetClientRect' donne la zone incluant les bordures et le titre qui ne permet pas de placer sans dessiner quelque chose. – nwp

+0

@nwp, bonne question. Je n'ai pas trouvé l'implémentation d'origine, mais j'ai mis à jour ma réponse avec une solution possible. C'est essentiellement un hack impliquant des unités de dialogue. – efotinis

1

Juste une supposition, mais il semble que vous héritez soit le bord statique ou le style Edge client de vous thème. Je crée la plupart de mes boîtes de dialogue à partir de l'éditeur de ressources et définissez ces propriétés ici.

Dans votre cas, vous pouvez remplacer votre CreateWindow par un CreateWindowEx pour définir ces styles étendus, qui sont probablement définis par défaut dans CreateWindow. Spécifiquement vérifier WS_EX_STATICEDGE, WS_EX_WINDOWEDGE and WS_EX_CLIENTEDGE

Editer: Je suppose que cela ne se produit pas parce que le bouton est le contrôle par défaut dans la boîte de dialogue, ce qui donnerait également un bord noir.

0

Apparemment, les boîtes de groupe ne sont pas destinés à des commandes de groupe (être un de hwnd parent)

Ainsi, afin de se débarrasser des bordures noires/problèmes de peinture que je dois sous-classe boîte de groupe et mettre en œuvre WM_PAINT et WM_PRINTCLIENT

-2

Ahh oui le fond noir avec des boutons radio et des boîtes de groupe. Bien que je ne sache pas si cela fonctionnera pour VC++ 2008, la solution pour les applications sur le thème de VB6 était de placer d'abord les contrôles radio sur un PictureBox (un conteneur générique), puis de l'ajouter au boîte de groupe.

Ça vaut le coup!

Questions connexes