Faire perdre le focus d'une editbox

Résolu
Signaler
Messages postés
116
Date d'inscription
dimanche 26 septembre 2004
Statut
Membre
Dernière intervention
13 février 2008
-
Messages postés
116
Date d'inscription
dimanche 26 septembre 2004
Statut
Membre
Dernière intervention
13 février 2008
-
Bonjour, j'ai un léger soucis, je voudrais faire perdre le focus d'une edit box pour récuperer sa valeur après l'appui sur la touche entrer.

J'ai essayé d'intercepter le message WM_KEYDOWN ou WM_CHAR dans ma fenetre mère, mais dès que mon curseur est dans l'edit alors ces messages ne sont plus détectés.

Que faire ? Merci d'avance pour m'indiquer une piste de réflexion.

http://www.rc-bot.com/

10 réponses

Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
13
Le principe du sous-classement est très simple:

Chaque contrôle (Edit, Bouton, Static etc...) a une procédure par
défaut qui le gère. Cette procédure est invisible car elle est gérée
par le système. SetWindowLong() nous
permet de récupérer l'adresse de cette procédure et puis la remplacer
par l'adresse de notre procédure de sous-classement. Ainsi tous
les messages destinés à la procédure originale sont interceptés dans la
procédure de sous-classement. Si on fait return 0
dans le traitement d'un message, celui-ci ne sera pas envoyé à la
procédure originale. C'est justement le but recherché. Pour laisser
passer les autres messages on utilise CallWindowProc() comme dans l'exemple.
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
30
Quel besoin de s'occuper du focus pour cela ??? Mets un bouton IDOK en defpush et sa procédure sera lancée à l'appui de ENTER.

ciao...
BruNews, MVP VC++
Messages postés
1466
Date d'inscription
vendredi 2 janvier 2004
Statut
Modérateur
Dernière intervention
14 février 2014
1
salut,

tu peux aussi "subclass(er)" la fonction:
SetWindowLong(hwEdit,GWL_WNDPROC,&myWndProc);
dans ta wndproc, tu utilise:
LRESULT CallWindowProc(

WNDPROC lpPrevWndFunc,
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
pour appeler l'ancien handler.

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

Moi aussi, comme patatalo, je préfère le sous-classement. Voici un exemple:
// Variable déclarée en global:


WNDPROC OldEditProc;

// Procédure de sous-classement de l'Edit:


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


{


switch (message)


{


case WM_CHAR:


// Empêcher le beep après appui sur ENTREE:


if (wParam == VK_RETURN) return 0;


break;




case WM_KEYDOWN:


// Si la touche tapée est "ENTREE":


if (wParam == VK_RETURN)


{


// Faire ce qu'on veut ici:

// ..........


return 0;


}


break;




default:


break;


}


// Appeler la procédure originale:


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


}


Dans le traitement du message WM_CREATE ou WM_INITDIALOG, tu fais ceci:

OldEditProc= (WNDPROC) SetWindowLong(hEdit, GWL_WNDPROC, (LPARAM)EditProc);

Il faut que l'Edit soit déjà crée avant d'appeler SetWindowLong().

Pour plus de détails tu peux regarder ma source:

http://www.cppfrance.com/codes/NAVIGATEUR-WEB-API-/29247.aspx
Messages postés
116
Date d'inscription
dimanche 26 septembre 2004
Statut
Membre
Dernière intervention
13 février 2008

Bon j'ai un peu plus de mal avec le sousclassement des proc car en plus je n'ai pas qu'une seule editbox pour laquelle ceci doit fonctionner mais 32 alors ça me fait bcp de procédures ...

Parcontre j'ai essayé avec ce qu'a dit Brunews mais j'ai pas du tout comprendre car ça ne veut pas marcher. Voilà ce que j'ai ajouté à mon code:

Après la création de ma fenetre "dmxwindow" où se trouvent mes edits j'envoie:

SendMessage(dmxwindow,DM_SETDEFID,ID_DEFAULTBUTTON,0);

Pour préciser l'handle virtuel du bouton par defaut. J'ai une première question à ce sujet : doit il réellement exister ce bouton ?

Puis logiquement l'appuie sur "entrée" quand mon curseur de texte est dans un edit box çà envoie le message WM_COMMAND comme si j'avais appuyé sur le defpush : ID_DEFAULTBUTTON

Donc j'intercepte son handle dans le case WM_COMMAND de ma procedure de gestion de ma "dmxwindow"

if(LOWORD(wParam)==ID_DEFAULTBUTTON){
SetFocus(hwnd);
}

Et je remet mon focus sur ma fenetre entière ce qui va envoyer un EN_KILLFOCUS et déclencher la prise en compte de la valeur de mon edit box (bout de code qui existe déjà).

Mais hélas rien ne se passe quand j'appuie sur entrée, parcontre le fait d'appeler SetFocus(hwnd); déclenche bien l'effet escompté. J'utilise d'ailleurs cette méthode pour prendre ma valeur de l'edit lorsqu'un clic de souris survient.

Je suis en C (pas++) sous dev-cpp ... si ça a une importance ...

Merci

http://www.rc-bot.com/
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
30
Mets direct le style BS_DEFPUSHBUTTON à la création de ton bouton.

Je n'avais quasi rien compris à ta question mais le sous classement est de loin la meilleure manière de procéder pour controler les entrées utilisateur. Ce n'est pas parce qu'on a X edit qu'il faudra X editProc, la même editProc peut servir à tous les rdit pour lesquels tu veux un traitement ressemblant.

ciao...
BruNews, MVP VC++
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
13
Oui c'est vrai tu peux utiliser une seule procédure de sous-classement
pour tes 32 Edits. J'ai déjà fait un programme utilisant ce principe.
J'ai déclaré les HWND de mes 20 Edits dans un tableau en global. Pareil
pour les WNDPROC pour les procédure originales:

HWND hEdit[20];

WNDPROC oldproc[20];

Une autre variable globale sert à préciser l'Edit courant:

int courant;

"courant" est récupéré apès clic dans l'un des 20 Edits grâce à une boucle:

case WM_COMMAND:

for (int j=0;j<20;j++)

{

if( (HWND)lParam == hEdit[j]) break;

}

courant =j;

break;



SetWindowLong est utilisée dans une autre boucle:

for (int i=0;i<20;i++)

{

oldproc[i]= (WNDPROC) SetWindowLong(hEdit[i], GWL_WNDPROC, (LPARAM)EditProc);

}



Dans la procédure de sous-classement j'ai fait:

case WM_KEYDOWN:
if (wParam == VK_RETURN)
{
// Appeler la fonction de récupération du contenu de l'Edit
SetFocus(hEdit[courant+1]; // Passer le focus à l'Edit suivant
return 0;
}
break;

//............

return CallWindowProc(oldproc[courant], hwnd, message, wParam, lParam);

J'espère que ça aidera.
Messages postés
116
Date d'inscription
dimanche 26 septembre 2004
Statut
Membre
Dernière intervention
13 février 2008

Bon je dois être un peu mal doué j'ai fait :

HWND boutondefaultdmx;
boutondefaultdmx = CreateWindowEx(0,
"BUTTON",
"",
WS_CHILD|BS_DEFPUSHBUTTON,
nbcanauxparpage*31-44,
244,
50,
20,
hwnd,
(HMENU)ID_DEFAULTBUTTON,
g_hInst,
NULL);

puis j'intercepte toujours :

if(LOWORD(wParam)==ID_DEFAULTBUTTON){
SetFocus(hwnd);
}

http://www.rc-bot.com/
Messages postés
116
Date d'inscription
dimanche 26 septembre 2004
Statut
Membre
Dernière intervention
13 février 2008

... suite du message (ça a merdé chef)

Mais rien ne se passe. Je vais tenter le subclassement même si j'ai un peu de mal à le comprendre. Mais j'aimerais savoir pourquoi je n'arrive pas à faire fonctionner la méthode de Brunews qui me conviendrais mieux je pense.

http://www.rc-bot.com/
Messages postés
116
Date d'inscription
dimanche 26 septembre 2004
Statut
Membre
Dernière intervention
13 février 2008

Bon merci beaucoup, j'ai maintenant compris la philosophie du subclassement et j'ai appliqué la méthode avec succés dans mon projet.

http://www.rc-bot.com/