Delphi clavier virtuel : éditer l'objet dans lequel je me trouve

Résolu/Fermé
duffduffduff Messages postés 12 Date d'inscription vendredi 23 octobre 2015 Statut Membre Dernière intervention 11 mars 2022 - 8 oct. 2016 à 17:22
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 - 29 oct. 2016 à 22:58
Bonjour à tous et merci d'avance merci pour votre aide.

Je ne soyez pas trop technique car je suis proche du niveau 0 en delphi mais je m’amuse ;-)

Je crée un clavier virtuel dans mon app de commande de marchandises par e-mail.

Mon soucis est que j'aimerai que lorsque je clique sur une touche de mon clavier virtuel
quel delphi sache dans quel edit je me trouve sans devoir le faire manuellement pour chaque edit...

ps: j'ai fait mon clavier avec une stringgrid

J'espère que je bien expliqué mon problème.

Merci,

Céd
A voir également:

3 réponses

nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
8 oct. 2016 à 19:59
Bonjour,

je ne comprend pas exactement la question, mais la réponse se trouve probablement du côté de "Col" et "Row" du stringgrid, donnant respectivement la colonne et la ligne de l'élément en cours.
Il suffirait donc de lire ces deux valeurs pour déduire la correspondance de touche et réagir en conséquence...
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
9 oct. 2016 à 07:52
Ha oui, après une petite réflexion pédagogique, je me suis dis que vous deviez remplir les strings du clavier virtuels à partir de l'inspecteur d'objets, d'où le fait de manquer ensuite de lien clair entre la touche et son contenu.
Ceci dit le contenu de chaque chaîne est accessible à l'exécution via "Items" +qui est le conteneur des chaines affichées+ en utilisant "Col" et "Row" pour déterminer la touche concernée.
Mais pour mieux faire, vous devriez vous entrainer à remplir ces chaînes par prog plutôt que par l'inspecteur d'objet, c'est facile et c'est très utile pour aller plus loin.
Pour ma part j'aurais même plutôt utilisé un Drawgrid: à partir de ce composant il est facile de dessiner soi-même les touches dans la méthode "OnDrawCell" en utilisant des couleurs et des justifications avec "DrawText" (qui est une fonction Windows, pas delphi, donc dans win32sdk).
Passer outre l'emploi de simple chaînes pour déterminer les touches permet d'implémenter tout type de comportements, tel que la touche "enter", "esc", "retour" etc...
L'idéal +tout en restant simple+ serait de créer un tableau à deux dimensions représentant les lignes et colonnes du clavier, avec un champ pour la touche virtuelle de type Vk_ (virtual Key windows, codant toutes les touches du clavier), à partir de laquelle il est possible de retrancher le code ascii, donc le caractère à afficher ou autre sigle, avec les bitmaps d'un "ImageList" par exemple.
Le contenu de ce tableau peut être défini simplement sous forme de constante.
Sur cette base, on sait quel caractère dessiner lors d'un "OnDrawCell" en lisant dans ce tableau avec "Col" et "Row" présents en paramètres.
Pareillement, il est facile de réagir lors du survol d'une touche, ou d'un clic, en retrouvant le caractère concerné dans le tableau grâce aux propriétés "Col" et "Row" du composant. Ces propriétés ne reflètent cependant que la case dernièrement sélectionnées, donc pour savoir quelle case est survolée avec "OnMouseMove", ou plus généralement pour savoir quelle case est à telle position, il faut utiliser "MouseToCell".
0
duffduffduff Messages postés 12 Date d'inscription vendredi 23 octobre 2015 Statut Membre Dernière intervention 11 mars 2022
17 oct. 2016 à 00:39
Sorry pour la réponse tardive je me suis accordé une bonne semaine sans programmation....

Je me suis mal fait comprendre mon clavier est bien "rempli" et fonctionne parfaitement de la manière suivante :

Quand je "rentre" dans une édit par ex "edit1" (onenter)
je dis à ma variable string qui s'appelle "focus" focus:='edit1';

Et donc lorsque clique sur la touche 'A' de mon clavier virtuel je lui dit :
if focus='edit1' then edit1.text:=edit1.text+(La lettre A du clavier virtuel).

Jusque la tout va bien... quand on à 1,2,...5 edit c'est assez simple je n'ai qu'a faire :

if focus='edit1' then
if focus='edit2' then
if focus='edit3' then....edit3.text:=....

Mais imaginons que j'ai plus de 50 edit dans mon programme....
cela devient laborieux et "répétitif" à programmer.

"C'est maintenant que je n’embrouille dans mon explication"

Je que je cherche c'est que mon App se souvienne toute seule quel est la dernière edit à avoir été choisi (ca c'est assez simple) mais j'aimerai que mon clavier virtuel tape dans la bonne edit sans devoir mettre une ligne de code pour chaque edit."

c'est comme si je pouvait programmer ceci :

on clavier(toucheA).click then last_focusededit.text:=.......

OU alors dire a ma string focus dans quel edit je suis et faire
focus.text:=.... (ce qui voudrait dire : edit1.text:=.....)

Encore dsl même quand je me relis je comprends rien ;-)
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
17 oct. 2016 à 18:28
Bonjour,

Ha oui je vois! Alors, en programmation, quand il y a des répétitions de code c'est généralement qu'il y a moyen de faire bien plus simple et donc beaucoup mieux!
Ici, c'est la variable qui retient l'Edit concerné par la frappe de touche qui cloche, c'est à dire que ce n'est pas une string qu'il faut, mais un TEdit ou une classe parente.
En fait, TEdit est un type de classe, et il est possible de déclarer une variable de ce type sans pour autant créer l'objet, car cette variable n'est dans tous les cas qu'un pointeur sur objet, et non l'objet lui-même.
Donc on déclare une variable "Focus : TEdit" ou "Focus : TObject" et ensuite on peut y mettre un pointeur sur l'Edit qui est focusé, donc pas avec le nom de l'Edit, mais avec son pointeur: "Focus:= Edit1".
Ensuite, on peut s'adresser directement à l'Edit focusé grâce à la variable : "Focus.text:= Focus.Text + (Lettre du clavier virtuel)", comme si Focus était l'Edit lui-même, ce qui nous donne effectivement une formulation de ce genre:
on clavier(toucheA).click then focus.text:=.......

Donc pour définir le contenu de "Focus", l'utilisation de l'évènement OnEnter des TEdit convient oui, et il est possible de le mettre en commun entre tous les Edit (en déclarant pour l'un d'eux et recopiant le nom de l'évènement pour les autres), et ensuite d'employer "Sender" : "If sender is TEdit then Focus:= Sender as TEdit".
0
duffduffduff Messages postés 12 Date d'inscription vendredi 23 octobre 2015 Statut Membre Dernière intervention 11 mars 2022
18 oct. 2016 à 08:17
MERCIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
Je me doutait que ca devait exister, j'avais déjà vu des "sender" & co
mais je savais pas comment les utiliser..... pas si compliqué sue cela....
surtout quand on vous donne la réponse ! ;-)

Merci encore !!!!
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 18/10/2016 à 19:15
Pas de quoi, ce fut un plaisir!

Et l'explication sur le "Sender", c'est que les événements sont prévus pour être appelés par un composant tiers, comme dans le cas du TEdit: C'est à dire que le TEdit ou autre "TControl" reçoit l'événement windows, et déclenche l'événement qui a été déclaré dans la Form en passant par l'inspecteur d'objet; Mais pour savoir qui est à l'origine de l'événement, il y a toujours le paramètre "Sender" qui précise l'émetteur, donc le TEdit dans le cas présent.
Concrètement, un événement est un champ contenant un pointeur sur un objet précis ainsi que l'une des méthodes déclarées de cet objet; L'événement est donc l'appel d'une méthode d'une instance d'objet tiers.
Ainsi, lorsqu'on déclare un événement "OnEnter" d'un TEdit dans l'inspecteur d'objets, Delphi ajoute une méthode typée dans la Form, Edit1OnEnter par exemple, telle que OnEnter est déclarée dans le TEdit, puis branche l'événement correspondant du TEdit dessus.
Le TEdit appelle ensuite l'événement contenu dans son champ "FOnEnter", en se donnant comme Sender, ce qui provoque l'appel de la méthode Edit1OnEnter contenue dans la Form, et voilà!
0
duffduffduff Messages postés 12 Date d'inscription vendredi 23 octobre 2015 Statut Membre Dernière intervention 11 mars 2022
22 oct. 2016 à 23:23
Encore un dernier "truc"...

Imaginons que je doive "taper" avec mon clavier virtuel dans des edit et des dbedit...
ehhhh comment faire ?? je sais le faire ... uniquement dans des edit ou uniquement dans des dbedit mais pas les 2 en même temps.

Merci d'avance
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 23/10/2016 à 09:21
Hé bien, c'est là qu'il faut bien cerner le principe d'héritage : tous les objets ont au minimum un ancêtre commun (TObject), duquel ils héritent des propriétés et du code; Sachant cela, pour stocker un pointeur d'objet plus souple, il suffit de le typer avec leur ancêtre commun, surtout s'il comporte les éléments qui nous intéressent;
On constate que le TDbEdit et le TEdit ont pour ancêtre commun TCustomControl, il suffit donc de déclarer :
Focus: TCustomControl
ainsi dans cette variable on peut stocker des DbEdit comme des TEdit, tout en ayant accès à la propriété Text qui appartient à leur ancêtre commun TCustomControl.

Ceci dit, il n'y a rien d'obligatoire dans tout ça, et par ailleurs on est vite confrontés à la définition de pointeurs bien plus flous, donc définis en TObject.
On peut déclarer :
Focus : TObject;

En tant que TObject, on peut placer un objet de n'importe quelle classe dans cette variable :
Focus:= Sender;
Focus:= Edit1;
Focus:= DbEdit1;
etc...

Ensuite, pour savoir de quel type est cette variable sans type, il suffit de le tester:
If Focus is TCustomControl then (Focus as TCustomControl).Text:= '';
Et donc:
If Focus is TCustomControl then With (Focus as TCustomControl) do Text:= Text + lettre du clavier;

L'opérateur "is" permet de savoir si l'objet est compatible avec la classe spécifiée, sachant qu'elle répond vrai si c'est un descendant même éloigné;
Ainsi TEdit is TCustomControl est vraie,
TDbEdit is TCustomControl aussi,
TDbEdit is TObject également.

L'opérateur "as" est le pendant de "is", il permet de dire qu'on utilise l'objet dans le type spécifié.
Donc "is" permet de tester la compatibilité de l'objet avec telle classe, et "as" permet de l'utiliser en tant que telle classe, à condition qu'il descende de la classe donnée.
En remplacement de "as", on peut aussi faire TCustomEdit(Focus).Text;

En fait, la variable Focus ne contient qu'un pointeur sur objet, et lui donner un type ne sert qu'à préciser au compilateur ce qu'on peut attendre de cette variable, et évite donc par la suite de devoir tester. Donc lorsque le type est connu, ou qu'il y a une classe commune au-delà du TObject répondant aux différents types qu'on y placera, il vaut mieux dans ce cas déclarer la variable avec un type le plus évolué possible, ainsi le code est plus clair (en plus du nom de la variable, le type donne des infos sur son contenu) et on évite des tests et autres transtypages.

Comme de nombreux langages, Delphi est entièrement structuré autour de l'objet, et je vous suggère d'étendre votre connaissance de celui-ci pour mieux comprendre les mécanismes en jeu:
Ce tuto m'a l'air bien construit:
https://fbeaulieu.developpez.com/guide/?page=page_16


Le chêne aussi était un gland, avant d'être un chêne
0
duffduffduff Messages postés 12 Date d'inscription vendredi 23 octobre 2015 Statut Membre Dernière intervention 11 mars 2022
23 oct. 2016 à 11:38
Génial rien n'est impossible en fait ;-) mais j'ai encore un mais

var Focus : TObject; //ca c'est ok

edit1onenter --> Focus:= Sender; //tout va bien

pour la suite je beug !

If Focus is TCustomControl then With (Focus as TCustomControl) do Text:= Text + lettre du clavier;

l'App se compile mais rien ne se passe. ai-je raté un épisode ?
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
23 oct. 2016 à 15:09
Comme quoi trop de contrôle tue le contrôle, je pensais vous rendre service en vous indiquant la version bien encadrée que je n'utilise jamais pour ma part, mais elle fonctionne un peu différemment de ce que je croyais jusqu'ici, puisque je découvre que les opérateurs "is" et "as" ne fonctionnent que si le type correspond strictement, et c'est sans doute pourquoi j'ai abandonné leur utilisation il y a longtemps d'ailleurs! Alors, pour le fonctionnement tel que je le décrivais, il faut donc utiliser la méthode InheritsFrom à la place du "is", et le transtypage forcé à la place du "as":

If (Focus <> nil) and Focus.InheritsFrom(TCustomControl) then With TCustomControl(Focus) do Text:= Text + lettre du clavier;

Donc, on commence par tester la validité (pointeur non nul) de Focus car on appelle une méthode à partir de son pointeur;
"InheritsFrom" renvoie Vrai si la classe spécifiée correspond à celle de l'objet ou à l'un de ses ancêtre;
TCustomControl(Focus) permet de forcer le compilateur à utiliser l'objet en tant que...

Par ailleurs, pour savoir ce qui fonctionne de travers, rien de tel que le débuggeur intégré! La touche F4 permet d'exécuter jusqu'à la ligne du cureur et de s'y arrêter, F7 avance pas-à-pas au gré des appels de fonctions, F8 est un pas-à-pas superficiel, et F9 exécute jusqu'au bout.
Lorsque le programme est arrêté sur une ligne, il est possible d'inspecter la valeur de certaines variables et de les suivre, ce qui est extrêmement précieux pour vérifier la conformité du déroulement du code...

Le debuggeur fonctionne ligne par ligne uniquement, donc il est parfois nécessaire de découper les lignes en plusieurs parties:
If (Focus <> nil) and Focus.InheritsFrom(TCustomControl) then
With TCustomControl(Focus) do
Text:= Text + lettre du clavier;
0
duffduffduff Messages postés 12 Date d'inscription vendredi 23 octobre 2015 Statut Membre Dernière intervention 11 mars 2022
24 oct. 2016 à 16:18
toujours rien ... j'essaye de trouver par moi même pour arrêter de passer pour un assisté ;-) mais rien y fait... Merci encore et toujours pour le temps que vous prenez pour m'aider
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
24 oct. 2016 à 22:05
Haa baah c'est de ma faute, c'est que j'ai écris TCustomControl au lieu de TCustomEdit, TCustomControl n'étant pas ancêtre des contrôles de type Edit! Je travaille trop en ce moment! Et je travaille trop avec TCustomControl!
TCustomEdit est l'ancêtre le plus proche en commun entre le TEdit et le TDbEdit, et contient le propriété "Text", alors que le fait de mettre "With TCustomControl(Focus) do" ne génère pas d'erreur car le compilateur trouve la propriété "Text" dans "Form1"...

Et le "is" et "as" fonctionnent bien sur les ancêtres donc, c'est moi qui fait l'erreur depuis le début, désolé!

Promis, cette ligne-là fonctionne, et cette fois je l'ai testée avant!

If Focus is TCustomEdit then With (Focus as TCustomEdit) do Text:= Text + lettre du clavier;

Ça montre la difficulté de cerner les erreurs en prog, car celle-ci a beau être évidente, mais quand on s'est mis dans la tête que c'est tel nom et pas tel autre, on ne le voit plus! D'autres erreurs sont bien plus sournoises, et l'intérêt du debuggeur intégré se fait vite sentir pour les détecter!
0
duffduffduff Messages postés 12 Date d'inscription vendredi 23 octobre 2015 Statut Membre Dernière intervention 11 mars 2022
25 oct. 2016 à 00:28
MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI MERCI

Si le temps vous le permet... j'ai une question que j'ai déjà posée sur un forum à laquelle personne n'a su répondre. Une connaissance "un petit génie autodidacte en informatique" qui à crée pour les versions à partir de D3 un composant "AUTOTABLE" en table Ado qui est sensé rafraîchir(refresh) automatiquement une table d'un base de donnée en réseau lorsqu'une modification y est apportée.

Le composant fonction en tant que table Ado mais le problème est je n'arrive pas trouver la subtilité de ce pourquoi il a été inventé ... autrement dit s'auto-rafraîchir

J'ai bien essayé de contacter ce Monsieur, mais il a beaucoup de travaille et n'a gère le temps de s'occuper d'un petit composant (aujourd'hui surement sans internet pour lui) qui a créer il y a plus de 18 ans ....

Voici le lien ou vous pouvez le trouver : https://torry.net/authorsmore.php?id=1241

Mais comme je l'ai dit, pas d'urgence juste beaucoup de curiosité.

PS : je l'ai teste sous D6 avec Accès et Paradox

@+
0