Je sais, il doit y avoir un moyen d'intégrer un (modales) dialogue comme enfant d'une fenêtre créée avec CreateWindow
. Dans mon cas, je veux les incorporer dans une fenêtre de conteneur défilante, dans laquelle ce conteneur est lui-même un enfant de la fenêtre principale (voir image).Enrobage boîtes de dialogue modales comme fenêtre enfant avec Windows API
Le premier problème que je rencontre est que je veux toujours être en mesure d'utiliser les touches TAB et autres navigation spécifiques de dialogue. Mais comment?
Ma boucle de message:
while (GetMessage(&msg, NULL, 0, 0)) {
if (IsDialogMessage(msg.hwnd, &msg)) continue;
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Edit: Pour des fins d'essai I modifié la boucle:
while (GetMessage(&msg, NULL, 0, 0)) {
if (IsEmbeddedDialogWindow(msg.hwnd)) {
if (IsDialogMessage(msg.hwnd, &msg)) continue;
}
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
while (GetMessage(&msg, NULL, 0, 0)) {
if (IsScrollableContainerWindow(msg.hwnd)) {
if (IsDialogMessage(msg.hwnd, &msg)) continue;
}
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Plus d'informations comment faire de la bonne façon se trouve ici: Using the TAB key to navigate in non-dialogs, redux
Avec cette boucle de message, rien ne se passe si je veux saisir des textes de dialogue comme si le message n'est pas manipulé. Si IsDialogMessage
est supprimé, je peux entrer du texte dans un contrôle d'édition dans l'une des boîtes de dialogue intégrées, mais la navigation dans les boîtes de dialogue ne fonctionne pas comme prévu. Bien sûr, le style WS_TABSTOP
est défini pour les contrôles enfants de boîte de dialogue.
Le récipient de mesure de défilement est créé avec CreateWindowEx
avec des styles WS_CHILD, WS_VISIBLE, WS_VSCROLL, WS_TABSTOP, WS_EX_CONTROLPARENT
et les dialogues sont créés comme des enfants de ce conteneur.
HWND hWndContainer = GroupBarPanelCreate(WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, WS_EX_CONTROLPARENT, hWndMain, 0, 0, 400, 400);
GROUPBAR_PANEL* GroupBarPanel = (GROUPBAR_PANEL*) GetWindowLongPtr(hWndContainer, 0);
// Test embedding dialogs
for (unsigned int i = 0; i < 10; i++) {
HWND hWndDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWndContainer, About, 0);
GroupBarPanelInternalAddLast(GroupBarPanel, hWndChild, hWndDlg, nullptr);
}
Ma GroupBarPanelInternalAddLast
modifier les styles de dialogue non modale en enlevant la légende et des frontières, et veille à ce que WS_CHILD
, WS_VISIBLE
et WS_TABSTOP
est réglé (SetWindowLong(hWndDlg, GWL_STYLE, ...)
). (Également testé style WS_EX_CONTROLPARENT
) Avec SetParent(hWndDlg, hWndContainer)
boîtes de dialogue non modales parent est changé.
Alors qu'est-ce que je manque ici? Comme je l'ai découvert, ni la procédure de fenêtre de contenant ni incorporé (à des fins de test sous-classé) procédure de dialogue presque jamais obtient WM_SETFOCUS
ou WM_KILLFOCUS
messages par exemple, mais pourquoi cela?
Solution: Appel de IsDialogMessage pour la fenêtre de niveau supérieur.
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
if (IsDialogMessage(hWndTopLevel, &msg)) {
continue;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
'IsDialogMessage' doit être passé à' HWND' de la boîte de dialogue candidate, et non à la fenêtre ciblée. –
Eh bien, il devrait être donné le 'HWND' de la fenêtre qui a le style' WS_EX_CONTROLPARENT', et qui est le parent des autres boîtes de dialogue. –
Lors de la création, vous devez définir manuellement le focus d'entrée, sinon la navigation au clavier ne fonctionnera pas. Je ne suis pas entièrement convaincu que cela puisse fonctionner de manière fiable. Pourquoi ne créez-vous pas des fenêtres régulières à la place? – IInspectable