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

Delphi Discussion :

Evenement et recupération


Sujet :

Delphi

  1. #1
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Par défaut Evenement et recupération
    Salut à tous.
    J'ai une classe de base
    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
     
      TAncestorClass = Class
      private
        FErrorNum: TErrorType;
        FInternalNum: Integer;
        FErrorDesc: String;
        FonError: TNotifyEvent;
        procedure SetErrorDesc(const Value: String);
        procedure SetErrorNum(const Value: TErrorType);
        procedure SetInternalNum(const Value: Integer);
        procedure SetonError(const Value: TNotifyEvent);
      protected
        procedure DoError;
        property  OnError      : TNotifyEvent read FOnError write SetOnError;
      published
        property InternalNum  : Integer read FInternalNum write SetInternalNum;
        property ErrorNum     : TErrorType read FErrorNum write SetErrorNum;
        property ErrorDesc    : String read FErrorDesc write SetErrorDesc;
      end;
    Implementation
     
    procedure TAncestorClass.DoError;
    begin
      If Assigned(FOnError) then
        FOnError(Self);
    end;
     
    procedure TAncestorClass.SetErrorDesc(const Value: String);
    begin
      If FErrorDesc <> Value then
        FErrorDesc := Value;
    end;
     
    procedure TAncestorClass.SetErrorNum(const Value: TErrorType);
    begin
      If FErrorNum <> Value then
      begin
        FErrorNum := Value;
        if FErrorNum = etError then
          DoError;
      end;
    end;
     
    procedure TAncestorClass.SetInternalNum(const Value: Integer);
    begin
      If FInternalNum <> Value then
        FInternalNum := Value;
    end;
     
    procedure TAncestorClass.SetOnError(const Value: TNotifyEvent);
    begin
      FOnError := Value;
    end;
    deux classe descendant TChildAClass et tChildBClass qui sont similaire (pour le test)
    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
     
      TChildBClass  = Class(TAncestorClass)
      private
        FStrOne: String;
        procedure SetStrOne(const Value: String);
      published
        property StrOne : String read FStrOne write SetStrOne;
        property OnError;
      end;
    implementation
    procedure TChildAClass.SetStrOne(const Value: String);
    begin
      if FStrOne <> Value then
      begin
        FStrOne := Value;
        if Length(FStrOne) > 15 then
        begin
          ErrorDesc  := 'Length string out of range in class : '+Self.ClassName;
          ErrorNum   := etError;
          FStrOne := '';
        end;
      end;
    end;
    Une autre classe heritant de TAnestorClass et qui instancie les 2 autres classes
    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
     
      TMixClass = Class(TAncestorClass)
      private
        FChildA: TChildAClass;
        FChildB: TChildBClass;
        procedure SetChildA(const Value: TChildAClass);
        procedure SetChildB(const Value: TChildBClass);
      published
        property ChildA : TChildAClass read FChildA write SetChildA;
        property ChildB : TChildBClass read FChildB write SetChildB;
        property OnError;
      public
        constructor create;
        destructor destroy; Override;
      end;
    implementation
    constructor TMixClass.create;
    begin
      Inherited Create;
      ChildA  := TChildAClass.Create;
      ChildB  := TChildBClass.Create;
    end;
     
    destructor TMixClass.destroy;
    begin
      ChildA.Free;
      ChildB.Free;
      inherited;
    end;
     
    procedure TMixClass.SetChildA(const Value: TChildAClass);
    begin
      FChildA := Value;
    end;
     
    procedure TMixClass.SetChildB(const Value: TChildBClass);
    begin
      FChildB := Value;
    end;
    La question :
    Comment implementer l'event OnError au niveau de TMixClass pour que les OnError de ChildA et ChildB soit intercepté.

    Merci

  2. #2
    Membre Expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 568
    Par défaut
    Salut


    Si j'ai bien compris ton problème, la solution est simple :

    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
     
    TMixClass = Class(TAncestorClass)
      private
        FChildA: TChildAClass;
        FChildB: TChildBClass;
        procedure SetChildA(const Value: TChildAClass);
        procedure SetChildB(const Value: TChildBClass);
      published
        property ChildA : TChildAClass read FChildA write SetChildA;
        property ChildB : TChildBClass read FChildB write SetChildB;
        property OnError;
      public
        constructor create;
        destructor destroy; Override;
      end;
    implementation
    constructor TMixClass.create;
    begin
      Inherited Create;
      FChildA := TChildAClass.Create;
      FChildA.OnError := OnError;
      FChildB := TChildBClass.Create;
      FChildB.OnError := OnError;
    end;
     
    destructor TMixClass.destroy;
    begin
      ChildA.Free;
      ChildB.Free;
      inherited;
    end;
     
    procedure TMixClass.SetChildA(const Value: TChildAClass);
    begin
      FChildA := Value;
      FChildA.OnError := OnError;
    end;
     
    procedure TMixClass.SetChildB(const Value: TChildBClass);
    begin
      FChildB := Value;
      FChildB.OnError := OnError;
    end;
    est-ce ce que tu attendais ?

    Remarque 1 : TMixClass est par construction propriétaire de ChildA et ChildB (TMixClass assure la création et la destruction de ces objets) or tu donne accès en écriture à ces objets, c'est risqué.

    Remarque 2 : Un événement n'est pas implémenté au niveau d'une classe mais rattaché à une instance de cette classe.

    cdlt

    e-ric

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  3. #3
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Par défaut
    En faites j'aimerais faires simplement :
    FOnError = FChildA.OnError or FChildB.OnError

    Comment realiser cela.

    Car actuellement, je dois faire comme ceci pour arriver à mes fin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    procedure TForm1.OnMixError(Sender: TObject);
    begin
      MessageDlg(Pchar((Sender as TAncestorClass).ErrorDesc), mtError, [mbOK], 0);
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Mix := TMixClass.create;
      Mix.ChildA.OnError  := OnMixError;
      Mix.ChildB.OnError  := OnMixError;
    end;
    Merci

  4. #4
    Membre Expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 568
    Par défaut
    je ne comprend pas bien ceci :
    Citation Envoyé par Andry
    En faites j'aimerais faires simplement :
    FOnError = FChildA.OnError or FChildB.OnError

    Comment realiser cela.

    Car actuellement, je dois faire comme ceci pour arriver à mes fin :

    Code:
    procedure TForm1.OnMixError(Sender: TObject);
    begin
    MessageDlg(Pchar((Sender as TAncestorClass).ErrorDesc), mtError, [mbOK], 0);
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    Mix := TMixClass.create;
    Mix.ChildA.OnError := OnMixError;
    Mix.ChildB.OnError := OnMixError;
    end;
    Merci
    Veux-tu affecter automatiquement les 2 événements FChildA.OnError or FChildB.OnError à l'affectation de MixClass.OnError ?

    e-ric

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  5. #5
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Par défaut
    Salut,
    Pour plus d'infos, les classes seront utilisés pour des saisies avec des controles très rigoureux (genre nb car, contenue, etc), donc j'ai implementé un evenement OnError et verifie chaque affectation de valeur et si valeur non conforme, on stop tout au niveau de l'appli.
    La saisie concerne pas mal de domaine donc j'ai découpé en plusisuers classes afin de rendre la maintenance plus aisée.

    J'ai le choix entre deux utilisation :
    - Soit déclarer des objets de type ChildX et utiliser ces objets directement. (Celui ci est bon, ça marche)
    - Soit créer une Class qui incorpore tous les childs et instancié celui ci.
    C'est cette dernière que j'essaie de mettre en oeuvre, mais je me butte sur l'evenement OnError. Comment au niveau de TMixClass, savoir qu'un Event s'est produit dans ces membres.

    Merci

  6. #6
    Membre Expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 568
    Par défaut
    Il est difficile de déterrminer si un événement a été déclenché, un événement est une adresse de méthode (deux pointeurs en fait).

    Une solution consiste à notifier l'exécution de l'événement OnError à ton objet TMixClass.
    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
     
      TMixClass = Class(TAncestorClass)
      private
        FChildA: TChildAClass;
        FChildB: TChildBClass;
        procedure SetChildA(const Value: TChildAClass);
        procedure SetChildB(const Value: TChildBClass);
      published
        property ChildA : TChildAClass read FChildA write SetChildA;
        property ChildB : TChildBClass read FChildB write SetChildB;
        property OnError;
      public
        constructor create;
        destructor destroy; Override;
        procedure NotifyError(Error: TAncestorClass);
      end;
     
    implementation
     
    constructor TMixClass.create;
    begin
      Inherited Create;
      ChildA  := TChildAClass.Create;
      ChildB  := TChildBClass.Create;
    end;
     
    destructor TMixClass.destroy;
    begin
      ChildA.Free;
      ChildB.Free;
      inherited;
    end;
     
    procedure TMixClass.SetChildA(const Value: TChildAClass);
    begin
      FChildA := Value;
    end;
     
    procedure TMixClass.SetChildB(const Value: TChildBClass);
    begin
      FChildB := Value;
    end;
     
    procedure TMixClass.NotifyError(Error: TAncestorClass);
    begin
    // le code de traitement
    End;
    // -------------------------------------------------
    // puis dans le code client
    procedure TForm1.OnMixError(Sender: TObject);
    begin
      if Sender is TAncestorClass then
      begin
        Mix.NotifyError(Sender as TAncestorClass)
        MessageDlg(Pchar((Sender as TAncestorClass).ErrorDesc), mtError, [mbOK], 0);
      end;
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Mix := TMixClass.create;
      Mix.ChildA.OnError  := OnMixError;
      Mix.ChildB.OnError  := OnMixError;
    end;
    Cela a le mérite d'être simple. Est-ce que cela te suffit ?

    Il est possible de rendre la notification implicite et éviter ainsi l'appel Mix.NotifyError; mais il faut modifier la conception de tes classes TMixClass et TChilX de façon à implémenter clairement les relations de composant(TChilX) à composé (TMixClass).

    cdlt

    e-ric

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  7. #7
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Par défaut
    Merci à toi de pencher sur mes problèmes.
    Tu disais en bas qu'il est possible de rendre la notification implicite et éviter ainsi l'appel Mix.NotifyError; mais qu'il faut modifier la conception de tes classes TMixClass et TChilX de façon à implémenter clairement les relations de composant(TChilX) à composé (TMixClass).
    Peux tu me dire comment le faire.
    J'aime mieux tout refaire s'il le faut et aussi avoir des bonnes pratiques.

    Merci

  8. #8
    Membre Expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 568
    Par défaut
    je te donne des pistes
    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
     
      TAncestorClass = Class
      private
        FErrorNum: TErrorType;
        FInternalNum: Integer;
        FErrorDesc: String;
        FonError: TNotifyEvent;
        procedure SetErrorDesc(const Value: String);
        procedure SetErrorNum(const Value: TErrorType);
        procedure SetInternalNum(const Value: Integer);
        procedure SetonError(const Value: TNotifyEvent);
      protected
        procedure DoError; virtual;
        property  OnError      : TNotifyEvent read FOnError write SetOnError;
      published
        property InternalNum  : Integer read FInternalNum write SetInternalNum;
        property ErrorNum     : TErrorType read FErrorNum write SetErrorNum;
        property ErrorDesc    : String read FErrorDesc write SetErrorDesc;
      end;
     
      // Classe "abstraite" destinée à implémenter les interactions dans le déclenchement
      // et l'interception du gestionnaire OnError
      TOwnerClass = Class(TAncestorClass)
      private
      protected  
        procedure NotifyError(Error: TAncestorClass); virtual;
      public
      end;
     
      TOwnedClass = Class(TAncestorClass)
      private
        FOwner: TOwnerClass;
      protected
        property Owner: TOwnerClass read FOwner;
        procedure DoError; override;
      public
     
      end;
     
      TChildBClass  = Class(TOwnedClass)
      private
        FStrOne: String;
        procedure SetStrOne(const Value: String)
      published
        property StrOne : String read FStrOne write SetStrOne;
        property OnError;
      end;  
     
      TMixClass = Class(TOwnerClass)
      private
        FChildA: TChildAClass;
        FChildB: TChildBClass;
        procedure SetChildA(const Value: TChildAClass);
        procedure SetChildB(const Value: TChildBClass);
      published
        property ChildA : TChildAClass read FChildA write SetChildA;
        property ChildB : TChildBClass read FChildB write SetChildB;
        property OnError;
      public
        constructor create;
        destructor destroy; Override;
      end;
     
    Implementation
     
    { TAncestorClass }
     
    procedure TAncestorClass.DoError;
    begin
      If Assigned(FOnError) then
        FOnError(Self);
    end;
     
    procedure TAncestorClass.SetErrorDesc(const Value: String);
    begin
      If FErrorDesc <> Value then
        FErrorDesc := Value;
    end;
     
    procedure TAncestorClass.SetErrorNum(const Value: TErrorType);
    begin
      If FErrorNum <> Value then
      begin
        FErrorNum := Value;
        if FErrorNum = etError then
          DoError;
      end;
    end;
     
    procedure TAncestorClass.SetInternalNum(const Value: Integer);
    begin
      If FInternalNum <> Value then
        FInternalNum := Value;
    end;
     
    procedure TAncestorClass.SetOnError(const Value: TNotifyEvent);
    begin
      FOnError := Value;
    end;
     
    { TOwnerClass } 
    procedure TOwnerClass.NotifyError(Error: TAncestorClass);
    begin
      // Code de ta méthode
    End;
     
    { TOwnedClass }  
    procedure TOwnedClass.DoError;
    begin
      // interception du gestionnaire OnError, le propriétaire est 
      // informé du déclenchement
      Owner.NotifyError(self);
      If Assigned(FOnError) then
        FOnError(Self);
    end;
     
    { TChildBClass }
     
    procedure TChildBClass.SetStrOne(const Value: String);
    begin
      if FStrOne <> Value then
      begin
        FStrOne := Value;
        if Length(FStrOne) > 15 then
        begin
          ErrorDesc  := 'Length string out of range in class : '+Self.ClassName;
          ErrorNum   := etError;
          FStrOne := '';
        end;
      end;
    end;
     
    { TMixClass }
     
    constructor TMixClass.create;
    begin
      Inherited Create;
      ChildA  := TChildAClass.Create;
      ChildB  := TChildBClass.Create;
    end;
     
    destructor TMixClass.destroy;
    begin
      ChildA.Free;
      ChildB.Free;
      inherited;
    end;
     
    procedure TMixClass.SetChildA(const Value: TChildAClass);
    begin
      FChildA := Value;
    end;
     
    procedure TMixClass.SetChildB(const Value: TChildBClass);
    begin
      FChildB := Value;
    end;
    Grâce à cette conception, l'instruction Mix.NotifyError(Sender as TAncestorClass) ne présente plus d'intérêt dans les gestionnaire d'événements de ChildA et ChildB.

    Rem : Le NotifyError pourrait être un événement plutôt qu'une méthode (je te laisse le soin de réaliser cette adaptation si elle est nécessaire).

    Est-ce que la conception proposée est une solution à ton problème ?

    cdlt

    e-ric

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  9. #9
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Par défaut
    Meric e-ric,
    J'ai un peu modifier ta source afin pour que ça fonctionne.(J'ai mis la propriété Owner en lecture ecriture car en l'etat des chose, j'ai un beau erreur de violation).
    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
     
    unit EvClasses;
     
    interface
    Uses Classes;
     
    type
      TErrorType     = (etNone,etOk,etWarning,etError);
      TAncestorClass = Class
      private
        FErrorNum: TErrorType;
        FInternalNum: Integer;
        FErrorDesc: String;
        FonError: TNotifyEvent;
        procedure SetErrorDesc(const Value: String);
        procedure SetErrorNum(const Value: TErrorType);
        procedure SetInternalNum(const Value: Integer);
        procedure SetonError(const Value: TNotifyEvent);
      protected
        procedure DoError; virtual;
        property  OnError      : TNotifyEvent read FOnError write SetOnError;
      published
        property InternalNum  : Integer read FInternalNum write SetInternalNum;
        property ErrorNum     : TErrorType read FErrorNum write SetErrorNum;
        property ErrorDesc    : String read FErrorDesc write SetErrorDesc;
      end;
     
      // Classe "abstraite" destinée à implémenter les interactions dans le déclenchement
      // et l'interception du gestionnaire OnError
      TOwnerClass = Class(TAncestorClass)
      private
      protected  
        procedure NotifyError(Error: TAncestorClass); virtual;
      public
      end;
     
      TOwnedClass = Class(TAncestorClass)
      private
        FOwner: TOwnerClass;
      protected
        property Owner: TOwnerClass read FOwner write FOwner;
        procedure DoError; override;
      public
     
      end;
     
      TChildAClass  = Class(TOwnedClass)
      private
        FStrOne: String;
        procedure SetStrOne(const Value: String);
      published
        property StrOne : String read FStrOne write SetStrOne;
        property OnError;
      end;
     
      TChildBClass  = Class(TOwnedClass)
      private
        FStrOne: String;
        procedure SetStrOne(const Value: String);
      published
        property StrOne : String read FStrOne write SetStrOne;
        property OnError;
      end;
     
      TMixClass = Class(TOwnerClass)
      private
        FChildA: TChildAClass;
        FChildB: TChildBClass;
      published
        property ChildA : TChildAClass read FChildA;
        property ChildB : TChildBClass read FChildB;
        property OnError;
      public
        constructor create;
        destructor destroy; Override;
      end;
     
    implementation
     
    { TAncestorClass }
     
    procedure TAncestorClass.DoError;
    begin
      If Assigned(FOnError) then
        FOnError(Self);
    end;
     
    procedure TAncestorClass.SetErrorDesc(const Value: String);
    begin
      If FErrorDesc <> Value then
        FErrorDesc := Value;
    end;
     
    procedure TAncestorClass.SetErrorNum(const Value: TErrorType);
    begin
      If FErrorNum <> Value then
      begin
        FErrorNum := Value;
      end;
      if FErrorNum = etError then
        DoError;
    end;
     
    procedure TAncestorClass.SetInternalNum(const Value: Integer);
    begin
      If FInternalNum <> Value then
        FInternalNum := Value;
    end;
     
    procedure TAncestorClass.SetOnError(const Value: TNotifyEvent);
    begin
      FOnError := Value;
    end;
     
    { TOwnerClass } 
    procedure TOwnerClass.NotifyError(Error: TAncestorClass);
    begin
      // Code de ta méthode
      FErrorNum   := Error.ErrorNum;
      FErrorDesc  := Error.ErrorDesc;
    End;
     
    { TOwnedClass }  
    procedure TOwnedClass.DoError;
    begin
      // interception du gestionnaire OnError, le propriétaire est
      // informé du déclenchement
      FOwner.NotifyError(self);
      If Assigned(FOwner.OnError) then
        FOwner.OnError(Self);
    end;
     
    { TChildAClass }
     
    procedure TChildAClass.SetStrOne(const Value: String);
    begin
      if FStrOne <> Value then
      begin
        FStrOne := Value;
        if Length(FStrOne) > 15 then
        begin
          ErrorDesc  := 'Length string out of range in class : '+Self.ClassName;
          ErrorNum   := etError;
          FStrOne := '';
        end
        else
          ErrorNum  := etOk;
      end;
    end;
     
    { TChildBClass }
     
    procedure TChildBClass.SetStrOne(const Value: String);
    begin
      if FStrOne <> Value then
      begin
        FStrOne := Value;
        if Length(FStrOne) > 15 then
        begin
          ErrorDesc  := 'Length string out of range in class : '+Self.ClassName;
          ErrorNum   := etError;
          FStrOne := '';
        end
        else
          ErrorNum  := etOk;
      end;
    end;
     
    { TMixClass }
     
    constructor TMixClass.create;
    begin
      Inherited Create;
      FChildA  := TChildAClass.Create;
      FChildB  := TChildBClass.Create;
      FChildA.Owner := Self;
      FCHildB.Owner := Self;
    end;
     
    destructor TMixClass.destroy;
    begin
      ChildA.Free;
      ChildB.Free;
      inherited;
    end;
    end.
    Ensuite j'ai testé avec une simple appli pour voir et ça marche.
    2 tEdit et 2 bouton pour tester l'erreur au niveau de StrOne.
    Un Gestionnaire onError pour afficher un message d'erreur au niveau de FMix.
    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
     
    unit Appel;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, EvClasses;
     
    Type
      TForm1 = class(TForm)
        Button1: TButton;
        Edit1: TEdit;
        Edit2: TEdit;
        Button2: TButton;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure MixError(Sender: TObject);
     
      private
        { Déclarations privées }
        FMix : TMixClass;
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      FMix  := TMixClass.create;
      FMix.OnError  := MixError;
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      FMix.Free;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      FMix.ChildA.StrOne := Edit1.Text;
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      FMix.ChildB.StrOne := Edit2.Text;
    end;
     
    procedure TForm1.MixError(Sender: TObject);
    begin
      MessageDlg(Pchar(FMix.ErrorDesc), mtError, [mbOK], 0);
    end;
    end.
    Et voilà, ça fonctionne.
    S'il y a encore d'autre suggestion, je suis preneur avant que je m'enfonce un peu.

    Encore merci

  10. #10
    Membre Expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 568
    Par défaut
    Oups! J'avais oublié quelques détails, désolé j'ai pas testé, voici un patch :

    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
     
      TOwnedClass = Class(TAncestorClass)
      private
        FOwner: TOwnerClass;
      protected	
        property Owner: TOwnerClass read FOwner;
        procedure DoError; override;
      public 
        constructor Create(Owner: TOwnerClass);
      end;
     
    implementation
     
    { TOwnedClass }
    constructor TOwnedClass.Create(Owner: TOwnerClass);
    begin
      inherited;
      FOwner := Owner;
    End;
     
    procedure TOwnedClass.DoError;
    begin
      // interception du gestionnaire OnError, le propriétaire est
      // informé du déclenchement
      if Assigned(FOwner) then
        FOwner.NotifyError(self);
      If Assigned(FOwner.OnError) then
        FOwner.OnError(Self);
    end;
     
    { TMixClass }
     
    // tu peux alors laisser la propriété Owner en lecture seule    
    constructor TMixClass.create;
    begin
      Inherited Create;
      FChildA  := TChildAClass.Create(self);
      FChildB  := TChildBClass.Create(self);
    end;
    Cela devrait aller mieux !

    e-ric

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  11. #11
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Par défaut
    Le patch fonctionne à merveille. Il faut juste spécifier Create
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    constructor TOwnedClass.Create(Owner: TOwnerClass);
    begin
      inherited Create;
      FOwner := Owner;
    End;
    Sinon le code ne se compile pas.(D7);

    Merci

Discussions similaires

  1. Réponses: 9
    Dernier message: 09/08/2012, 18h09
  2. [MVVM] recupération de l'evenement onclose() d'une winform 2.0 en WPF
    Par igorzup dans le forum Windows Presentation Foundation
    Réponses: 2
    Dernier message: 28/06/2012, 16h23
  3. Réponses: 2
    Dernier message: 22/12/2010, 16h56
  4. [JFrame] [MouseListener] recupérer evenement souris
    Par kikoufr dans le forum Agents de placement/Fenêtres
    Réponses: 2
    Dernier message: 19/08/2004, 18h45
  5. develloppement avec ORBit: service d'evenement
    Par belmontv dans le forum CORBA
    Réponses: 3
    Dernier message: 06/06/2002, 22h56

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