Follow me
RSS feed
My sources
My Viadeo

WinDev..BeforeNavigate2

Greg | 18 Feb 2009

windowsPour des questions professionnelles, j'ai dû me mettre à WinDev...

C'est pour moi une grande première. Tout d'abord parce que je n'avais plus fait de développement sur Windows depuis l'apparition de Windows NT 5.0 et qu'en plus il ne me serait jamais venu à l'idée d'aller copiner avec un langage qui permet de programmer en français.

Anyway1 ! Je ne ferais ni apologie ni satire contre l'OS ou le langage. Je voudrais juste vous faire profiter de mes premiers pas.

L'objectif que j'avais était de pouvoir afficher une liste de documents HTML et de permettre de naviguer entre ces documents. Faire un navigateur en quelque sorte. Oui, mais avec une contrainte supplémentaire due au fait que certains liens, dans ces documents, ont des URL qui ne pointent pas vers d'autres pages, mais qui doivent permettre de récupérer de l'information dans une base de données.

Je m'explique. L'ensemble des documents de départ est stocké dans une base de données. Pour chacun nous avons (entre autres), le nom du document et son contenu. Chaque document peut contenir trois types de liens :

J'ai parlé de base, mais en fait les documents, et toutes les informations nécessaires, sont accessibles via un jeu d'API.

La première chose à faire consiste à récupérer l'ensemble des titres des documents (il y en a peu prêt 150) et à les afficher dans une liste. Quand l'utilisateur clic sur un titre, le document correspondant s'affiche. Si par la suite il clic sur un lien pointant vers un document accessible via les APIs, ce document s'affiche. S'il clic sur un lien vers un document externe, là encore il s'affiche. S'il clic sur un lien pointant vers une donnée de la base, les informations relatives à cette donnée sont présentées dans un champ texte.

Le chargement de la liste des documents est relativement simple et sans surprise. Dans le cas qui m'intéresse, chaque document à un nom et un identifiant. J'ai donc déclaré une structure globale document :

document est une structure
  // Titre du document
  titre est une chaîne
  // ID du document
  id est un entier
FIN

J'ai également déclaré une variable de type tableau associatif afin d'y stocker les documents :

tableauDocument est un tableau associatif de document

Au niveau de l'interface, il suffit d'ajouter un champ de type liste (nommé ListeDocument). Puis, au moment de l'initialisation de la fenêtre contenant cette liste, nous récupérons l'ensemble des documents que nous ajoutons dans le tableau tableauDocument et dans la liste ListeDocument. Pour cela j'ai créé la procédure suivante :

PROCEDURE AjouteDocument( titre, id )
  // Création d'un document
  doc est un document
  doc:id = id
  doc:titre = titre

  // Ajout du document dans le tableau des documents
  tableauDocument[doc:titre] = doc

  // Ajout du titre du document dans la liste des documents
  ListeAjoute(ListeDocument, doc:titre)

La liste étant remplie, quand l'utilisateur double-clic sur un élément de la liste ListeDocument, nous chargeons le document HTML correspondant. La récupération du document se fait via une API prenant en entrée l'ID du document et renvoyant l'URL d'accès à ce document. Cette URL correspond à un fichier posé sur le disque du type C:\chemin\vers\le\document.html. Le code de Bouton gauche double-clic (VM_LBUTTONDBLCLK) de ListeDocument est le suivant :

titre est une chaîne = ListeDocument[ListeSelect(ListeDocument)]
doc est un document = tableauDocument[titre]
url est une chaîne = ChaîneRécupère(AppelDLL32(dll, "getDocumentUrl", doc:id), crAdresseASCIIZ)
ActiveXMSWebNavigateur>>Navigate2(url)

l'API getDocumentUrl agit de la façon suivante. Elle sort le document de la base et le dépose dans un fichier temporaire sur le disque. Puis elle renvoie le chemin vers ce fichier.

Comme vous l'avez remarqué, j'utilise l'ActiveX Microsoft Web Browser pour afficher les documents HTML. La mise en place de ce composant est très simple. Dans l'interface il suffit d'ajouter un ActiveX, de lui donner un nom (ActiveXMSWebNavigateur dans cet exemple) et de choisir Microsoft Web Browser dans la liste.

Le choix de cet ActiveX s'explique par le fait que, comme je l'ai signalé plus haut, certains liens doivent servir à récupérer de l'information dans une base de données. Or le composant HTML fourni en standard dans WinDev ne permet par ce genre de chose. Par contre, l'ActiveX utilisé propose l'événement BeforeNavigate2 qui est appelé avant le début de la navigation. Pour pouvoir l'utiliser, nous ajoutons la ligne suivante au niveau de initialisation de ActiveXMSWebNavigateur :

ActiveXEvénement("CaptureClicSurDocument", ActiveXMSWebNavigateur, "BeforeNavigate2")

Cette ligne indique que quand il y a un début de navigation sur un document, soit détection de l'événement BeforeNavigate2 sur ActiveXMSWebNavigateur, il faut appeler CaptureClicSurDocument. Il faut donc ajouter cette dernière procédure dans les Procédures locales.

La documentation de BeforeNavigate2 sur le MSDN indique que cet événement reçoit 7 paramètres. Voici donc comment nous devons déclarer la procédure CaptureClicSurDocument :

PROCEDURE CaptureClicSurDocument( pDist, Url, Flags, TargetFrameName, PostData, Headers, bCancel )

Il y a deux paramètres qui vont particulièrement nous intéresser :

Sachant cela, nous pouvons maintenant remplir le corps de la procédure CaptureClicSurDocument. Dans le cas particulier de cet exemple, si le lien sert à récupérer une information dans la base de données, l'URL est du type database/query?cle=valeur ou database est le nom de la base de données.

Nous allons donc partir du principe que si le paramètre Url de CaptureClicSurDocument contient la chaîne database/query nous devons stopper la navigation et recherche l'information dans la base. Sinon, nous avons affaire à un lien vers un autre document et nous laissons donc la navigation se poursuivre :

PROCEDURE CaptureClicSurDocument( pDist, Url, Flags, TargetFrameName, PostData, Headers, bCancel )
  SI ChaîneOccurence(Url, "database/query") > 0 ALORS
    // Recherche et la donnée dans la base
    RechercheDonnéeEnBase( Url )

    // Arrêt de la navigation
    bCancel = Vrai
  FIN

Tout l'intérêt réside maintenant dans la procédure RechercheDonnéeEnBase. Malheureusement nous je suis confronté, à ce niveau, à un problème. En effet l'ActiveX Microsoft Web Browser ne semble pas réagir de la même façon quand l'Url pointe sur un fichier local et quand elle pointe vers une adresse HTTP.

Pour nous en convaincre, regardons ce qui se passe quand on clic sur les deux liens du document HTML suivant :

<html>
  <body>
    <a href="http://www.example.com?cle=valeur">Lien HTTP</a><br />
    <a href="file:///C:/database/query?cle=valeur">Lien local</a>
  </body>
</html>

Dans le cas du clic sur le Lien HTTP, le debugger nous montre ceci :

lienhttp

Comme vous pouvez le voir, nous avons bien les paramètres dans Url. Mais si nous cliquons sur le Lien local, voici ce qu'indique le debugger :

lienlocal

Les paramètres ne sont pas là :(

Dans le cas qui m'intéresse, il s'agit toujours de liens locaux. En effet, les documents sont chargés localement et les liens de requête sont du type <a href="database/query?cle=valeur">...</a> dont transformé en quelque chose du genre file:///C:/temp/database/query?cle=valeur.

Je continue mon exploration du monde Windows/WinDev et je vous préviendrai dès que j'ai une solution.

1 en Québécois dans le texte (NDLR).

Copyright © 2009 - 2011 Grégoire Lejeune.
All documents licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License, except ones with specified licence.
Powered by Jekyll.