DÉPLACER LE FOCUS D'UN TEDIT À L'AUTRE EN IGNORANT LES AUTRES COMPOSANTS

Messages postés
4580
Date d'inscription
samedi 19 janvier 2002
Statut
Modérateur
Dernière intervention
9 janvier 2013
- - Dernière réponse : cs_grandvizir
Messages postés
1237
Date d'inscription
samedi 8 novembre 2003
Statut
Membre
Dernière intervention
3 septembre 2006
- 21 nov. 2004 à 11:40
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/27383-deplacer-le-focus-d-un-tedit-a-l-autre-en-ignorant-les-autres-composants

cs_grandvizir
Messages postés
1237
Date d'inscription
samedi 8 novembre 2003
Statut
Membre
Dernière intervention
3 septembre 2006
10 -
Nan mais vraiment !!! Bien sûr que si qu'on peut changer le Key sur l'évènement OnKeyDown. C'est pas «impossible», sauf si on ne voit pas la différence entre un key en mode CHAR (onKeyPress) et un key en mode ORDINAL (onKeyUp/Down). C'est sûr qu'on ne peut pas écrire Key:='x'; sur OnKeyDown. On peut par contre mettre Key:=Ord('x'); Inversement avec OnKeyPress. C'est une histoire de conversion, pas de faisabilité. Restons en là avec "is TCustomEdit" de DelphiProg :)
cs_grandvizir
Messages postés
1237
Date d'inscription
samedi 8 novembre 2003
Statut
Membre
Dernière intervention
3 septembre 2006
10 -
En tout cas, dans OnKeyPressed, ça marche !... euh... Ah ouais, je viens de voir le truc... En fait, tellement l'évènement OnKeyPressed me paraissait évident que j'ai mis OnKeyDown. C'est logique ! ?? Mais qui sait, je me trompe encore.
cs_MAURICIO
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5 -
Je cite:
<<[MAURICIO] Pour convertir les Enter en Tabs, il suffit juste dans l'évènement onKeyDown de mettre:
if key=#13 then key:=#9;
Le composant se charge du reste après.>>

Dans le OnKeyDown tu peux pas mettre ça!!! Impossible!!!
Donc ton dernier commentaire, ne tiens pas debout...

Je cite:
<<Sinon, je ne voit pas le rapport avec les TDBMachin. On vit dans les TEdit ici (pas exclusivement non plus).>>
Si t' as pas compris, je t' explique:
Aller, je me cite:
<<Voici un probleme archi connu pour delphi:
remplacer la touche Tab par la touhe Enter dans les forms:>>
Donc, c' est une fonction utilisable de maniere GENERALE pour n' importe quelle form.
Tu as compris maintenant pourquoi je parle de DB truc machin???????????????????????????
cs_grandvizir
Messages postés
1237
Date d'inscription
samedi 8 novembre 2003
Statut
Membre
Dernière intervention
3 septembre 2006
10 -
Je cite: «Bem ouai, si tu veux aller à la ligne dans un Memo, bem tu peux pas». Sauf si tu paramètres WantsTabs et WantsReturn correctement.
cs_MAURICIO
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5 -
Voici la nouvelle fonction ameliorée grâce à DelphiPRO:
(il faut l' appeler dans le onkeypress de vos forms qui, celles-ci doivent avoir keypreview à True)

je garde cette ligne DelphiProg : Cont := TWC <> Nil;
Tu vois pourquoi ...

procedure NavegarComEnter(Na_Form: TForm; var Tecla: Char);
var TWC : TWinControl;
Cont : Boolean;
begin
if Tecla = #13
then begin
TWC := Na_Form.ActiveControl;
Cont := TWC <> Nil;

if Cont
then begin
if TWC is TDBLookupComboBox
then Cont := not ((TWC as TDBLookupCombobox).ListVisible);

if Cont and not ((TWC is TDBMemo)
or (TWC is TMemo)
or(TWC is TDBRichEdit)
or (TWC is TDBGrid)) then
begin
Na_Form.Perform(WM_NEXTDLGCTL, 0, 0);
Tecla := #0;
end;
end;
end;
end;
cs_MAURICIO
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5 -
Ha grandvizir, si tu fais seulement:
if key=#13 then key:=#9
tu vas avoir quelques problemes avec certains composants (le memos par exemple).
Bem ouai, si tu veux aller à la ligne dans un Memo, bem tu peux pas, c pour ça que je regarde quel est le control qui a le focus.
De plus, il faut mettre:
if TWC is TDBLookupComboBox then
Cont := not ((TWC as TDBLookupCombobox).ListVisible);

Enfin, merci à Delphiprog pour l' optimisation de mon code ... C' est vraiment un grand Monsieur ce DelphiProg. Pour peu, je l' appelerai DelphiPro, ça lui va mieux!!!
japee
Messages postés
1715
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
2 décembre 2019
2 -
grandvizir > moi aussi j'aime tout le monde, et tous les intervenants sur cette page sont de grande qualité, et je respecte leur avis.

Je maintiens que mon code est une approche intéressante du problème.

Je ne suis pas fâché non plus (no problem), et ne perdons pas l'enthousiasme qui nous fera avancer toujours plus loin ;)

Faut pas mollir !

Bonne prog' à tous :))))))))
cs_Delphiprog
Messages postés
4580
Date d'inscription
samedi 19 janvier 2002
Statut
Modérateur
Dernière intervention
9 janvier 2013
24 -
GrandVizir et Mauricio : regardez mon code et vous verrez que j'ai utilisé le test :

if WinControl is TCustomEdit then...

parce que TdBEdit, TEdit, TMaskEdit, TMemo, TDbMemo, TDbLookupCombo, etc descendent tous de TCustomEdit et qu'il devient de ce fait inutile de tester chaque composant.
Il faut aussi savoir utiliser les relations dhéritage.

Mauricio : ActiveControl est du type TWinControl. D'ailleurs, tous les contrôles visuels déposés sur une fiche descendent de TWinControl (attention : sous Delphi mais pas sous Kylix).
Tu peux donc "alléger" ton code de la manière suivante :
procedure NavegarComEnter(Form: TForm; var Key: Char);
var
TWC: TWinControl;
Cont: Boolean;
begin
if Key = #13 then
begin
Cont := True;
TWC := Form.ActiveControl;

if TWC is TDBLookupComboBox then
Cont := not ((TWC as TDBLookupCombobox).ListVisible);

if Cont and not ((TWC is TDBMemo)
or (TWC is TMemo)
or(TWC is TDBRichEdit)
or (TWC is TDBGrid)) then
begin
Form.Perform(WM_NEXTDLGCTL, 0, 0);
Key := #0;
end;
end;
end;
cs_grandvizir
Messages postés
1237
Date d'inscription
samedi 8 novembre 2003
Statut
Membre
Dernière intervention
3 septembre 2006
10 -
[MAURICIO] Pour convertir les Enter en Tabs, il suffit juste dans l'évènement onKeyDown de mettre:
if key=#13 then key:=#9;
Le composant se charge du reste après.

Sinon, je ne voit pas le rapport avec les TDBMachin. On vit dans les TEdit ici (pas exclusivement non plus).
cs_grandvizir
Messages postés
1237
Date d'inscription
samedi 8 novembre 2003
Statut
Membre
Dernière intervention
3 septembre 2006
10 -
[Japee] Je ne demande pas de foudre de untel sur l'autretel. On a compris qu'il y a la méthode de X, de Y et de Z. C'est tout. Je raisonnais juste en terme d'octet pour un gain SIGNIFICATIF de place. Il n'y a pas que des "pros" sur ce site, et il convient donc de montrer les subtilités qui ne sont a priori pas connues de tous. C'est tout... Sinon, faut pas trop jouer sur les mots.

Je ne suis pas faché :)) La preuve !
cs_MAURICIO
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5 -
Pour ceux qui n' aurait pas compris:
il faut appeler la fonction de maniere suivante:
(ouai, mais n' oubliez pas de la mettre dans votre unit quand meme ...)

procedure Tform1.FormKeyPress(Sender: TObject; var Key: Char);
begin
NavegarComEnter(form1, Key);
end;
cs_MAURICIO
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5 -
Voici un probleme archi connu pour delphi:
remplacer la touche Tab par la touhe Enter dans les forms:

Il suffit d' utiliser la fonction suivante dans votre OnKeyPress de votre form (Form.keypreview doit être à true):

procedure NavegarComEnter(Na_Form: TForm; Var Tecla: Char);
var TWC : TWinControl;
Cont : Boolean;
begin
If Tecla = #13 // *** Tecla Enter *** //
Then Begin
Try
TWC := Nil;
TWC := Na_Form.ActiveControl As TWinControl;
Except

End;

If TWC <> Nil
Then Begin
If TWC Is TDBLookupComboBox
Then Cont := Not ((TWC As TDBLookupCombobox).ListVisible)
Else Cont := True;
End
Else
Cont := False;

If Cont
Then
If Not (TWC Is TDBMemo) And Not (TWC Is TMemo) And Not (TWC Is TDBRichEdit) And Not (TWC Is TDBGrid)
Then Begin
Na_Form.Perform( WM_NEXTDLGCTL, 0, 0 );
Tecla := #0;
End;
End;
end;

Ok, on va me dire que le code peut etre optimisé, mais il a au moins 6 ans et depuis, je ne l' ai pas changé ...
japee
Messages postés
1715
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
2 décembre 2019
2 -
Le "KeyPreview" de Delphi prog est "bien meilleur" dans le cas où l'on veut impliquer tous les TEdits de la fiche.

C'est clair, et je l'ai déjà dit, et je suis d'accord, et personne ne dit le contraire, et ça ne fait aucun doute, et c'est ok, et ça le fait, et aucun argument contradictoire n'ayant été avancé..., et qui a dit le contraire? Donc adjugé, vendu...

Sinon, selon ses besoins, chacun choisira la technique qui lui convient le mieux... et je ne vois pas qui pourra l'en empêcher, puisque ce sera son choix, pris en connaissance de cause, tout ayant été dit dans les commentaires.

Au fait, pas une ligne de code dans mon post... On pourrait penser que mon avis est subjectif et sujet à caution, et comme tout argument non démontré est facile à contredire... lol :)

Mais regardez, mon code est plus haut, dans mon source.

Bonne prog' à tous

P-S: je confirme, Delphiprog est bien le meilleur, s'il était moins présent sur ce site, ce dernier perdrait beaucoup en intérêt (opinion certes subjective et difficilement démontrable, c'est juste la mienne). ;)
cs_grandvizir
Messages postés
1237
Date d'inscription
samedi 8 novembre 2003
Statut
Membre
Dernière intervention
3 septembre 2006
10 -
Je confirme que le KeyPreview de Delphiprog est bien meilleur. En effet, la centralisation des OnKey[Event] sur un composant TEdit est un énorme surgénérateur d'octets. C'est pareil avec d'autres composants...

DelphiProg a encore raison cette fois. On n'a pas le droit de modifier TabStop sans scrupules. Cette propriété est très importante. Déjà, c'est l'un des 4 critères de focusabilité. Le truc caché: JulioDelphi tend à parasiter le fonctionnement des tabulations. Jouons: mettons 3 composants fenêtrés (donc focusables) dont le N°2 pris en sandwich avec sa propriété TabStop=false. Si on est sur le CompoN°1 et qu'on fait Tab, on passe sur CompoN°3. Le second a été oublié. Alors, on met true, on met false... on ne touche à rien plutôt.

En fait, pour bien voir l'utilité de TabStop, il suffit de se référer au développement des TRadioCheckBox. J'ai bossé dessus: ouhlala ! Faut pas oublier une ligne de code parce que pour remettre à jour l'ordre dans les TabStop... ... (je met doubles suspensions). A ne pas confondre avec TabOrder ! A la base, l'idée est bonne, mais techniquement... plouf! Il peut toujours essayer de démontrer le contraire: ça sera intéressant pour tout le monde.
cs_Delphiprog
Messages postés
4580
Date d'inscription
samedi 19 janvier 2002
Statut
Modérateur
Dernière intervention
9 janvier 2013
24 -
JulioDelphi: effectivement, un solution consisterait à mettre la propriété TabStop à False des autres composants. Mais alors, comment l'utilisateur ayant l'habitude de se déplacer avec la touche tabulation fera-t-il ?
D'ailleurs mon code possède une grosse lacune : il ne distingue pas un TEdit d'un autre composant.
Il faut donc ajouter au début de FormKeyDown ou FormKeyPress :

if (ActiveControl is TCustomEdit) and (Key = #13) then...
ou son équivalent
if (ActiveControl is TCustomEdit) and (Key = VK_RETURN) then...

Voilà Japee, la balle est dans ton camp maintenant.
Mais, sincèrement, ne penses-tu pas qu'il est intéressant et enrichissant pour les personnes qui liront nos commentaires plus tard de mieux comprendre les différentes possibilités ?
Donc tu peux laisser ton code originel. Il ne souffre d'aucun défaut. Tu as eu une approche différente, tout comme JulioDelphi. Ma méthode n'est pas meilleure. Elle est juste différente.
Après tout, un problème peut comporter plusieurs solutions ou avoir plusieurs manières d'être traité.
japee
Messages postés
1715
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
2 décembre 2019
2 -
Au fait, à mon avis :

- mon code et le premier de Delphiprog sont plus adaptés si l'on ne désire appliquer l'effet qu'à certains Edits de la fiche, mais pas à tous;

- le 2ème code de Delphiprog est plus adapté dans le cas où l'on veut l'appliquer à tous les Edits de la fiche.

- la solution de JulioDelphi n'est pas dépourvue d'intérêt non plus.

Je vais ajouter une version allégée tenant compte des remarques de Delphiprog, tout en restant dans l'esprit de mon code d'origine.
japee
Messages postés
1715
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
2 décembre 2019
2 -
Pourquoi pas, JulioDelphi ? Ton idée est intéressante.
Mais on peut avoir besoin de garder la possibilité d'utiliser TabStop pour les autres composants...
Et puis, s'il y a beaucoup de composants pouvant recevoir le focus, autres que des TEdit, il est facile d'en oublier un...
Il est plus facile de regrouper les Edits qu'on veut voir réagir au code.
Et si l'on utilise la 2eme méthode décrite par DelphiProg, alors là, y'a même plus à hésiter.
Et puis s'il n'y a pas moyen de trouver un prétexte à faire un source, alors... :(
Capicce ? ;)
JulioDelphi
Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
12 -
wow je vois de bons codes là depuis qqs jours :)

celui ci me plait aussi :D mais euh ... en fait, la finalité de ce code est de passer Edit en Edit en evitant les autres compo .. ok ...

N'est-il pas plus simple de mettre le TabStop à False sur les autres compos et de bien regler l'odre de tabulation des autres edit ?
ou alors j'ai pas tout capicce ...
japee
Messages postés
1715
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
2 décembre 2019
2 -
En voilà, un commentaire constructif et enrichissant, Delphiprog !

Ton deuxième code, en particulier, m'a inspiré.

Donc, pour les paresseux ;) ou ceux qui peineraient à l'adapter à l'énènement OnKeyDown:

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
WinControl: TWinControl;
GoForward: Boolean;
begin
case Key of
VK_DOWN, VK_NEXT, VK_RETURN: GoForward := True;
VK_UP, VK_PRIOR: GoForward := False;
else Exit;
end;
repeat
WinControl := FindNextControl(ActiveControl, GoForward, True, False);
if WinControl is TCustomEdit then
begin
WinControl.SetFocus;
Key := 0;
Break;
end
else
ActiveControl := WinControl;
until WinControl = nil;
end;

Pour le premier, serait-il intéressant de remplacer ce morceau de code:

VK_RETURN: SetFocusNextEdit(not (ssShift in Shift));
if ssShift in Shift then
SetFocusNextEdit(False)
else
SetFocusNextEdit;

par

VK_RETURN: SetFocusNextEdit(not (ssShift in Shift));

?

Merci à toi.
cs_Delphiprog
Messages postés
4580
Date d'inscription
samedi 19 janvier 2002
Statut
Modérateur
Dernière intervention
9 janvier 2013
24 -
Pas mal. Mais si on veut alléger ton code on peut aussi écrire et prendre en compte la touche Shift :

procedure TForm1.SetFocusNextEdit(GoForward: boolean = True);
begin
repeat
Perform(WM_NEXTDLGCTL, Ord(GoForward) - 1, 0);
until ActiveControl is TCustomEdit;
end;

procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of
VK_DOWN, VK_NEXT : SetFocusNextEdit;
VK_RETURN:
{Par défaut, la touche Shift inverse le parcours
des contrôles pour les touches Enter et TAB}
if ssShift in Shift then
SetFocusNextEdit(False)
else
SetFocusNextEdit;

VK_UP, VK_PRIOR: SetFocusNextEdit(False);
end;
end;

Je propose une autre alternative basée sur les principes suivants :
- mettre la propriété KeyPreview de la fiche à True
- mettre le code qui suit dans le gestionnaire d'évènement OnKeyPress de la fiche :
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
var
WinControl: TWinControl;
begin
if Key = #13 then
repeat
WinControl := FindNextControl(ActiveControl, True, True, False);
if WinControl is TCustomEdit then
begin
WinControl.SetFocus;
Key := #0;
Break;
end
else
ActiveControl := WinControl;
until WinControl = nil;
end;
Et c'est tout !
Donc pas besoin d'assigner d'évènement OnKeyPress à chaque TEdit. Ben voui, s'il y en a beaucoup sur une fiche, ça devient vite fastidieux et le risque d'oubli augmente en proportion.

Je pense que vous ferez sans difficultés l'adaptation si vous souhaitez adapter ce code à l'évènement OnKeyDown de la fiche.

Encore Bravo Japee.