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 lancer msedge.exe avec une url, mais captif dans un TPanel ?


Sujet :

API, COM et SDKs Delphi

  1. #21
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    360
    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 : 360
    Billets dans le blog
    1
    Par défaut
    tu dois quand même bien avoir dans le menu principal Projet et au sein de ce menu (tout en bas) Options ?
    Oui, bein sûr !

    Ca, je l'ai trouvé. ET j'ai exploré ce menu dans tous les sens, mais je n'ai rien trouvé qui ressemble à ""common_DLL_folder_path\x86\WebView2Loader.dll".
    Par contre, dans ces options, jce qu'il resseemble le plus ce que tu mentionnes, c'est ceci:
    Nom : aa1.png
Affichages : 79
Taille : 23,9 Ko

    Et la DLL est bien dans le dossier suivant:
    C:\Users\klausgunther\Documents\Embarcadero\Studio\23.0\CatalogRepository\EdgeView2SDK-1.0.2739.1\Bin\x86\WebView2Loader.dll

    Normalement, le programme devrait le trouver via BDSCatalogRepository, non ? Sinon, où est-ce que je paramètre cela ?

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 912
    Par défaut
    Citation Envoyé par KlausGunther Voir le message
    Normalement, le programme devrait le trouver via BDSCatalogRepository, non ?
    Et par quel miracle ?

    Comme n'importe quel DLL, les chemins de recherche sont : répertoire system32, etc. et ceux définis par la variable d'environnement PATH. Donc redéfinis cette variable dans les options de ton projet et ajoute le chemin complet vers cette dll.

    Mais un essai montre qu'elle n'est chargée qu'au Navigate, tu pourrais dès lors redéfinir PATH par code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      {$IFDEF Debug}
      var BDSRepo :array[0..MAX_PATH -1] of char;
      ExpandEnvironmentStrings('%BDSCatalogRepository%\EdgeView2SDK-1.0.2739.1\Bin\x86', BDSRepo, MAX_PATH);
     
      const Path = GetEnvironmentVariable('PATH') +';' +BDSRepo;
      SetEnvironmentVariable('PATH', PChar(Path));
      {$ENDIF}
     
      EdgeBrowser1.Navigate('https://domain.com');
    end;

  3. #23
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    360
    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 : 360
    Billets dans le blog
    1
    Par défaut
    Très bien ! Ceci élimine la nécessité de copier la DLL dans le dossier de l'exécutable, et on n'a pas besoin d'installer la DLL dans le dossier système de Widows,pour une installation client.

    Tout fonctionne maintenant, sauf un dernier détail: l'obet initial de mon post, c'eat-a-dire créer le TEdgeBrowser dans un TPanel, lui aussi créé programmatiquement par la DLL.

    J'avais l'habitude de procéder ainsi, sous Delphi D6 PE:
    1 - dériver un TMyPanel d'un TPanel
    2 - y placer une variable privée fMyControl et créer une propriété Mycontrol accédant cette variable
    3 - créer programmatiquement un TMyPanel
    4 - créer ensuite programmatiquement un objet quelconque (un TSynedit par exemple)
    5 - placer visuellement le second objet dans le TMyPanel en changeant sa propriété ParentWindow pour y mettre le handle du TPanel
    6 - mémoriser le second objet dans la variable fMyControl de l'objet MyPanel
    7 - fournir MyPanel (tohours résidant dans la DLL) au programme appelant (hors DLL)
    8 - ce programme appelant, sans jamais utiliser directement cette valeur retournée, l'utilise alors comme "identifiant" pour des fonctions DLL travaillant avec cet objet

    Tout ceci marche parfaitement en D6. Mais ici, avec Delphi 12, j'ai une violation de mémoire au moment d'affecter le handle de TMuPanel à ParentWindow du TWebBrowser, alors que je n'ai pas encore quitté la DLL - je suis encore à la phase (5).

    Volici un extrai de mon code - la déclaration de ma classe dérivée du TPanel et la procédure de constrction:
    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
    type TKgfEdge = class(TPanel)
      private
        fEdge: TEdgeBrowser;
        fReady: boolean;
        fIsSuccess: Boolean;
        fWebErrorStatus: COREWEBVIEW2_WEB_ERROR_STATUS;
      published
        constructor CreateNew;
        destructor Destroy; override;
        procedure NavigationCompleted(Sender: TCustomEdgeBrowser;
          aIsSuccess: Boolean; aWebErrorStatus: COREWEBVIEW2_WEB_ERROR_STATUS);
      property Edge: TEdgeBrowser read fEdge write fEdge;
      property Ready: boolean read fReady write fReady;
      property IsSuccess: boolean read fIsSuccess write fReady;
      property WebErrorStatus: COREWEBVIEW2_WEB_ERROR_STATUS read fWebErrorStatus write fWebErrorStatus;
     
      end;
     
     
     
    implementation
     
    constructor TKgfEdge.CreateNew;
    begin
      inherited;
    showmessage('CreateNew - start');
      Edge := TEdgeBrowser.Create(nil);
    showmessage('CreateNew - 1');
      fReady := true;
    //  Edge.Parent := Self;
    showmessage('CreateNew - 2');
      Edge.ParentWindow := Handle;
    showmessage('CreateNew - 3');
      Edge.Top := 0;
      Edge.Left := 0;
      Edge.Width := self.ClientWidth;
      Edge.Height := self.ClientHeight;
    showmessage('CreateNew - 4');
      Edge.OnNavigationCompleted := NavigationCompleted;
    showmessage('CreateNew - fin');
    end;
    La violation de mémoire intervient lors de la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      Edge.ParentWindow := Handle;
    Chose qui fonctionnait parfaitement en D6.

    A l'évidence, me saut de D6 à D12 est énorme...
    -

  4. #24
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 988
    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 988
    Par défaut
    Pour la DLL pour faciliter le déploiement, intègre la en ressource ta DLL, avec ParamStr(0) ou GetModuleFileName tu connais le nom de l'EXE hote pour l'y placer.
    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

  5. #25
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    360
    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 : 360
    Billets dans le blog
    1
    Par défaut
    @ShaiLeTroll:
    Oui, je sais faire cela. Cette astuce est déjà mise en oeuvre dans ma DLL pour deux choses distinctes:
    - mise en place d'une ImageLibrary pour des icônes spécifiques
    - installation d'un programme de mise à jour de ma DLL, à la demande

    Ceci dit, je reiens sur ma question initiale:
    Pourquoi m'est-il impossible d'injecter programmatiquement un TEdgeBrowser créé programmatiquement dans un TPanel créé programmatiquement ?

    Je joins un fichier ZIP avec deux projets: KGF_Edge qui crée la DLL contenant le EdgeBrowser, et Test_KGF_Edge qui crée un programme chargeant cette DLL dynamiquement. La DLL généré n'est pas dans le ZIP, ni l'exe du programme démo - le téléchargement l'interdir.
    Ce dernier a 4 boutons, et seul le bouton de gauche est intéressant pour le moment: "Create KGF_Edge".
    Lors de la création de la Form1, KGF_Edge.dll est chargée dynamiquement et les liens vers ses 3 fonctions sont établis et memorisés.
    La fonction affiche d'ailleurs la valeur de la variable d'environnement PATH pour vérifier que le chemin vers la DLL de WebView2 est bien présent (à la fin).
    Le bouton "Create KGF_Edge" appelle la fonction Create_KGF_EDGE.
    Cette fonction, localisée dans la DLL, est bien appelée et démarre. Des messages indiquent son état d'avancement.
    Ainsi, on constate que la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      Edge.ParentWindow := Handle;
    de cette fonction génère une violation de mémoire. Pourquoi ?

    En Delphi 6, je fais ça tout le temps, sans aucun problème.
    Est-ce une différence avec Delphi 12 ?
    Est-ce TEdgeBrowser qui ne supporte pas cela ?
    Fichiers attachés Fichiers attachés

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 912
    Par défaut
    Citation Envoyé par KlausGunther Voir le message
    Pourquoi m'est-il impossible d'injecter programmatiquement un TEdgeBrowser créé programmatiquement dans un TPanel créé programmatiquement ?
    Parce que ton code est bogué

    1. Tu masques l'exception dans Create_KGF_EDGE, ce n'est pas une erreur mais ça n'aide pas.
    2. Tu renommes le constructeur CreateNew, pourquoi pas puisque l'instanciation est dynamique, mais inherited ne sert à rien puisque cette méthode n'existe pas dans ses ancêtres.
    3. Create n'est pas appelé suite à ce renommage, l'objet n'est pas correctement initialisé.
    4. Edge.ParentWindow := Handle n'est pas possible à ce moment-là puisque ce panel n'a ni propriétaire, ni parent (l'exception masquée au point 1), TWinControl.CreateWnd échoue.
    5. Les procédures exportées sont en stdcall mais les prototypes côté exe ne le sont pas.


    Au minimum ceci (après correction côté exe) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    constructor TKgfEdge.CreateNew(hDest :hWnd);
    begin
      Create(nil);
     
      ParentWindow := hDest;
      Edge := TEdgeBrowser.Create(self);
      Edge.Parent := Self;
      ...
    end;
    La destruction aussi est surprenante.

    1. result := aKEB : tu comptes retourner une instance libérée !
    2. if assigned(aKEB) then exit si assigné, ne libère rien !


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure Delete_KGF_EDGE(aKEB: TObject); stdcall; export;
    begin
      if aKEB is TKgfEdge then
        aKEB.Free;
    end;

  7. #27
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    360
    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 : 360
    Billets dans le blog
    1
    Par défaut
    Pour approfondir les recherches, j'ai fait un petit projet opérationnel en D6, et j'ai adapté mon projet en D12 de façon symétrique.

    Version Delphi 6:
    Préalable:
    1. définir ine variable dummyForm, mais sans créer la form

    Dans le constructeur:
    1. créer une classe simple sans racine
    2. ajouter un TPanel standard à cette classe, avec Owner=dummyForm
    3. assigner le handle de ma form cible à ParentWindow de ce panel
    4. ajouter un TMemo standard à cette classe, avec Owner=panel
    5. assigner le handle du panel à ParentWindow de ce mémo
    6. configurer position et dimensions du mémo dans le panel

    Par un bouton "Créer":
    1/ appeler le constructeur avec le handle de Form1 en paramètre

    Résultat: Mon panel avec le mémo apparaît dans la Form1. Je peux le supprimer, le recréer, etc. Tout fonctionne.

    Version Delphi 12:
    Préalable:
    1. définir ine variable dummyForm, mais sans créer la form

    Dans le constructeur:
    1. créer une classe simple sans racine
    2. ajouter un TPanel standard à cette classe, avec Owner=dummyForm
    3. assigner le handle de ma form cible à ParentWindow de ce panel
    4. ajouter un TEdgeBrowser standard à cette classe, avec Owner=panel
    5. assigner le handle du panel à ParentWindow de ce EdgeBrowser
    6. configurer position et dimensions du EdgeBrowser dans le panel

    Par un bouton "Créer":
    1/ appeler le constructeur avec le handle de Form1 en paramètre

    Résultat: il y a une viloation de mémoire lors du chargement de ParentWindow du Panel, avant même de penser au TEdgeBrowser


    Conclusion: il y a une différence importante entre D6 et D12 que je ne comprends pas.

    Auriez-vous une idée comment résoudre ce problème ?
    En pièces jointes, vous trouverez un fichier ZIP avec mon projet en D6 et un autre ZIP avec le projet de DLL et celui du programme de test associé.
    Fichiers attachés Fichiers attachés

  8. #28
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 569
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par KlausGunther Voir le message
    Et la DLL est bien dans le dossier suivant:
    C:\Users\klausgunther\Documents\Embarcadero\Studio\23.0\CatalogRepository\EdgeView2SDK-1.0.2739.1\Bin\x86\WebView2Loader.dll
    Normalement, le programme devrait le trouver via BDSCatalogRepository, non ?
    Donc, tu as bien la partie évènements de construction et c'est là qu'il faut intervenir
    Oui, BDSCatalogRepository est bien renseigné mais le hic c'est que les évènements de construction c'est l'équivalent d'un fichier batch . Perso je n'ai pas réussi à accéder au %BDSCatalogRepository% via shell ou cmd, c'est pourquoi j'ai indiqué le chemin entier

  9. #29
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    360
    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 : 360
    Billets dans le blog
    1
    Par défaut
    Eureka ! Merci à vous tous ! Vos suggestions m'ont ouvert la voie. Tout marche maintenant.

    Voici la version finale, permettant d'injecter dans une form un TPanel construit programmatiquement, cmprenant un TEdgeBrowser lui aussi construit programmatiquement.

    Cette version, encore de style "démo", affiche quelques messages de traçage. L'utilisation est la suivante:
    1. avant tout, créer la DLL enconstruisant le projet KGF_Edge (KGF_Edge.dll)
    2. puis créer le programme de démo en construisant le projet Test_KGF_Edge (Test_KGF_Edge.exe)
    3. lancer Test_KGF_Edge.exe

    On obtient ceci:
    Nom : aa1.png
Affichages : 54
Taille : 4,9 Ko

    4. commencer par le bouton "Create KGF_Edge"

    On ontient ceci:
    Nom : aa2.PNG
Affichages : 55
Taille : 6,0 Ko

    On voit bien le panel ainsi que le EdgeBrowser (en blanc).

    5. utiliser un des boutons "Load Google" ou "Load Help"
    Pour Google, on obtient ceci:
    Nom : aa3.png
Affichages : 55
Taille : 28,2 Ko

    6.le bouton "Delete KGF_Edge" supprime le browser et le panel
    7. la croix rouge supprime le browser et le panel si ce n'est pas encore fait, puis termine le programme.

    Voilà ce que je volais obtenir. Grâce à vos suggestions, j'y suis arrivé.
    Prochaine étape: intéger KGF_Edge.dll comme ressource dans ma grande DLL et l'en extraire en cas de besoin. Mais ça, je sais faire.
    Un grand MERCI à vous tous !
    Fichiers attachés Fichiers attachés

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 912
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    je n'ai pas réussi à accéder au %BDSCatalogRepository% via shell ou cmd
    Ces variables sont définies dans l'environnement Delphi et non au niveau global. Elles sont accessibles dans un batch s'il est lancé depuis l'événement de construction puisque dans ce cas il hérite du processus parent.

    Sans batch dans l'événement de construction, on accède à ces variables par $(BDSCatalogRepository).

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 4
    Dernier message: 30/04/2014, 17h06
  2. [Windows Phone 8] [Debutant] Lancer le navigateur avec une url depuis une application
    Par krizentherm dans le forum Windows Phone
    Réponses: 3
    Dernier message: 06/04/2014, 12h39
  3. [Débutant] Comment lancer un exe avec un autre utilisateur que Système
    Par Amelie_sc dans le forum C#
    Réponses: 6
    Dernier message: 04/07/2013, 12h24
  4. [CKEditor] Comment configurer l'éditeur avec une url
    Par whitespirit dans le forum Bibliothèques & Frameworks
    Réponses: 5
    Dernier message: 12/06/2008, 11h00
  5. comment lancer un exe avec parametre avec shell
    Par niceen dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 07/05/2008, 19h56

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