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

API, COM et SDKs Delphi Discussion :

Comment déclarer programmatiquement un évènement OnChange d'un TTntTreeView


Sujet :

API, COM et SDKs Delphi

  1. #1
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    361
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 361
    Billets dans le blog
    1
    Par défaut Comment déclarer programmatiquement un évènement OnChange d'un TTntTreeView
    Bonjour,

    Je suis sous W10 avec Delphi 6 PE et j'utilise ldes contrôles Unicode suivants:
    Tnt Delphi Unicode Controls
    http://www.tntware.com/delphicontrols/unicode/
    Version: 2.3.0
    J'essaie d'ajouter programmatiquement un évènement OnChange à un objet TTntTreeView que j'ai également créé programmatiquement.

    Je définis mon objet TntTreeView de la manière suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      type TMyTntTreeView = class(TPanel)
          private
          MyTreeView: TTntTreeView;
        published
          Constructor Create(AOwner: TComponent);
          Destructor Destroy; override;
      end;
    Je définis mes routines OnClick et OnChange de la manière suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    type
      TUnicodeObject = class(TWinControl)
        class procedure Click(Sender: TObject);
        class procedure TVChange(Sender: TObject; Node: TTntTreeNode);
      end;
    Voici le code de ces routines:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class procedure TUnicodeObject.Click(Sender: TObject);
    begin
      // ici, reaction pour un clic dans l'objet              
    end;
     
    class procedure TUnicodeObject.TVChange(Sender: TObject; Node: TTntTreeNode);
    begin
      // ici, réaction pour un changement dans un noeud de l'objet                   
    end;
    Voici le constructor et destructor de l'objet:
    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
    Constructor TMyTntTreeView.Create(AOwner: TComponent);
    begin
      inherited;
      ParentWindow := UnicodeParentWindow;
      MyTreeView := TTntTreeView.Create(self);
      MyTreeView.ParentWindow := self.Handle;
      self.Width := MyTreeView.Width;
      self.Height := MyTreeView.Height;
    end;
     
    Destructor TMyTntTreeView.Destroy;
    begin
      MyTreeView.Free;
      inherited;
    end;
    Et voici comment je crée l'objet:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          Obj := TMyTntTreeView.Create(nil);
          TMyTntTreeView(Obj).ParentWindow := hnd;
          TMyTntTreeView(Obj).MyTreeView.OnClick := TUnicodeObject.Click;
          TMyTntTreeView(Obj).MyTreeView.OnChange := TUnicodeObject.TVChange;   // <===== iei, erreur e compilation
    Or, à la compilation, j'obtiens ceci:
    Nom : aa1.png
Affichages : 156
Taille : 13,7 Ko

    Si je désactive la ligne avec OnChange, la compialtion passe, le programme est généré correctement et il fonctionne.
    Il crée proprement mon objet TMyTntTreeView, l'affiche dans la destinatioin voulue et réagit à l'évènement OnClick en cliquant dedans.

    On dirait le l'évènement OnChange de MyTreeView atteMyTreeView est boen nt un TTreeNode comme second paramètre.
    Or, MyTreeView est bien un TTntTreeView et la classe TTntTreeNode existe dans l'unité TTntTreeView.

    Auriez-vous une idée comment résoudre ce problème ? Ai-ce mal compris ? Est-ce un bug ?

    P.S.

    Exactement la même technique fonctionne pour un TTntEdit, TTntMemo et un TTntComboBox, avec évidemment une procédure OnChange dans le format d'un simple TNotifyEvent.

    EDIT

    D'ailleurs, le problème va plus loin. J'ai l'impression que le composant TTntTreeView n'est pas "fini'.
    Par exemple, il y a bien une classe TTntTreeNode,mais la méthode Select de TTntTreeView attend un TTreeNode, mais pas un TTntTreeNode.
    Conséquence: erreur en exécution.

    Est-ce que je m'en sers mal ou est-ce que j'utilise unne version dépassée ? sur le site du téléchargement, il était indiqué qu'il s'agissait de la dernière version: Version: 2.3.0

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 999
    Par défaut
    Juste avec le message, je dirais tout simplement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class procedure TVChange(Sender: TObject; Node: TTreeNode);
    C'est un TTreeNode génrique qu'il faut caster ensuite
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    361
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 361
    Billets dans le blog
    1
    Par défaut
    Merci d'avoir regardé, ShaiLeTrool, surtout un dimanche soir !

    Je reste perplexe.

    1. Dans ces unités des contrôles TNT, toutes les classes ayant un tapport avec String versus WideString snt redéfinies avec le préfixe TNT.
    Ainti, TTreeNode est redéfini en TTntTreeNode, avec la propriété Text en WiodeString. Logique.

    Donc, logiquement, dans la procédure TVChange, le paramètre Node devrait etre TTntTreeNode et non TTreeNode.
    Si je le faisais comme indiqué, en recastong Node après coup, cela conduit à un crash. ancore une fois logique.

    Par ailleurs, comme je l'ai dit dans mon EDIT, la méthode Select du TTntTreeNode attend un TTreeNode et non un TTntTreeNode.
    J'ai aussi remarqué que dans certain ce qui estes classes liées au TTntTreeeView, il reste des AnsiString.

    C'est pourquoi je me permets d'avancer ma prudente suggestion: l'implémentation de TTntTreeView n'est pas conduite jusqu'au bout.
    Je posterai bientôt un mini-projet avec un code minimal pour mettre cela en évidence.

  4. #4
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    361
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 361
    Billets dans le blog
    1
    Par défaut
    Voici le petit projet mettant le problème en évidence.

    Cliquer d'abour sur le bouton "Create"TreeView" --> le TntTreeView apparaît en haut à gauche.
    Il ne fait encore rien.

    Ciquer ensuite sur le bouton "Define OnClick" --> chaque clic sur le TntTreeView provoque un message dans le mémo.

    Le bouton "Define OnChange" affiche seulement un message. La ligne réelle de code est désactivée.

    Il y a aussi d'autres boutons permettant d'ajouter des racines et deux enfants à la première racine.
    Tout ceci marche bien, à l'aide de la classe TTntTreeNode, mais PAS avec la classe TTreeNode !

    Donc, mon problème avec le OnChange reste...
    Fichiers attachés Fichiers attachés

  5. #5
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 999
    Par défaut
    Citation Envoyé par KlausGunther Voir le message
    Merci d'avoir regardé, ShaiLeTrool, surtout un dimanche soir !
    En simultanée d'un jeu en ligne avec un pote

    Citation Envoyé par KlausGunther Voir le message
    Donc, logiquement, dans la procédure TVChange, le paramètre Node devrait etre TTntTreeNode et non TTreeNode.
    Si je le faisais comme indiqué, en recastong Node après coup, cela conduit à un crash. ancore une fois logique.

    En lisant le code sur github on constate que le OnChange est hérité du TCustomTreeView donc un TTVChangedEvent

    le TTntTreeView ne redefini pas le OnChange, on peut même se demander si il est correctement supporté.

    N'ayant ni D6 ni le temps à installer Tnt, pour ma part, je ne vois pas comment comprendre le problème.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    361
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 361
    Billets dans le blog
    1
    Par défaut
    Merci !

    En lisant le code sur github on constate que le OnChange est hérité du TCustomTreeView donc un TTVChangedEvent

    le TTntTreeView ne redefini pas le OnChange, on peut même se demander si il est correctement supporté.
    Cela confirme mon intuition - l'adaptation de TTntTreeView n'est oas "finie".

    Mais, cela étant dit, est-ce que quelqu'un d'autre parmi vous aurait utilisé les contrôles Tnt et aurait une expérience avec ces sources ?
    Je vais continuer à tester d'aures composants de cet ensemble Tnt, mais maintennt, je crains fort de tomber sur d'autres couacs de ce genre.

    En-dehors des contrôles Tnt, est-ce qu'il y a d'autres sources permettant Unicode avec D6 PE ? Personnelement, même après de multiples recheches, je n'ai rien trouvé.

  7. #7
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 999
    Par défaut
    Je testerais le même bricolage du ParentWindow avec un TTreeView classique

    Tout ce contrôle est géré par des Messages Windows et Delphi facilite certains éléments particulièrement retord, comme tu joues avec le ParentWindow vs la parentalité classique VCL, est-ce que cela a un impact ?

    Citation Envoyé par KlausGunther Voir le message

    Le bouton "Define OnChange" affiche seulement un message. La ligne réelle de code est désactivée.

    Donc, mon problème avec le OnChange reste...
    J'ai regardé le zip, j'ai lu le code, et c'est toujours en TTntTreeNode, au final, c'est quoi le problème, la compilation ou le runtime ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  8. #8
    Membre expérimenté
    Homme Profil pro
    ‫‬
    Inscrit en
    Septembre 2024
    Messages
    146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : ‫‬

    Informations forums :
    Inscription : Septembre 2024
    Messages : 146
    Par défaut
    La redéfinition en TTreeNode fonctionne cette classe est déclarée dans l'unité ComCtrls, il faut l'ajouter.
    En plus il y a une autre erreur dans le code fourni, c'est TVChange qui est affecté OnClick
    TV.MyTreeView.OnClick := TUnicodeObject.TVChange;

    Bien que cela fonctionne mais cette approche est fausse car une méthode de classe n'est pas compatible à une méthode d'objet le self n'est pas le même...la vraie question quel l’intérêt de la classe TUnicodeObject.

    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
     
    unit Test_TntTreeView_Main;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, ExtCtrls,
      Dialogs, StdCtrls,
      ComCtrls,
     
      ActiveIMM_TLB, TntActnList, TntAxCtrls, TntButtons, TntCheckLst, TntClasses, TntClipBrd, TntComCtrls,
      TntControls, TntDialogs, TntExtActns, TntExtCtrls, TntExtDlgs, TntFileCtrl, TntFormatStrUtils, TntForms,
      TntGraphics, TntGrids, TntListActns, TntMenus, TntRegistry, TntStdActns, TntStdCtrls, TntSystem,
      TntSysUtils,  TntWideStrings, TntWideStrUtils, TntWindows;
     
      type TUnicodeObject = class
        procedure Click(Sender: TObject);
        procedure TVChange(Sender: TObject; Node: TTreeNode);
      end;
     
      type TMyTntTreeView = class(TPanel)
          private
          MyTreeView: TTntTreeView;
        protected
         procedure Createhandle; override;
        published
          Constructor Create(AOwner: TComponent);
        end;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        Button2: TButton;
        Button3: TButton;
        Button4: TButton;
        Button5: TButton;
        Button6: TButton;
        TreeView1: TTreeView;
        procedure Button1Click(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
        procedure Button4Click(Sender: TObject);
        procedure Button5Click(Sender: TObject);
        procedure Button6Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
      TV: TMyTntTreeView;
      TN: TTntTreeNode;
      UnicodeObject: TUnicodeObject;
    implementation
     
    {$R *.dfm}
     
    procedure TUnicodeObject.Click(Sender: TObject);
    begin
      Form1.Memo1.Lines.Add('Click');
    end;
     
    procedure TUnicodeObject.TVChange(Sender: TObject; Node: TTreeNode);
    begin
      Form1.Memo1.Lines.Add('Change');
    end;
     
    Constructor TMyTntTreeView.Create(AOwner: TComponent);
    begin
      inherited;
      MyTreeView := TTntTreeView.Create(AOwner);
      Width := MyTreeView.Width;
      Height := MyTreeView.Height;
      MyTreeView.Align := alClient;
    end;
     
    procedure TMyTntTreeView.Createhandle;
    begin
      inherited;
      MyTreeView.Parent  := self;
      MyTreeView.Indent := 4;
      MyTreeView.ShowRoot := true;
      MyTreeView.ShowLines := true;
      MyTreeView.ShowButtons := true;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      if assigned(TV) then begin
        showmessage('Objet déjà créé');
        exit;
      end;
      TV := TMyTntTreeView.Create(Form1);
      Tv.Parent := self;
    end;
     
    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      TV.Free;
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      if assigned(TV) then
          TV.MyTreeView.OnClick := UnicodeObject.Click;
    end;
     
    procedure TForm1.Button3Click(Sender: TObject);
    begin
    //  showmessage('Inactif car erreur en compilation.'+#13#10+'Activer la ligne dans le code pour voir le problème...');
      if assigned(TV) then
           TV.MyTreeView.OnChange := UnicodeObject.TVChange;
    end;
     
    procedure TForm1.Button4Click(Sender: TObject);
    begin
      if assigned(TV) then begin
        TV.MyTreeView.Items.Add(nil,'First root');
        TV.MyTreeView.Items.Add(nil,'Second root');
      end;
    end;
     
    procedure TForm1.Button5Click(Sender: TObject);
    var
      i, n: integer;
    begin
      if assigned(TV) then begin
        TN := nil;
        n := TV.MyTreeView.Items.Count;
        if n=0 then exit;
        for i:=0 to n-1 do begin
          if TV.MyTreeView.Items[i].Text='First root' then begin
            TN := TV.MyTreeView.Items[i];
            exit;
          end;
        end;
        showmessage('non trouvé');
      end;
    end;
     
    procedure TForm1.Button6Click(Sender: TObject);
    begin
      if assigned(TV) then begin
        if not assigned(TN) then showmessage('Aucun noeud "parent" n''est sélectionné');
        TV.MyTreeView.Items.AddChild(TN,'Child 1');
        TV.MyTreeView.Items.AddChild(TN,'Child 2');
      end;
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
       UnicodeObject := TUnicodeObject.Create;
    end;
     
    end.

  9. #9
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    361
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 361
    Billets dans le blog
    1
    Par défaut
    Merci d'avoir regardé, rMist2024.

    En plus il y a une autre erreur dans le code fourni, c'est TVChange qui est affecté OnClick
    TV.MyTreeView.OnClick := TUnicodeObject.TVChange;
    Oui, je l'avais remarqué après, et je l'ai corrigé.

    J'ai remplacé TTntTreeNode par TTTreeNode pour l'évènement OnChange.

    Résultat: il n'y a plus d'erreur de compilation, et aucun crash à l'exécution.

    MAIS:
    L'évènement OnChange ne se déclenche pas lorsqu'il y a un changement !


    En fait, l'évènement OnClick déclenche en même temps un évènement ON_Change, dès l'ajout de neuds enfant.
    Et ceci pour chaque clic, même s'il n'y a pas d'autre changements entretemps.

    Pour mettre cela en évidence, procéder come suit:
    1. bouton "Create TreeView"
    2. bouton "Define OnClick"
    3. bouton "Define OnChange"
    jusqu'ici, rien ne s'est passé dans le TTntTreeView, et aucun évènemnt ne s'est déclenché.
    4. cliquer dans le TTntTreeView ==> OnClick se déclenche
    5. bouton "Add 2 roots" ==> les deux nouvelles racines apparfaissent dans le TTntTreeView, mais le OnChange ne se déclenche pas !
    6. cliquer dans le TTntTreeView ==> OnChange se déclenche, puis OnClick se déclenche
    7. ciquer dans le TTntTreeView ==> OnClick se déclenche
    8. bouton "Find first root"
    9. bouton "Add 2 chldren" ==> rien ne se déclenche
    10. cliquer dans le TTntTreeView ==> OnChange se déclenche, puis OnClick se déclenche
    11. à partir de mainitenant, tout nouveau clic dans le TTntTreeView produit le résultat en (10).

    En pièce jointe, il y a un ZIP avec la version décrite ci-dessus.Ceci est certainement dû au conflit d'interface pour l'évènement OnChange. A l'évidence, utiliser un TTreeNode comme second paramètre ne peut pas produire de bons résultats, même si le compilateur n'a rien à y redire.

    Je persists à penser que l'implémentation de TTntTreeView est "partielle" et impropre à l'utilisation en l'état. Quelles autres incompatibilités vais-je découvrir en utilisant plus de propriétés et méthodes de cet objet ? Ce n'est pas rassurant.

    Par rapport à ta remarque:
    Bien que cela fonctionne mais cette approche est fausse car une méthode de classe n'est pas compatible à une méthode d'objet le self n'est pas le même...la vraie question quel l’intérêt de la classe TUnicodeObject.
    je fais les réponses suivantes:

    1. J'ai vérifié la valeur de self dans Constructor TMyTntTreeView.Create(AOwner: TComponent);.
    Elle est exactement la même que la valeur de l'objet TTntTreeView après sa création (variable TV).
    Et donc, le self dans constructor remplit exactement son rôle pour affecter le composant TTntTreeView au TMyTntTreeview qui est un TPanel dérivé et qui doit servir de parent au TTntTreeView, car sinon, le OnChange ne se déclenchera jamais (alors que pour le OnClick, ce ne serait pas nécessaire, voir les explications de ShaiLeTroll).

    2. J'utilise la classe TUnicodeObject uniquement pour créer des procédures capables d'être affectées aux évènements de mon TTntTreeView.
    J'utilise cette technique depuis pas mal d'années, pour plein d'autres objets VCL, et sans jamais avoir rencontré de problèmes.
    Le compilateur ne dit rien, et à l'exécution, tout fonctionne et je n'ai jamais d'erreur ou de plantage sur ce point précis.
    D'ailleurs, cette technique m'a été suggérée, il y a des années, par un des membres de ce forum (et je l'en remercie encore !).
    Fichiers attachés Fichiers attachés

  10. #10
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 999
    Par défaut
    Citation Envoyé par rMist2024 Voir le message

    Bien que cela fonctionne mais cette approche est fausse car une méthode de classe n'est pas compatible à une méthode d'objet le self n'est pas le même...la vraie question quel l’intérêt de la classe TUnicodeObject.
    En réalité, cela fonctionne très bien, le Self c'est la classe TUnicodeObject au lieu d'être une instance d'un autre objet et dans un gestionnaire d'évènement, il est rare que l'on est vraiment besoin du self mais plutôt du Sender.
    un gestionnaire d'évènement peut très bien être supporté par une méthode de classe.

    Il faut cependant vraiment maitrisé ce que l'on fait dans une telle situation et n'utiliser QUE et uniquement que le Sender (et les autres paramètres)

    Il semble évident que la classe TUnicodeObject est une sorte de mini-Controller au sens MVC

    Cependant, je l'aurais déclaré ainsi TControlerOfTntTreeView = class(TObjet) car il n'y a aucun raison que cela soit un TWinControl
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  11. #11
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 999
    Par défaut
    La création d'un neoud ne devrait pas produire OnChange !

    Vous devriez d'abord totalement maitriser le TTreeView puis ensuite comparer avec le TTntTreeView

    Le comportement est normal.
    Le OnChange se produit que si il y a un noeud sélectionné différent du précédent
    Se produit à chaque fois que la sélection est passée d'un noeud à un autre.
    Créer un noeud ne modifie pas Selected donc ne provoque pas de OnChange

    Etudiez le OnChanging, cela devrait vous montrer plus de chose, vous verrez que Node est différent de la propriété Selected


    6. cliquer dans le TTntTreeView ==> OnChange se déclenche, puis OnClick se déclenche
    OnChanging Selected nil et Node avec le Node cliqué


    7. ciquer dans le TTntTreeView ==> OnClick se déclenche
    Tant que l'on change pas de noeud


    10. cliquer dans le TTntTreeView ==> OnChange se déclenche, puis OnClick se déclenche
    OnChanging Selected Node précédemment selectionné et Node avec le Node cliqué
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  12. #12
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    361
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 361
    Billets dans le blog
    1
    Par défaut
    Bon, d'accord. J'ai compris que ce que je prenais pour un comportement anormal était en fait une malcompréhension de ma part.
    Comme souvent, le problème se situe entre le siège et le clavier.

    Ceci dir, le problème du TTreeNode bersus TTntTreeNode dans l'évènement OnChange persiste.
    J'ai parcouru un peu le source - partout il est question de TTntTreeNode dérivé de TTreeNode mais avec FText déclarée en WideString.
    D'ailleurs, dans les commentaires en introduction des modules source il est écrit, aprmi d'autres remarques:
    { TODO: TTntCustomTreeView events - reintroduce ones that refer to ansi classes (ie. TTreeNode) }
    Ceci semble indiquer que la conversion en Unicide n'est pas allée à son terme.

    Pour le moment, je vais laisser tomber le TTntTreeView et chercher d'aures solutions, tout en explorant d'autres contrôles du groupe TNT.
    Actuellement, les contrôles TNT sont passés sous l'égide de TMS Software et ne sont plus gratiuts. La version actuelle ne s'applique pas non plus à D6.

    J'ai regardé le VirtualTreeView. Très intéressant, mais uniquement à partir de D7. Dommage.

    Donc, clap de fin pour le TTntTreeView.

  13. #13
    Membre expérimenté
    Homme Profil pro
    ‫‬
    Inscrit en
    Septembre 2024
    Messages
    146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : ‫‬

    Informations forums :
    Inscription : Septembre 2024
    Messages : 146
    Par défaut
    Le seul vrai événement widestring pour TTreeView est OnEdited et il est implémenté dans TTntTreeView
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     TTntTVEditedEvent = procedure(Sender: TObject; Node: TTntTreeNode; var S: WideString) of object;
    Il fonctionne parfaitement après l'edition du texte du node
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
       type TUnicodeObject = class
        procedure Click(Sender: TObject);
        procedure TVChange(Sender: TObject; Node: TTreeNode);
        procedure TVEdited(Sender: TObject; Node: TTntTreeNode; var S: Widestring);
      end;
    D'ailleurs, dans les commentaires en introduction des modules source il est écrit, aprmi d'autres remarques:
    Ca n'a pas grande importance, le but de la réintroduction est pour redéclarer les événements avec TTntTreeNode pour pouvoir accéder à la propriété Text version widestring déclaré dans TTntTreeNode une chose qu'on peut faire par un simple cast du node à l’intérieure du gestionnaire de l'évenement, ex pour récupérer le texte du node qui a été sélectionné dans l'event OnChange : ( attention le memo doit être un TntMemo pour afficher le texte Unicode)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     procedure TUnicodeObject.TVChange(Sender: TObject; Node: TTreeNode);
    begin
      Form1.Memo1.Lines.Add('Change ' + TTntTreeNode(Node).Text);
    end;
    A la base TTreeView permet la création des nodes personnalisés avec davantage de champs via OnCreateNodeClass et faire un cast a l’intérieure des événements est tout a fait normal

  14. #14
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    361
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 361
    Billets dans le blog
    1
    Par défaut
    Bon, je vais m'y remettre, alors... Un grand MERBI pour ces explications...

    Je ne comprends absolument pas comment un TTreeNode avec la propriété Text: String peut être le même u'un TTntTreeNode avecla propriété Text: WideString, mais je vais faire comme si je comprenais et le prendre tel quel.

  15. #15
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 999
    Par défaut
    En fait TTntTreeNode hérite de TTreeNode donc le premier "contient" le second et l'enrichi

    Faut juste penser en pointeur, tu reçois une référence TTreeNode mais elle a été créé comme un TTntTreeNode, le Cast fait le boulot pour utiliser les propriétés adéquates.

    Si l'on résume le code, on voit l'introduction du Text dans TTntTreeNode qui masque la propriété héritée de TTreeNode, c'est la base POO en Delphi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      TTntTreeNode = class(TTreeNode)
      private
        FText: WideString;
        procedure SetText(const Value: WideString);
        procedure SetInheritedText(const Value: AnsiString);
        function GetText: WideString;
    ...
      public
    ...
        property Text: WideString read GetText write SetText;
        property TreeView: TTntCustomTreeView read GetTreeView;
      end;
    Au final, l'astuce c'est que le TTreeView est un contrôle Windows, il est à la fois Ansi et Unicode
    TTreeNode utilise SetWindowTextA
    TTntTreeNode utilise SetWindowTextW

    Et évidemment c'est uniquement à partir de Win 2000 (peut-être aussi NT4), alors que Win9x lui était Ansi uniquement (CodePage obligatoire), faut penser que Delphi est sorti en 16Bits pour Win 3.1, l'héritage Pascal + VCL Windows a été long à migrer
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  16. #16
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    361
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 361
    Billets dans le blog
    1
    Par défaut
    Merci beaucoup. Je comprends mieux. Je vais poursuivre alors avec ce contrôle.

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 30/10/2020, 12h36
  2. Documentation gratuite sur l'API Windows, COM, DCOM, OLE, etc.
    Par Community Management dans le forum Windows
    Réponses: 1
    Dernier message: 16/11/2006, 15h28
  3. [Kylix] Kylix embarqué sur PDA ?
    Par Anonymous dans le forum NoSQL
    Réponses: 10
    Dernier message: 29/11/2002, 13h59
  4. Réponses: 4
    Dernier message: 27/03/2002, 11h03
  5. F.A.Q, Doc, cours, tutoriels sur JBuilder
    Par Ricky81 dans le forum JBuilder
    Réponses: 0
    Dernier message: 14/03/2002, 15h28

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