IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

associer un evenement à un composant crée en dynamique


Sujet :

Langage Delphi

  1. #1
    Membre confirmé

    Inscrit en
    Novembre 2002
    Messages
    760
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 760
    Points : 499
    Points
    499
    Par défaut associer un evenement à un composant crée en dynamique
    Bonjour à tous

    [DELPHI RIO]
    [ WINDOWS 10]
    Même si ce post est la suite de mon post sur les port RS232 virtuel, j'en crée un nouveau car il ne traitement pas le même sujet de programmation.

    Le but est de détecteur tous les ports séries actifs sur le pc, d'y associer des composants "TComport" et TcomDataPacket" de l'unité "Cport".

    Le processus que j'essaye de mettre ne œuvre fonctionne avec des composant en statique.

    La première procédure ci-dessous "RechercheEtAssignRs232Actif" s'occupe de détecter les port séries et d'y associer les composants. Elle fonctionne au moins pour le "TComport", car je sais que j’écris bien dans l'appareil connecté sur le port.

    Pour le composant 'TcomDataPacket', je sais pas ... car même si la déclaration de mon événement me semble correcte (procédure "LitAdresse"), je ne reçois en dynamique aucune réponse.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    procedure TFRS232.RechercheEtAssignRs232Actif;
    Var i,j:integer;
        PortExistant:array[ 1 .. 250] of boolean;
    begin
       // On passe tous les ports séries possible du PC et on reécupère dans une
       // liste lequels sont accessibles.
       J:=1;
       for i:=1 to 250 do
       begin
           Comport1.Port:= 'COM'+inttostr(i);
           // on essaye de se connecteur au port pour voir s'il existe.
           Comport1.Connected:=true;
           if PortOpen=true then
           begin
               PortRs232[J].NomPort:='COM'+inttostr(i);
               inc(J);
               if J=11 then break;
           end;
           Comport1.Connected:=false;
       end;
     
       // On associé un composant "TcomPort" et un composant TcomDataPacket à
       // chaque port detecté.
       for i:=1 to 10 do
       begin
           if PortRs232[i].NomPort<>'' then
           begin
               PortRs232[i].CompoP:=Tcomport.create(self);
               with PortRs232[i].CompoP do
               begin
                    Parent:=self;
                    Port:= PortRs232[i].NomPort;
                    BaudRate:=br9600;
                    databits:=dbEight;
                    StopBits:=sbOneStopBit;
                    Parity.Bits :=prNone;
               end;
     
               PortRs232[i].CompoD:=TcomDataPacket.create(self);
               with PortRs232[i].CompoD do
               begin
                    Parent:=self;
                    Comport:= PortRs232[i].CompoP;
                    Onpacket:=LitAdresse;
               end;
     
               // On envoie un ordre RS232 à l'appareil connecté sur le port serie courant
               // pour qu'il me retourne sont ID
               PortRs232[i].compoP.connected:=true;
               PortRs232[i].compoP.WriteStr('ADRESS?'+#10);
           end;
        end;
    end;
     
     
    Procedure TFRS232.LitAdresse(Sender: TObject;const Str: string);
    var i:integer;
    begin
      if (sender is TcomDataPacket) then
      begin
          for i := 1 to 10 do
          begin
             if (sender as TcomDataPacket) = PortRs232[i].CompoD then  PortRs232[i].Adresse:=str;
          end;
      end;
    end;

    Je pense que mon erreur viens de la déclaration de l'événement sans comprendre pourquoi !

    des idées , des conseils ou tout autre aide est la bien venue..

    Merci a vous.

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 879
    Points : 11 377
    Points
    11 377
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    Je lis ici que l'événement OnPacket n'est déclenché qu'à la réception d'une trame répondant aux critères fixés (longueur, début, fin).
    Or je ne vois pas fixer ces propriétés dans ton code : suffit-il de les affecter pour que l'événement se déclenche bien comme tu l'attends ?

  3. #3
    Membre confirmé

    Inscrit en
    Novembre 2002
    Messages
    760
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 760
    Points : 499
    Points
    499
    Par défaut
    salut tourlourou et les autres ,

    Entre mon post précédant et maintenant j'avais essayé aussi cela et fixé la trame à l'identique de celle qui fonctionne en statique.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
       ....
       PortRs232[i].CompoD:=TcomDataPacket.create(self);
       with PortRs232[i].CompoD do
       begin
              Parent:=self;
              Comport:= PortRs232[i].CompoP;
              Onpacket:=LitAdresse;
              StartString:='';
              StopString:='';
              IncludeStrings:=false;
              CaseInsensitive:=false;
        end;
        ...
    Et c'est pareil.

  4. #4
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 879
    Points : 11 377
    Points
    11 377
    Billets dans le blog
    6
    Par défaut
    Bonsoir,
    Cet événement semble utile pour recevoir des trames dont on connaît le format à l'avance (début, fin, taille).
    Peut-on l'utiliser sans indiquer de taille ni de caractères délimiteurs ?

  5. #5
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    alors si je comprend bien, ça fonctionne quand tu crées le composants sur la fiche, mais pas quand tu le crées dynamiquement ?

    est-ce que tu peux faire un copier/coller du composant sur le forum...tu obtiendras la partie du DFM qui concerne le composant.

    par ailleurs, au lieu de bidouiller l'évènement Onpacket pour savoir qui est le sender, il est plus simple de dériver du composant

    exemple (au pif d'après ton code)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    type
      TMoncomDataPacket = class(TcomDataPacket)
      private
        Adresse: string;
        procedure LitAdresse(Sender: TObject;const Str: string);
      public
        constructor Create(AOwner: TComponent); override;
      end;
     
    constructor Create(AOwner: TComponent);
    begin
      inherited;
      Onpacket:=LitAdresse;
    end;
     
    procedure TMoncomDataPacket.LitAdresse(Sender: TObject;const Str: string);
    begin
      Adresse := Str;
    end;
     
    begin
      PortRs232[i].CompoD:=TMoncomDataPacket.create(self);
      ...
    end.
    il existe aussi probablement une méthode virtuelle DoPacket qui invoque OnPacket; tu dois dois pouvoir la surcharger au lieu de modifier OnPacket...en tout cas c'est souvent le cas dans la VCL.

    et tu peux mettre aussi tout le code d'initialisation dans le constructor avec des paramètres en plus si nécessaire

    et ce que tu as dans PortRs232[] doit pouvoir aussi se mettre dans la classe TMoncomDataPacket , ton tableau ne sera alors qu'un tableau de TMoncomDataPacket

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 665
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 665
    Points : 25 459
    Points
    25 459
    Par défaut
    En C++Builder, j'utilisais TComPort exclusivement en Dynamique : https://www.developpez.net/forums/d1...3/#post7102672
    A lire si cela peut t'inspirer : https://www.developpez.net/forums/d7...a/#post6551900

  7. #7
    Membre confirmé

    Inscrit en
    Novembre 2002
    Messages
    760
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 760
    Points : 499
    Points
    499
    Par défaut
    Bonjour a tous;

    Tourlourou,
    En fonctionnement en statique, les appareils me retournent tous une valeur différentes sur deux caractères suivies des deux caractères 0Ah et 0Dh.
    Que j'indique ou pas ces deux caractères de "retour chariot" et de "fin de ligne" en tant que "StopString" ne change rien je reçois les bonnes valeurs. Ces deux caractères "retour chariot" et "fin de ligne" doivent être automatiquement filtrés par le composant.
    J'ai aussi déjà utilisé ses délimiteurs de trame, mais quand je gérais les deux cotés de l'émission et sur de longue trame. Là je lis simplement la doc fournie avec l'appareil, qui m'indique comment lire ce code de deux caractères. Les appareil m'envoie par exemple "10 0Ah 0Dh" pour une adresse = 10.

    Paul TOTH
    Oui, cela fonctionne parfaitement quand les composants sont posés sur la fiche. Je pourrai travailler comme cela, mais je voudrai faire quelque chose de plus universel :
    Car mon application n'est pas figée à un nombre de port, cela varie en fonction des clients et de l'utilisation. je voulais automatiser un peu la configuration de tout cela au démarrage du système.
    Mon idée était Au démarrage :
    Détecter tous les ports actifs : qui autorise une connexion.
    Si le port est actif, voir si quelqu'un est connecté dessus et s'il répond à ma demande de lecture d'une info (adresse)
    Si une adresse valide est renvoyée, associer cette adresse au port COM(x) que lequel j'ai écris.
    Ensuite quand je veux dialoguer avec un appareil j'utilise son adresse sans tenir compte du com(x), transcodage de l'adresse en com(x)
    Pour rappel : Tous cela car ces systèmes fonctionnes sous Windows10, donc tous les ports séries sont virtuels et je ne connais pas en avance sur quel port sont connectés les appareils.

    Tu veux le composant dans se format Texte ? OK

    Je ne suis pas à l'aise avec les création de composant, d'héritage ou de deriver un composant

    Quand tu dis "bidouiller l'évènement OnPacket" qu'entends tu par là? que le fais de rechercher le nom du "Sender" dans un évènement n'est pas très pertinent ?

    Je pensais aussi que cela se ferais tout seul (ahah), la création de composants en dynamique ne m'avait pas posé bcp de problème jusqu'à présent ?. Surtout que cela fonctionne comme je le souhaite avec 2 ports en statiques donc avec deux appareils.
    Le choix de passer en dynamique était juste d'éviter de déclarer en permanence une 15ene de ports qui ne seraient pas utilisés et surtout que lors de la création virtuelle des ces Com(x) je ne connais pas le numéro du com.

    ShaireLetroll,

    Je vais lire les post en question.

    Merci a vous tous.

  8. #8
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 879
    Points : 11 377
    Points
    11 377
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    L'idée de Paul Toth était d'ouvrir en mode texte le fichier dfm de la fiche d'un programme fonctionnel sur laquelle est déposé un TcomDataPacket créé au design time pour voir ses propriétés et s'il y a une différence avec celles assignées lors d'une création dynamique.

  9. #9
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    Bonjour,
    L'idée de Paul Toth était d'ouvrir en mode texte le fichier dfm de la fiche d'un programme fonctionnel sur laquelle est déposé un TcomDataPacket créé au design time pour voir ses propriétés et s'il y a une différence avec celles assignées lors d'une création dynamique.
    oui, c'est presque ça

    en fait si tu fais le "Copier" d'un composant de la fiche, tu peux le coller ici même pour avoir la portion du DFM qui le concerne, il n'est pas nécessaire d'aller recherche le composant dans le fichier DFM à la main.

  10. #10
    Membre confirmé

    Inscrit en
    Novembre 2002
    Messages
    760
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 760
    Points : 499
    Points
    499
    Par défaut
    Bonjour

    voici le code ou je crée les composants dynamiques :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    // On associé un composant "TcomPort" et un composant TcomDataPacket à chaque port détecté (10 max dans cet exemple).
     
    for i:=1 to 10 do
       begin
           if PortRs232[i].NomPort<>'' then
           begin
               PortRs232[i].CompoP:=Tcomport.create(self);
               with PortRs232[i].CompoP do
               begin
                    Parent:=self;
                    Port:= PortRs232[i].NomPort;
                    BaudRate:=br9600;
                    databits:=dbEight;
                    StopBits:=sbOneStopBit;
                    Parity.Bits :=prNone;
               end;
     
               PortRs232[i].CompoD:=TcomDataPacket.create(self);
               with PortRs232[i].CompoD do
               begin
                    Parent:=self;
                    Comport:= PortRs232[i].CompoP;
     
                    Onpacket:=LitAdresse;
     
                    Ondiscard:=Discard;
     
                    StartString:='';
                    StopString:='';
                    IncludeStrings:=false;
                    CaseInsensitive:=false;
               end;
     
               // On envoie un ordre RS232 à l'appareil connecté sur le port courant
               // pour connaitre sint ID
               PortRs232[i].compoP.connected:=true;
               PortRs232[i].compoP.WriteStr('ADDRESS?'+#10);
               application.ProcessMessages;
           end;
        end;
    La différence avec le code précédant : dans les créations des "TcomDataPacket" j'ai ajouté :
    - Les propriétés de la trame de réception ( qui ne servent a rien a priori...)
    - L’événement "Ondiscard" pour voir si je recevais des caractères "hors trame", aucun événement n'est déclenchés ni OnDiscard ni OnPacket.
    J'ai aussi ajouté un "ProcessMessage" dans la boucle pour déclencher les événements.


    Ci dessous les composants tels qu'ils sont posés sur la fiche, et tel qu'ils fonctionnent.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    object ComPort1: TComPort
      BaudRate = br9600
      Port = 'COM1'
      Parity.Bits = prNone
      StopBits = sbOneStopBit
      DataBits = dbEight
      Events = [evRxChar, evTxEmpty, evRxFlag, evRing, evBreak, evCTS, evDSR, evError, evRLSD, evRx80Full]
      FlowControl.OutCTSFlow = False
      FlowControl.OutDSRFlow = False
      FlowControl.ControlDTR = dtrDisable
      FlowControl.ControlRTS = rtsDisable
      FlowControl.XonXoffOut = False
      FlowControl.XonXoffIn = False
      Timeouts.ReadTotalConstant = 3000
      StoredProps = [spBasic]
      TriggersOnRxChar = False
      Left = 444
      Top = 35
    end
     
     
    object ComDataPacket1: TComDataPacket
      ComPort = ComPort1
      OnPacket = ComDataPacket1Packet
      Left = 516
      Top = 43
    end
    A bientot pour vos remarques , s'il y en a !

  11. #11
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    si j'en crois le constructor qui se trouve ici il n'y a qu'un différence sur TriggersOnRxChar, et si j'ai bien compris le code de TCustomComPort.CallRxChar ça fait une grosse différence.

  12. #12
    Membre confirmé

    Inscrit en
    Novembre 2002
    Messages
    760
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 760
    Points : 499
    Points
    499
    Par défaut
    bonjour

    Après réorganisation mon code, sans vraiment en voir la différence entre les deux versions.
    J'ai juste nommé les composants à la création. Puis je passe par un "FindComponent" sur la fiche pour les retrouver et les utiliser.

    Ben le résultat attendu est là.

    Merci à vous tous pour vos conseils

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. gestion d'un evenement sur composant dynamique
    Par darkman13130 dans le forum C++Builder
    Réponses: 2
    Dernier message: 19/03/2009, 15h16
  2. Réponses: 5
    Dernier message: 05/09/2008, 17h17
  3. Réponses: 2
    Dernier message: 02/08/2006, 23h54
  4. effacer des composants crée dynamiquement
    Par forzaxelah dans le forum Delphi
    Réponses: 7
    Dernier message: 29/06/2006, 14h14
  5. Composant crée dynamiquement & Access in invalid memory
    Par Sunchaser dans le forum C++Builder
    Réponses: 4
    Dernier message: 12/02/2005, 01h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo