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

Composants VCL Delphi Discussion :

TTreeView - pas d'affichage de libellés des noeuds en création dynamique


Sujet :

Composants VCL Delphi

  1. #1
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    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 : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut TTreeView - pas d'affichage de libellés des noeuds en création dynamique
    Dans une DLL écrite en Delphi 6 Personal Edition, je crée un objet TTreeView que j'injecte dans une form du programme appelant (écrit dans un autre langage). Cela marche bien. Ma fonction de création retourne l'objet TTreeVeiw créé au programme appelant. Et ce programme passe cette information aux autres fonctions de manipulation de mon objet. Ainsi, j'ai une fonction de création d'un noeud racine. Je lui passe l'objet TTreeView, ainsi que le libellé. Par la méthode Items.Add, le neud se crée bien, mais le libellé n'est pas affiché.

    Alors, j'ai remplacé mon code par celui de l'aide Delphi. La structure arborescente de cette démo se crée bien, on peut déplier et replier les branches, mais aucun libellé ne s'affiche.

    J'ai fait un extrait de ma DLL, avec les fonctions concernées. Et un programme écrit en Delphi 6 Personal Edition pour mettre le problème en évidence.

    En pièce jointe, j'ai mis un fichier ZIP qui contient les sources et les binaires pour TV.dll et TestTV.dll.

    Merci de votre aide !
    Fichiers attachés Fichiers attachés
    • Type de fichier : zip TV.zip (392,9 Ko, 65 affichages)

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 447
    Points : 24 849
    Points
    24 849
    Par défaut
    il serait bon d'utiliser des PChar à la place de PString !
    Idem, utilise HWND au lieu de Integer !
    Les types Windows sont tout à fait utilisable entre DLL et EXE

    J'avais aider à l'encapsulation un TTreeView dans un ActiveX pour Navision,
    cela fonctionnait très bien car le TTreeView était placé dans une TForm (en bsNone)
    C'est la TForm créé via CreateParented qui était placé dans le Navision via un échange de Handle aussi

    l'utilisation de CreateParented est similaire au ParentWindow !
    Tente de mettre ton TTreeView dans une TForm interne
    Et c'est la TForm BorderyStyle bsNone que tu affiche dans l'EXE appelant toujours en utilisant des Pointer
    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 habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    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 : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Merci, ShaiLeTroll.

    Quelques remarques:
    1. Certes, HWND au lieu de INTEGER est plus lisible. Cependant, cela ne change rien à l'affaire - le comportement est identique. J'ai essayé.
    2. La DLL est appelé par un programme externe écrit dans un autre lengage, et ce langage passe un PSTRING, c'est-à-dire l'adresse d'un STRING, en paramètre. J'ai essayé avec PCHAR, mais ça ne marche pas. Si je déclare mon paramètre formel dans la fonction DLL comme PSTRING, je fais simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function test(ps: pstring):integer; stdcall; export;
    var
      s: string;
    begin
      s := ps^;
    ...
    end
    et j'ai le contenu de mon string en entrée.
    3. J'ai modifié mon programme de démo en copiant le code des fonctions de la DLL dans le programme principal TestTV, tout en ajoutant "Locally" à la fin de chaque nom de fonction. Puis, j'ai doublé les 3 boutons pour utiliser ces fonctions localement, sans recours à la DLL. Et là, ça marche ! Mes libellés s'affichent.

    Je ne comprends absolument pas pourquoi l'affichage des libellés ne se fait pas si le TreeView est injecté par la DLL, alors que la structure avec les traits et les "+" et "-" s'affichent dans les deux cas.
    Fichiers attachés Fichiers attachés
    • Type de fichier : zip TV2.zip (412,0 Ko, 67 affichages)

  4. #4
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 681
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 681
    Points : 13 089
    Points
    13 089
    Par défaut
    PSTRING est un pointeur sur une UnicodeString (type propre à Delphi). Ce n'est surement pas ce que ton programme externe utilise. Il s'agira soit de PWIDESTRING ou de PANSISTRING.

  5. #5
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    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 : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Je ne suis pas maître du code du programme externe. Tout ce que je sais, c'est que je reçois un entier non signé contenant l'adresse du début d'un string Delphi. A cette adresse, je trouve le premier caractère de la chaîne qui est terminée par un octet <0>, et les deux mots précédant cette adresse contiennent la longueur de la chaîne en octets et le compteur d'utilisation.

    C'est pour cette raison que la petite construction indiquée dans mon post précédent fonctionne parfaitement, dans tous les cas. Et ma DLL contient actuellement pas loin de 300 fonctions, dont une très large part utilise ce mécanisme pour récupérer des paramètres chaîne de caractères passés par le programme appelant.

    Mais ma demande ne concernait pas du tout cet aspect de la chose, qui pour moi est parfaitement fonctionnel. Je n'arrive pas à comprendre pourquoi les libellés des éléments d'un TreeView créé dynamiquement ne s'affichent pas si ce TreeView est créé dans ma DLL, alors que ça marche bien si la création a lieu dans un programme Delphi direct, sans passer par une DLL. J'ai joint à mon dernier post les sources et les binaires de la DLL ainsi que d'un programme de test, qui permet de voir le fonctionnement (voir non-fonctionnement). Et pour m'affranchir de tout problème de passage de chaîne de caractères, je ne passe rien, en fait, car j'utilise la création directe, dans la fonction Delphi, des éléments du TreeView en utilisant une copie du code issu de l'aide de Delphi pour l'objet TreeView.

    Essayez de décompresser le petit fichier ZIP, et faites marcher TestTV.exe. Cliquez d'abord sur les deux boutons "Créer...", et les deux TreeView vides vont apparaître. Puis cliquer sur les deux boutons "Montrer..." et vous constaterez qu'il y a une différence, alors qu'il ne devrait pas y en avoir - le code est identique, sauf qu'à gauche, il est exécuté à partir de la DLL, et à droite, par une copie des mêmes fonctions dans l'unité principale du programme, sans passer par la DLL.

    Voici une copie d'écran:
    Nom : aa1_TestTV.jpg
Affichages : 141
Taille : 43,3 Ko

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 447
    Points : 24 849
    Points
    24 849
    Par défaut
    Citation Envoyé par KlausGunther Voir le message
    Mais ma demande ne concernait pas du tout cet aspect de la chose, qui pour moi est parfaitement fonctionnel. Je n'arrive pas à comprendre pourquoi les libellés des éléments d'un TreeView créé dynamiquement ne s'affichent pas si ce TreeView est créé dans ma DLL,
    C'est probablement lié au message WM_PAINT qui ne passe pas bien !
    Pense que l'exe et la DLL ne partage pas la mémoire, chacun vit un peu sa vie et il faut être propre dans sa gestion !

    Il est possible qu'en compilant EXE et DLL avec les paquets d'execution,
    le TTreeView étant par conséquent dans le BPL, son comportement change aussi !

    Tu nous a décrit qu'il n'y avait pas de texte, cela m'a suffit, je t'ai confiance !

    Par exemple côté DLL, utiliser une TForm en interne, c'est la Form qui est échangé comme Integer et non le TreeView,
    cela change radicalement le comportement du dessin des composants (ainsi que les effets de bord sur la gestion de focus)

    Ayant fait exactement la même chose, il y a presque 10 ans d'exporter un TTreeView pour l'intégrer dans Navision,
    je dis te dis ce que j'ai fait parce c'est le truc qui a fonctionné, le coup du TForm !

    Essaye la TForm et reviens si cela ne change rien !
    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

  7. #7
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    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 : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Tu veux dire, qu'il faut créer un TForm dans lequel on place le TTreeView, et on injecte ensuite le TForm dans la form dont le programme externe passe le handle, au lieu d'y injecter directement le TTreeView ? Je vais essayer ça, et je posterai le résultat.

    Je suis perplexe, tout de même. Car je fais exactement la même chose avec des TMaskEdit, TValueEditor, TDateTimePicker, TRichEdit, TWebBrowser, et j'en passe, et je n'ai jamais rencontré ce problème. Mais je vais faire ce que tu suggères.

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 447
    Points : 24 849
    Points
    24 849
    Par défaut
    TRichEdit, lui aussi il est géré bizarrement avec des versions dans des DLL séparés ...
    TWebBrowser c'est un ActiveX, c'est un cas particulier ... et je me demande quel est l'utilité de l'utiliser via Delphi vu que c'est juste un TLB !

    D'ailleurs, étrange, ton langage il ne peut utilise les classes Windows directement ?
    C'est plus simple non ?
    Ton application fourni la donnée via COM, DCOM, DataSnap, WebService ... et l'appelant se charge de l'afficher avec ses propres composants visuels !


    Faudrait essayer avec le TListView, c'est le composant le plus proche du TTreeView !
    Est-ce que la gestion des thèmes à un impact ?

    A cette adresse, je trouve le premier caractère de la chaîne qui est terminée par un octet <0>, et les deux mots précédant cette adresse contiennent la longueur de la chaîne en octets et le compteur d'utilisation.
    L'appelant est en Delphi !
    Il n'y a pas beaucoup de langage qui doivent gérer la longueur en pointeur -4 et la compteur de référence en pointeur -8
    En XE2, on rajoute le codepage en -12 et la taille de char en -10
    Formats de données internes (Delphi) : Types chaînes étendues

    J'ai essayé avec PCHAR, mais ça ne marche pas
    Normal !
    un String c'est assimilable à un PChar encapsulé (grossier mais si faux )
    un PString c'est donc un PPChar (^PChar);

    tente par curiosité cette variante avec le mot const string au lieu de PString
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function test(const ps: string):integer; stdcall; export;
    var
      s: string;
    begin
      s := ps;
    ...
    end

    Ah Delphi 6 ! DOF, CFG, icone vert, ... ça faisait longtemps !
    Je n'ai connu que la version Entreprise !
    En Personnel, ni DB, ni XML, ni SOAP ... je ne pourrais pas bosser !

    Et dire qu'il existe Delphi XE6 (20)
    Est qu'un jour Embarcadero comprendra qu'une version gratuite est indispensable pour les nouvelles versions soit "aimées" pour des raisons personnelles et donc "payées" pour des utilisations professionnelles !

    Citation Envoyé par KlausGunther Voir le message
    Je ne suis pas maître du code du programme externe.
    Faudrait pas qu'un jour, ce programme passe dans un Delphi récent, tu aurais des soucis !


    Car en Delphi XE2, le PString pointant sur un UnicodeString et non sur un AnsiString ...
    Comme un caractère simple, la lettre A cela commence par un zéro, ta chaine est vide !
    Je te laisse étudier l'Unicode

    Pour le PString, qu'un autre langage le gère correctement, cela m'étonne énormément
    sauf si c'est du C++Builder mais même là, je n'oserais échanger une classe String du C++Builder vers le type string natif de Delphi entre EXE et DLL,
    sauf évidement si cela utilise BPL et ShareMem\FastShareMem !
    perso entre Delphi et C++, je l'utilisais du WideString\BSTR pour être tranquille !

    Si tu es curieux sur le PAnsiChar : Chaine à Zéro Terminal
    Manipulation des chaînes terminées par null
    Qu'est-ce qu'une chaîne AZT ?
    Evidemment, il n'y a rien à lire devant le pointeur concernant la chaine dans un PChar, c'est même risque d'une violation d'accès !
    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

  9. #9
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    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 : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Ces informations sont intéressantes. Il est bien possible que mon programme externe soit écrit en Delphi, mais je n'en sais rien. Je ne connais que les contraintes d'interface pour l'appel des fonctions dans une DLL, et je fais avec, en essayant de développer une multitude d'extensions de toutes sortes. Les contraintes de base sont extrêmement réductrices, il n'y a aucune souplesse. Seule une fonction peut être appelée dans une DLL, pas une procédure. La fonction retourne systématiquement une valeur de type integer. La fonction DLL peut avoir entre 0 et 6 paramètres, pas un de plus. Et tous les paramètres sont passés par valeur, sous forme d'une valeur integer. Voilà, c'est tout. Donc, pour passer une chaîne de caractères, le seul moyen est de passer son adresse et de se repérer sur l'octet 0 terminal. J'ai trouvé le moyen de retourner une valeur chaîne de caractères dans ces conditions sans provoquer de violation d'accès de mémoire, mais là, je sors trop du contexte de mon problème actuel.

    Pour en revenir à mon problème technique: après une pause depuis mon dernier message, je reprends le travail et vais réaliser l'astuce de la form intermédiaire. Je communiquerai le résultat...

  10. #10
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    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 : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut [Résolu] TTreeView - pas d'affichage de libellés des noeuds en création dynamique
    YES!!!!!!!!!!!!!

    Le conseil d'entourer le TreeView par un TFORM sans bord a été la solution. Tout s'affiche bien maintenant. J'ai doublé mes fonctions dans la DLL en ajoutant "...Surrounded" aux noms des 3 fonctions, et j'ai géré la form enveloppante dans ces fonctions. J'ai ajouté un nouveau jeu de 3 boutons en bas à gauche de la fenêtre de test, utilisant ces nouvelles fonctions. Et, miracle: tout s'affiche correctement. Voici une capture d'écran:
    Nom : TestTV_final.jpg
Affichages : 169
Taille : 59,3 Ko
    Le fichier ZIP joint contient tout: le projet et les sources pour la DLL et pour le programme de test, ainsi que les binaires. Question: pourquoi ça marche ainsi et pas directement en injectant le TTreeView dans une form externe ? J'aime bien comprendre...

    En tout cas, mes sincères remerciements pour ta bonne volonté et ton aide précieuse, ShaiLeTroll.
    Fichiers attachés Fichiers attachés
    • Type de fichier : zip TV3.zip (414,3 Ko, 59 affichages)

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

Discussions similaires

  1. [AJAX] [Struts] Pas d'affichage des boutons lors du raffraîchissement
    Par AnneB dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 20/07/2007, 13h29
  2. Pas d'affichage des valeurs nulles avec un COUNT
    Par phoenixz22 dans le forum Langage SQL
    Réponses: 13
    Dernier message: 30/05/2007, 18h39
  3. [XSLT] compte et affichage des noeuds distincts
    Par xoubidur dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 31/01/2007, 12h08
  4. [Swing][ListCellRenderer]Pas d'affichage des composants
    Par Cyberwan dans le forum AWT/Swing
    Réponses: 9
    Dernier message: 08/02/2006, 00h22
  5. Couleur des noeuds ds 1 TTreeView
    Par vincent DD dans le forum Composants VCL
    Réponses: 3
    Dernier message: 18/09/2002, 13h54

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