OVH Cloud OVH Cloud

Comment fonctionne la "modalite" ?

16 réponses
Avatar
Aurélien REGAT-BARREL
Hello,
Si on veut un dialog modal on utilise DialogBox.
Si on en veut pas c'est CreateDialog + sa boucle des msg.
Pblm : DialogBox appelle IsDialogMessage ce qui filtre certains messages
claviers.
Question : comment créer avec CreateDialog une boite modale ? (ou comment
utiliser DialogBox sans IsDialogMessage ?)
Plus généralement, disons avec CreateWindow, comment fonctionne la
"modalité" ?
Merci.

--
Aurélien REGAT-BARREL

10 réponses

1 2
Avatar
Patrice Labracherie
il me semble que c'est principalement la fenetre appelante qui est disablée

"Aurélien REGAT-BARREL" a écrit dans le
message news: 41591407$0$2236$
Hello,
Si on veut un dialog modal on utilise DialogBox.
Si on en veut pas c'est CreateDialog + sa boucle des msg.
Pblm : DialogBox appelle IsDialogMessage ce qui filtre certains messages
claviers.
Question : comment créer avec CreateDialog une boite modale ? (ou comment
utiliser DialogBox sans IsDialogMessage ?)
Plus généralement, disons avec CreateWindow, comment fonctionne la
"modalité" ?
Merci.

--
Aurélien REGAT-BARREL




Avatar
Manuel Leclerc
Aurélien REGAT-BARREL a écrit :

Si on veut un dialog modal on utilise DialogBox.
Si on en veut pas c'est CreateDialog + sa boucle des msg.
Pblm : DialogBox appelle IsDialogMessage ce qui filtre certains
messages claviers.
Question : comment créer avec CreateDialog une boite modale ?
(ou comment utiliser DialogBox sans IsDialogMessage ?)
Plus généralement, disons avec CreateWindow, comment fonctionne
la "modalité" ?



La modalité repose sur un Hook. Quel est le message que tu veux
intercepter pendant la modalité ?

--
So before Wine was created, anything which uses a Windows library was
a derivative of Windows?


Yes.
--Josh Triplett
Avatar
Aurélien REGAT-BARREL
> La modalité repose sur un Hook. Quel est le message que tu veux
intercepter pendant la modalité ?



Ben je sais pas. Je veux faire comme DialogBox, mais sans! Je sais pas
comment il fait lui.
Le probleme de DialogBox c'est qu'il appelle IsDialogMessage, ce qui filtre
WM_KEYDOWN. Donc apparement ça serait CreateDialog + hook pour faire la
modalité, ou DialogBox + hook pour contrer l'effet de IsDialogMessage.
Supair...
Y'a pas mieux ?
Et sinon, avez vous (toi ou Patrice) des liens sur comment ça fonctionne la
modalité ?
Merci à vous.

--
Aurélien REGAT-BARREL
Avatar
adebaene
"Aurélien REGAT-BARREL" wrote in message news:<41591407$0$2236$...

Plus généralement, disons avec CreateWindow, comment fonctionne la
"modalité" ?



Une fenêtre modale lance sa propre pompe à message
(GetMessage/TranslateMessage/DispatchMessage) à l'intérieur d'un
handler de message de la fenêtre parente. Tu te retrouves donc, dans
la pile d'appel, avec 2 pompes à messages : celle de la fenetre
modale, en haut de la pile, qui tourne effectivement et traîte les
messages, et celle de la fenêtre parente, plus bas dans la pile, qui
est bloquée dans un appel à DispatchMessage. 'est ce qui explique que
la fenêtre parente soit "figée" : elle ne peut plus recevoir et
traiter de messages de fenêtres.

Arnaud
MVP - VC
Avatar
Christian ASTOR
Aurélien REGAT-BARREL wrote:
Si on veut un dialog modal on utilise DialogBox.
Si on en veut pas c'est CreateDialog + sa boucle des msg.
Pblm : DialogBox appelle IsDialogMessage ce qui filtre certains messages
claviers.
Question : comment créer avec CreateDialog une boite modale ? (ou comment
utiliser DialogBox sans IsDialogMessage ?)
Plus généralement, disons avec CreateWindow, comment fonctionne la
"modalité" ?



DialogBox() appelle DialogBoxParam() qui disable la owner et la
re-enable en sortie.
Entre les 2, elle fait, principalement, une boucle sur PeekMessage()
-IsDialogMessage()-TranslateMessage()-DispatchMessage(), en testant des
cas particuliers comme WM_SYSKEYDOWN ou timers.

Pour DialogBox() & WM_KEYDOWN, WH_MSGFILTER hook (KB72219, ...)
Avatar
Aurélien REGAT-BARREL
> > Plus généralement, disons avec CreateWindow, comment fonctionne la
> "modalité" ?

Une fenêtre modale lance sa propre pompe à message
(GetMessage/TranslateMessage/DispatchMessage) à l'intérieur d'un
handler de message de la fenêtre parente. Tu te retrouves donc, dans



Ca j'avais compris.

la pile d'appel, avec 2 pompes à messages : celle de la fenetre
modale, en haut de la pile, qui tourne effectivement et traîte les
messages, et celle de la fenêtre parente, plus bas dans la pile, qui
est bloquée dans un appel à DispatchMessage. 'est ce qui explique que
la fenêtre parente soit "figée" : elle ne peut plus recevoir et
traiter de messages de fenêtres.



Mais là je sèche.
Tout d'abord la 2° n'est pas bloquée à cause de DispatchMessage il me semble
mais plutot à cause du
while ( GetMessage )
qui fait que le corps de la 2° boucle n'est pas exécuté.
Ensuite, ce que je pige pas, c'est en quoi le
GetMessage/TranslateMessage/DispatchMessage de la première boucle est
différent du même trio de la 2°. Je veux dire, DispatchMessage ca reste
DispatchMessage que ce soit dans une boucle X ou Y.
Moi je vois DispatchMessage( &msg ) comme un alias de :
CallWindowProc(
(WNDPROC) GetWindowLongPtr( msg.hwnd, DWLP_DLGPROC ),
msg.hwnd,
msg.message,
msg.wParam,
msg.lParam );

Donc que ce soit dans la 1° ou la 2° boucle, c'est kifkif, les message de la
fenêtre parent sont envoyés à cette dernière, donc je pige pas pourquoi elle
est "figée".
Elle l'est pas vraiment en fait, car si tu cliques dessus, tu as la boite
modale qui "flash", ca fait "ding ding", et surtout elle reçoit toujours
WM_PAINT.
Ca ressemble plutot à du disabled comme l'ont dit certains.

--
Aurélien REGAT-BARREL
Avatar
Aurélien REGAT-BARREL
> DialogBox() appelle DialogBoxParam() qui disable la owner et la
re-enable en sortie.


Ok, donc c'est simplement du disabling. Mais est-ce que ça suffit pour
expliquer que la fenêtre modale est toujours au-dessus de la fenêtre mère et
que la modale flash quand on clique sur sa maman ?

Entre les 2, elle fait, principalement, une boucle sur PeekMessage()
-IsDialogMessage()-TranslateMessage()-DispatchMessage(), en testant des
cas particuliers comme WM_SYSKEYDOWN ou timers.


Timers je pige pas trop pourquoi. Je sais qu'on peut arriver à bidouiller la
dialog proc via un timer (par exemple pour mettre un timeout sur une
MessageBox on met une procedure callback via SetTimer qui poste un
WM_CLOSE), je sais pas si c'est ça dont tu parles.

Pour DialogBox() & WM_KEYDOWN, WH_MSGFILTER hook (KB72219, ...)


Ah... je pensais qu'il y avait un moyen plus propre. Ca fait un peu bourrin
quand même. Mais bon...

--
Aurélien REGAT-BARREL
Avatar
Patrick 'Zener' Brunet
Bonjour.

"Aurélien REGAT-BARREL" a écrit dans le
message de news: 415ac52f$0$5298$
> > Plus généralement, disons avec CreateWindow, comment fonctionne la
> > "modalité" ?
>
<...>
Donc que ce soit dans la 1° ou la 2° boucle, c'est kifkif, les message de


la
fenêtre parent sont envoyés à cette dernière, donc je pige pas pourquoi


elle
est "figée".
Elle l'est pas vraiment en fait, car si tu cliques dessus, tu as la boite
modale qui "flash", ca fait "ding ding", et surtout elle reçoit toujours
WM_PAINT.
Ca ressemble plutot à du disabled comme l'ont dit certains.





Il y a plusieurs trucs à considérer :

0) La fenêtre modale a sa vie encadrée par une fonction qui inclut une pompe
à message, afin de bloquer le thread qui l'invoque sans paralyser
l'application.

1) Les fenêtres parentes de la même application (et a fortiori des autres)
continuent donc à traiter leurs messages (la preuve c'est qu'elles se
retracent quand on déplace la fenêtre modale).

2) La fenêtre modale peut capturer la souris au niveau de l'application pour
éviter que les fonctionnalités de changement du curseur des fenêtres
parentes ne soient exécutées.

3) La fenêtre modale a la possibilité de refuser de perdre le focus (elle
reçoit normalement un WM_KILLFOCUS avant que la prétendante ne reçoive le
WM_SETFOCUS correspondant).

4) La fenêtre modale, quand elle représente une boîte de dialogue, a la
responsabilité de gérer ce dialogue et de décider de sa propre fin (fin de
la modalité et destruction de la fenêtre).

5) En fait quand j'ai dû coder ça à la main avec des fenêtres "normales", ce
fut la partie la plus complexe : gérer correctement les "dlg codes" pour
faire tourner le focus selon la norme entre les contrôles de la fenêtre,
sachant que l'effet d'une touche dépend de la nature du contrôle ayant le
focus, et que les réponses normalisées au message WM_GETDLGCODE (si je me
souviens bien) ont des noms assez peu explicites.

En fait les fonctions "dialog" automatisent tout ça. Fouillez un peu dans le
code des MFC pour rassembler les pièces du puzzle...

Hope It Helps,

Cordialement,

--

/**************************************************************
* Patrick BRUNET @ ZenerTopia
* E-mail: lien sur http://zener131.free.fr/ContactMe
**************************************************************/
<8#--X--< filtré par Avast! 4 Home
Avatar
Aurélien REGAT-BARREL
> Il y a plusieurs trucs à considérer :

0) La fenêtre modale a sa vie encadrée par une fonction qui inclut une


pompe
à message, afin de bloquer le thread qui l'invoque sans paralyser
l'application.

1) Les fenêtres parentes de la même application (et a fortiori des autres)
continuent donc à traiter leurs messages (la preuve c'est qu'elles se
retracent quand on déplace la fenêtre modale).


Ok.

2) La fenêtre modale peut capturer la souris au niveau de l'application


pour
éviter que les fonctionnalités de changement du curseur des fenêtres
parentes ne soient exécutées.


C'est pas plus simple via un disable ?
Question : comment restreins-tu un SetCapture "au niveau de l'application" ?

3) La fenêtre modale a la possibilité de refuser de perdre le focus (elle
reçoit normalement un WM_KILLFOCUS avant que la prétendante ne reçoive le
WM_SETFOCUS correspondant).

4) La fenêtre modale, quand elle représente une boîte de dialogue, a la
responsabilité de gérer ce dialogue et de décider de sa propre fin (fin de
la modalité et destruction de la fenêtre).


Ok.

5) En fait quand j'ai dû coder ça à la main avec des fenêtres "normales",


ce
fut la partie la plus complexe : gérer correctement les "dlg codes" pour
faire tourner le focus selon la norme entre les contrôles de la fenêtre,
sachant que l'effet d'une touche dépend de la nature du contrôle ayant le
focus, et que les réponses normalisées au message WM_GETDLGCODE (si je me
souviens bien) ont des noms assez peu explicites.


Pourquoi ne pas avoir utilisé IsDialogMessage ?

En fait les fonctions "dialog" automatisent tout ça. Fouillez un peu dans


le
code des MFC pour rassembler les pièces du puzzle...


Ben j'ai fouillé dans le code de ReactOS, mais je n'ai pas trouvé la
lumière.

Merci.
--
Aurélien REGAT-BARREL
Avatar
Patrick 'Zener' Brunet
Bonsoir.

Il y a une dizaine d'années que j'ai joué à ça, alors mes souvenirs sont un
peu vagues...

"Aurélien REGAT-BARREL" a écrit dans le
message de news: 415acf72$0$5314$

<...>

> 2) La fenêtre modale peut capturer la souris au niveau de l'application
pour
> éviter que les fonctionnalités de changement du curseur des fenêtres
> parentes ne soient exécutées.
C'est pas plus simple via un disable ?



EnableWindow(FALSE) ?
Peut-être ... Le seul problème éventuel serait que ça grise des contrôles,
ce qui serait anormal visuellement.

Question : comment restreins-tu un SetCapture "au niveau de l'application"


?

Normalement c'est implicite. D'après la doc, "This function cannot be used
to capture mouse input meant for another process".

<...>

> 4) La fenêtre modale, quand elle représente une boîte de dialogue, a la
> responsabilité de gérer ce dialogue et de décider de sa propre fin (fin


de
> la modalité et destruction de la fenêtre).
Ok.

> 5) En fait quand j'ai dû coder ça à la main avec des fenêtres


"normales",
ce
> fut la partie la plus complexe : gérer correctement les "dlg codes" pour
> faire tourner le focus selon la norme entre les contrôles de la fenêtre,
> sachant que l'effet d'une touche dépend de la nature du contrôle ayant


le
> focus, et que les réponses normalisées au message WM_GETDLGCODE (si je


me
> souviens bien) ont des noms assez peu explicites.




Pourquoi ne pas avoir utilisé IsDialogMessage ?



C'est un wrapper qui retourne un booléen après avoir émis le WM_GETDLGCODE.
Ca n'est qu'une partie infime du problème.
Le vrai problème, c'est d'exploiter les valeurs DLGC_XXX dans ce message,
ainsi que les WM_KEYDOWN et les WM_CHAR, pour gérer le focus de manière
logique entre les contrôles. Surtout si ce sont des contrôles un peu
modifiés.

> En fait les fonctions "dialog" automatisent tout ça. Fouillez un peu


dans
le
> code des MFC pour rassembler les pièces du puzzle...
Ben j'ai fouillé dans le code de ReactOS, mais je n'ai pas trouvé la
lumière.



Cherchez dans la MSDN, par exemple Article ID: Q83302

Les vieux samples de quand on faisait tout en C et à la paluche sont les
plus explicites.

Cordialement,

PZB
1 2