Fenêtre CHILD

Résolu
Signaler
Messages postés
203
Date d'inscription
lundi 2 août 2004
Statut
Membre
Dernière intervention
8 septembre 2006
-
Messages postés
203
Date d'inscription
lundi 2 août 2004
Statut
Membre
Dernière intervention
8 septembre 2006
-
Bonjour
Une petite question. J'ai une fenêtre avec des contrôles definie à l'interieur comme suit:

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);


hGoupeConnexion = CreateWindowEx(NULL, "STATIC", NULL, WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE|WS_BORDER, 10, 20, 160, 70, hWnd, NULL, hInstance, NULL);
hTxtConnexion = CreateWindowEx(NULL, "STATIC", "Parametre de connexion ADM", WS_CHILD, 8, 5, 150, 20, hGoupeConnexion, (HMENU) ID_GROUPE_CNX_ADM, hInstance, NULL);
hEditUser = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "ADMA03B355", WS_CHILD, 5, 25, 75, 18, hGoupeConnexion, (HMENU) ID_EDIT_LOG_ADM, hInstance, NULL);
hEditPassWord = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "1605bes-3", WS_CHILD, 5, 45, 75, 18, hGoupeConnexion, (HMENU) ID_EDIT_PWD_ADM, hInstance, NULL);
hCmdBouton_Search = CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", "Search", WS_CHILD, 90, 30, 60, 30, hGoupeConnexion, (HMENU) ID_CMD_SEARCH, hInstance, NULL);

Donc un goupe de contôle contenant des contôles. Dans cette situation je ne sais pas intercépter le clic sur le bouton "Search"
Voila la boucle de traitement des messages :
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
MessageBox(hWnd, "WM_COMMAND", "WndProc", NULL);
...
...
break;
...
...
case ID_CMD_SEARCH:
//MessageBox(hWnd, "Contrôle non trouvé", "Recherche du contrôle", NULL);
EnumChildWindows(hWnd, (WNDENUMPROC) EnumChildProc_Find_Control, ID_EDIT_LOG_ADM);
//GetWindowText(hHandel_Control....);
//Connexion_AD();
break;
...
...
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

J'imagine bien que je m'y prend mal mais je vois pas comment procéder.

Une autre question au passage mais qui mérite peut-être un autre poste. EnumChildWindows me permet de récuperer le HWND du contrôle que je cherche, cela marche parfaitement mais pour récuper le HWND j'ai declaré une variable global et j'aimerais plustot faire en sorte d'avoir une fonction qui me retourne le HWND. Je vois comme solution à cela la création d'une classe mais il doit y avoir plus simple.

Merci de votre aide.

10 réponses

Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
13
Salut,

Le message WM_COMMAND est normalement
envoyé à la procédure de le fenêtre (ou le controle) mère du bouton.
Pour pouvoir intercepter ce message il y'a 2 solutions:

1- Remplacer la procédure de ton Static (parent) par celle de la
fenêtre principale. Ainsi, tous les messages destinés au Static seront
détournés vers ta WndProc.

2- Sous-classer le Static parent pour pouvoir intercepter et traiter les messages envoyés par ses controles enfants (child).



Dans ton cas, les messages sont envoyés à la procédure par défaut de ton Static hGoupeConnexion.

Voici comment procéder pour la première solution:

hGoupeConnexion = CreateWindowEx(NULL, "STATIC", ...........

SetWindowLong(hGoupeConnexion,GWL_WNDPROC,(LPARAM)WndProc);

Ainsi, tous les messages seront intercéptés et traités dans la procédure de la fenêtre principale WndProc.



Et voila comment faire pour la deuxième solution:

- Déclarer l'ancienne procédure en global:

WNDPROC OldStaticProc;

- Sous-classer le Static juste après sa création:

OldStaticProc= (WNDPROC) SetWindowLong(hGoupeConnexion,GWL_WNDPROC, (LPARAM)StaticProc);

- Placer la procédure de sous-classement juste après les déclarations globales:

LRESULT CALLBACK StaticProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

// Traitement du message WM_COMMAND :

if (message==WM_COMMAND && LOWORD(wParam)==ID_CMD_SEARCH )

{

// Traitement:

MessageBox(0,"Bouton Search cliqué","ok",0);

}

// Appeler la procédure originale:

return CallWindowProc(OldStaticProc, hwnd, message, wParam, lParam);

}

Si tu préfères le switch et case, il faut utiliser les 16 bits de poids faible de wParam pour récupérer l'identificateur du controle:

case WM_COMMAND:

int select;

select=LOWORD(wParam);

switch(select)

{

case ID_CMD_SEARCH:

// traitement ....

break;

case ID_XXX:

//....

break;

}

return 0;

//......

//.......



A toi de choisir la solution qui te convient mieux.

Voilà, j'espère n'avoir rien oublié.
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
13
C'est bien d'éviter les variables globales tant que possible. Mais parfois on ne peut pas faire autrement.

Dans ton cas tu peux éviter cette variable globale en faisant une
fonction qui retourne le HWND du controle recherché et reçoit en
paramètre le HWND parent et l'identificateur du controle. Cette
fonction utilisera GetWindow() ou FindWindowEx() pour trouver les
controles child et GetWindowLong() pour trouver les identificateurs. Si
l'identificateur obtenu correspond à celui donné en paramètre, la
fonction retourne son HWND. Si l'énumération est terminé sans trouver
le controle voulu, elle retourne 0.

Voici un petit exemple fait rapidement:

HWND GetChild(HWND hParent, int Identificateur)

{

HWND child=GetWindow(hParent, GW_CHILD);

while (child)

{

int id=(int)GetWindowLong(child, GWL_ID);
if (id==Identificateur) return child;

child=GetWindow(child, GW_HWNDNEXT)

}

return 0;

}
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
30
prends case ID_CMD_SEARCH: dans WM_COMMAND

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++
Messages postés
203
Date d'inscription
lundi 2 août 2004
Statut
Membre
Dernière intervention
8 septembre 2006

Il me semble bien que je l'avais fait ainsi au depart. Mais face à mon échec, j'ai essayé de le mettre un peut par tout. D'ou la présence de MessageBox(hWnd, "WM_COMMAND", "WndProc", NULL); pour tester la boucle.
J'avais pas fait attention en postant à ca je vérifirais. Il faut donc que je switch comme suis:
switch (wmId)
{
...
case ID_CMD_SEARCH:
...
}

Pour ce soir je peux pas aller plus loin. Reponse demain.
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
30
case WM_COMMAND:
switch(wParam) {
case ID_xxx:

}

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++
Messages postés
203
Date d'inscription
lundi 2 août 2004
Statut
Membre
Dernière intervention
8 septembre 2006

Merci de votre aide.
C'est SetWindowLong(hGoupeConnexion,GWL_WNDPROC,(LPARAM)WndProc); qui me manquait. Le code que j'ai posté contenait bien une erreur dans la boucle de traitement mais ce que je faisait initialement etait correcte :
switch (wmId)
{
...
case ID_CMD_SEARCH:

J'ai donc pu poursuivre, c'était vraiment simple.

Concerant :
Une autre question au passage mais qui mérite peut-être un autre poste. EnumChildWindows me permet de récuperer le HWND du contrôle que je cherche, cela marche parfaitement mais pour récuper le HWND j'ai declaré une variable global et j'aimerais plustot faire en sorte d'avoir une fonction qui me retourne le HWND. Je vois comme solution à cela la création d'une classe mais il doit y avoir plus simple.

Pouvez vous apporter une repnnse?
Merci
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
13
Ca dépend de ce que tu veux faire. Il y'a 2 fonctions API pour cela : FindWindowEx() et GetWindow().

Exemple:

// Pour trouver le premier controle Static child:

HWND child1=FindWindowEx(hParent,0,"STATIC",0);

// Pour trouver le suivant:

HWND child2=FindWindowEx(hParent,child1,"STATIC",0);

On peut continuer comme ça pour trouver les autres Statics.

La fonction GetWindow() trouve tous les controles child sans distinction de classe:

HWND child1=GetWindow(hParent, GW_CHILD);

HWND child2=GetWindow(child1, GW_HWNDNEXT);

Etc....

Le 4e paramètre de FindWindowEx() peut contenir le texte affiché dans un controle.

Il est plus pratique d'utilises ces APIs dans des boucles do while.
Messages postés
203
Date d'inscription
lundi 2 août 2004
Statut
Membre
Dernière intervention
8 septembre 2006

Merci je crois que FindWindowEx est ce que je cherche. Ce que je souhaite faire c'est chercher un EDIT qui à pour ID un ID passé en parametre.


Ce que je veux fait c'est exactement ça :


HWND hHandel_Control
main
{
...
EnumChildWindows(hWnd, (WNDENUMPROC) EnumChildProc_Find_Control, ID_EDIT_LOG_ADM);
...
}
BOOL CALLBACK EnumChildProc_Find_Control(HWND hWnd, LPARAM lParam)
{
if (GetWindowLong(hWnd, GWL_ID) == (LONG) lParam)
{
hHandel_Control = hWnd;
return FALSE;
};


return TRUE;
}
}

Voila ce que je veux faire. Ce code marche tres bien mais je souhaiterais une fonction qui me retourne directement le HWND que du controle que je cherche et non de passer par une variable globale, ce que je ne trouve pas très élégant.

Merci de ton aide.
Messages postés
203
Date d'inscription
lundi 2 août 2004
Statut
Membre
Dernière intervention
8 septembre 2006

Merci de ton aide
Messages postés
203
Date d'inscription
lundi 2 août 2004
Statut
Membre
Dernière intervention
8 septembre 2006

Voila finalement la fonction que j'utilise pour trouver un controle dans une fenetre en n'en connaissant que son ID.
En parmetre la fenetre parent et l'ID du controle.
Retourne le HWND du controle.
La recherche ce fait dans la fenetre les sous fenetre et leur sous fenetre....
HWND Find_Control(HWND hWnd, LONG ID_to_Find) {
HWND hControl=GetWindow(hWnd, GW_CHILD);
while (hControl)
{
LONG ID_Control = GetWindowLong(hControl, GWL_ID);
if (ID_Control==ID_to_Find)
return hControl;
Find_Control(hControl, ID_to_Find);
hControl=GetWindow(hControl, GW_HWNDNEXT);
}
return 0;
}

Comme ca si ca interesse quelqu'un

Bonne soiré