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 :

TButton et ParentWindow depuis DLL


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Février 2005
    Messages
    317
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 317
    Par défaut TButton et ParentWindow depuis DLL
    Bonjour à tous, j'éssaie de créér un bouton sur ma form depuis une DLL. Pour cela, je passes une structure contenant le control parent(un TPanel). J'initialise comme ceci:

    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
     
      procedure initModule(infos: CModuleInitInfos);  stdcall;
      begin
     
            minfos:=infos;
            dragcomp:=TDragComponentContainer.create(minfos.parent);
            dragcomp.ParentFont:=false;
            dragcomp.ParentWindow := minfos.parent.handle;
            dragcomp.Left:=5;
            dragcomp.top:=5;
            dragcomp.Width:=infos.parent.Width-10;
            dragcomp.Height:=infos.parent.Height-50;
            dragcomp.visible:=true;
            dragcomp.anchors:=[akLeft, akTop, akRight, akBottom];
            loadButtons();
     
            btnMkRes:=TButton.create(minfos.parent);
            btnMkRes.ParentFont:=false;
            //btnMkRes.ParentWindow:=minfos.parent.handle;
            btnmkres.Parent:=minfos.parent;
            btnMkRes.Top:= dragcomp.Height + 10;
            btnMkRes.Height:=25;
            btnMkRes.Width:=100;
            btnMkRes.left := 5;
            btnMkRes.Visible:=true;
            btnMkRes.caption:='Creer le tableau'; { }
     
      end;
    La ligne btnMkRes.ParentWindow:=minfos.parent.handle; pose problème, et si je ne la mets pas le bouton s'affiche pas. Si je la mets, il s'affiche mais je n'ai que des erreurs mémoire, quand je le cré, le survole...
    Quelqu'un aurait une idée du pourquoi?

    Merci d'avance !

  2. #2
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut
    la transmission d'objet de DLL vers exe est impossible.
    Soit on passe par des interfaces quasi impossible pour une gestion GUI, soit on se debrouille avec des types de bases.

    A ulie de transmettre l'opbjet, transmet le handle seulement.
    Si tu as besoin de plus de proprietees du parent a transmettre, creer un record contenant des Integer, PChar, etc ... contenant ces infos.

    Une solution sur laquelle je planche quand j'ai le temps consiste a creer un VCLManager, une classe qui peut creer le plus grand nombre possible d'objet de type TControl que l'on peu manipuler via des methdoes d'une interface.
    La dll se contente de creer et parametrer directement dans l'exe des objets VCL

    Par contre, le type des objets est predefini a la compilation de l'exe ... et marche dans des cas d'utilisation restreint mais permet de creer des interfaces VCL depuis des DLLs.

    Quoi qu'il en soit, ca pourra peut etre de donner des idees.

  3. #3
    Membre éclairé

    Profil pro
    Inscrit en
    Février 2005
    Messages
    317
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 317
    Par défaut
    Pourtant mon objet TDragComponent s'affiche sans problème, et avec une autre DLL j'ai même pu afficher une form sans bordures avec tous les boutons qu'il y avait dedans... Sinon je vais créer une form et mettre mon bouton mais bon...

  4. #4
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut
    Oui .... mais utiliser les pointeurs d'objets aux travers de Dlls c'est jamais bon

    Sinon je dit souvent : C'est pas parce que ca marche une fois que ca marche toutes les fois

    En fait, Les objets c'ets comme les parametres de fonctions. Delphi, C++, et autres langages n'implemente pas de la meme maniere les objets en memoire.

    Du coup quand tu declare un objet dans l'exe et que tu le transmet a une Dll via son pointeur, tu travailles dans la Dll selon la structure du langage de la Dll alors qu'il a ete cree en memoire selon la structure de l'exe.
    Et comme pour les paramettres de fonction .... on s'expose a de serieux problemes

    Pour les fonctions on a les directives StdCall, cDecl, safecall, etc ... pour synchroniser les gestions. Du cote objet, ca s'appelle les interfaces
    Ca permet de gerer les objets vie une structure memoire commune a tous les langages.

    Si ce que tu as ecrit fonctionne c'est que tu utilises les memes structures declaratives entre l'exe et la Dll mais ca n'est pas propre et tu t'exposes a des soucis ulterieure
    Sans compter que la Dll ne sera exploitable que sous Delphi, ce qui n'est pas franchement le principe des Dlls

  5. #5
    Membre éclairé

    Profil pro
    Inscrit en
    Février 2005
    Messages
    317
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 317
    Par défaut
    Mais je vois pas en quoi un TBUtton déclaré dans la DLL pourrait différé d'un TButton dans l'exe ?

  6. #6
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut
    Simple structure memoire.

    Par exemple (tres simpliste) :
    Si depuis @ l'adresse memoire de depart de l'objet, delphi code sur des 4x4 octets les valeurs successives Top/Left/Width/Height et ensuite la methode MEth1 puis Meth2 et que C++ code Width/Height/Left/Top/Meth2/Meth1 ... l'exe ne trouveras pas a l'emplacement desiré les données desirée ....

    Il faut donc que les 2 structures de la Dll/Exe soient rigoureusement identique. Or ca n'est pas le but des Dlls .... dont le principe est de pouvoir croiser les languages de developpement.

    De Delphi a Delphi ca marche (plus ou moins) mais ce n'ets pas pour autant conseillé, a pour des raisons que je ne pourrais detaillé, faute de connaissances suffisantes la dessus.

    Pour faire simple (une fois de plus) les String par exemple sont gere d'une telle maniere que transmettre une string d'un exe vers une Dll n'est pas faisable sans gestionnaire de mamoire partagé. Certaines données ne sont pas forcement stockées dans le meme gestionaire memoire.
    Pourtant la je parle d'application Delphi dialoguant avec une Dll Delphi.

    En bref, si cela etait possible, Borland n'aurais pas implementé le systeme de PAckage
    Ce ne sotn que des Dlls amélioré pour palier au problemes que pose les Dlls.
    Dans le cas des paquets c'est tout a fait possible d'impôrter tout type de classes vers un exe.
    Par contre, meme si j'ai ecris un tuto dessus, j'en sui revenu face aux contrainte que pose une gestion par package.
    A voir ....

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

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    Citation Envoyé par nek_kro_kvlt
    Mais je vois pas en quoi un TBUtton déclaré dans la DLL pourrait différé d'un TButton dans l'exe ?
    c'est simple, TButton dans l'exe utlise le code et le gestionnaire mémoire de l'exe, TButton dans la DLL utilise le code et le gestionnaire de mémoire de la DLL

    même si l'exe et la DLL sont compilés avec la même version de Delphi, ils ne partagent pas leurs infos respectivent. Il y a par exemple une instance de l'objet Application dans l'exe et une autre instance dans la DLL.

    La solution proposée par Borland est de faire des Packages, le Package et une DLL particulière qui a pour fonction de rendre communes un certain nombre d'unité.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    package MonPaquet;
    requires
     Paquet1,Paquet2;
    contains
     Unit1, Unit2;
    end.
    ici les unités Unit1 et Unit2 sont placées dans le paquet MonPaquet qui a lui même besoin des paquets Paquet1 et Paquet2.
    Avec cette déclaration, tout projet compilé par paquet qui a besoin de Unit1 ou Unit2 utilisera le paquet MonPaquet (et donc Paquet1 et Paquet2) au lieu d'intégrer sa propre version du code !.

    NB: une unité ne peut être déclaré que dans un seul paquet ! Soit elle est dans un des paquet requis, soit elle est dans une des unités "contenues". Elle ne peut pas être dans la partie "contains" de plusieurs paquets.

    On comprend alors que les paquets VCL sont responsables de tout ce qui concerne la gestion des composants...et ce de façon partagée !
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  8. #8
    Membre éclairé

    Profil pro
    Inscrit en
    Février 2005
    Messages
    317
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 317
    Par défaut
    Vu qu'il s'agit d'un problème de partage de mémoire, l'ajout de l'unité sharemem a réglé le problème (pour l'instant)...
    Merci de vos réponses !

  9. #9
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut
    Citation Envoyé par nek_kro_kvlt
    Vu qu'il s'agit d'un problème de partage de mémoire, l'ajout de l'unité sharemem a réglé le problème (pour l'instant)...
    Merci de vos réponses !
    Par experiance, je ne suis pas fana des solution qui marche pour le moment.
    Surtout quand il s'agit de chose aussi importante que ca.
    Si les besoins changent, migrer ton application vers un systeme de codage plus proche de ce qui se fait dans de tels cas (Interface) te demanderas de tres gros changements ..... voir peut etre une refonte de l'application.

    Si je peut te donner un modeste conseil, renseigne toi sur la gestion des objets via Interfaces, sur les packages, etc ... afin d'opter au plus tot pour la meilleur solution.

    Sur ce : Bonne prog !

  10. #10
    Membre éclairé

    Profil pro
    Inscrit en
    Février 2005
    Messages
    317
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 317
    Par défaut
    le problème c'est que j'aimerai que ça marche le plus tot possible, et ensuite si je constate des problème j'utiliserai les packages, mais à priori tous mes modules sont chargés et déchargés par une seule classe, la transition ne devrais pas être très difficile mais je ne connais rien aux packages pour l'instant... Bref, merci de tes conseils!

  11. #11
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut
    Si tu veux que ca soit rapide et efficace .... je te conseille les packages. C'ets simple et puissant.
    C'ets juste pas trop mon style de de ploiement de fichiers

    Rapidement pour bien demarrer :
    1 - Creer dans un projet test le ou les composants/Objets a exporter
    2 - Creer un nouveau paquet (menu fichier/Nouveau)
    3 - Ajouter les unitees contenant les classes du module
    4 - penser a faire appel aux fonctions : REgisterClass et UnregisterClass (section initialization/Finalisation ?)
    5 - Compiler.
    6 - Charger dynamiquement le package via la procedure LoadPackage (voir aussi unLoadPackage)
    7 - Charger et instancier une classe a l'aider de GetClass
    8 - Utiliser la classe cree en la castant avec le plus bas type connut de l'exe.
    9 - Compiler l'executable en specifiant dans les options de projet que l'on souhaite une compilation avec les paquets d'execution.
    10 - Fournir l'exe, les packages crees mais surtout : TOUS les packages requis par l'exe et/ou les paquets perso (VCL.bpl et RTL.bpl en tete)

    Apres ca si ya un peu de casse a l'execution, faut jsute bidouiller 2/3 options ... mais on verra ca en temps voulut.


    Pour le tuto : Cliquer ici

  12. #12
    Membre émérite
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Par défaut
    bonjour

    Voici un lien intéressant sur la représentation en mémoire des objets, classes et interfaces.
    http://rvelthuis.de/articles/articles-pointers.html

    Dans le livre "Delphi in a Nutshell", il y a le détail complet de la structure de la Vmt.

    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
    TVmt = record
      SelfPtr: TClass;
      IntfTable: PInterfaceTable;   
      AutoTable: PAutoTable;         
      InitTable:   PInitTable;
      TypeInfo:  PTypeInfo;
      FieldTable:  PFieldTable;         //Champs publiés
      MethodTable: PMethodTable;   //methodes publiées
      DynMethodTable: PDynMethodTable;
      ClassName: PShortString;
      InstanceSize: LongInt;
      ClassParent: ^TClass;
      // pointers vers les methodes virtuelles héritées de TObject
      SafeCallException: Pointer;
      AfterConstruction: Pointer;
      BeforeDestruction: Pointer;
      Dispatch: Pointer;
      DefaultHandler: Pointer;
      NewInstance: Pointer;
      FreeInstance: Pointer;
      Destroy:  Pointer;
    end;
     
    var Vmt: PVmt;
     
    //un pointer sur une classe d'objet est un pointeur sur la Vmt 
    Vmt := PVmt(UNObjet.ClassType);
    Dec(Vmt);

    @+

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

Discussions similaires

  1. appel class depuis dll
    Par bergoliv dans le forum Langage
    Réponses: 3
    Dernier message: 08/09/2010, 15h21
  2. Transmettre des donnees depuis dll
    Par devroot dans le forum C++
    Réponses: 2
    Dernier message: 07/03/2007, 12h58
  3. Comment accéder à une DLL COM depuis un exécutable ?
    Par Denys dans le forum API, COM et SDKs
    Réponses: 10
    Dernier message: 20/09/2005, 08h04
  4. Réponses: 5
    Dernier message: 08/09/2005, 20h33
  5. Comment charger un TFrame depuis une dll ?
    Par Millenod dans le forum Langage
    Réponses: 29
    Dernier message: 22/12/2004, 14h48

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