La Référence Absolue sur les Technologies Microsoft




Tous les Articles du Laboratoire Microsoft

Programmation sur Tablet PC : Réalisation d'une barre de recherche IE
Accueil > Articles > Matériels
Auteurs 
Julien BAKMEZDJIAN



 Tous les articles de cet auteur

4,2/5

Bien


35892
15/63

 

Introduction

 

Dans le dernier article, nous avons terminé notre moteur de recherche. Nous allons maintenant réaliser une application radicalement différente mais toujours dédiée TabletPC et utilisant la SDK déjà présentée. Ceci sera l’occasion d’aller plus avant dans la programmation .Net : nous allons nous attaquer à des problèmes d’interopérabilité COM/.Net, d’interfaces graphiques, d’accès à l’API Windows, de déploiement, ainsi qu’à une multitude d’obstacles ponctuels, comme la protection de ressources critiques. Notre objectif est en effet de réaliser une barre d’outils intégrée à Internet Explorer pour TabletPC. La barre devra permettre une utilisation la plus naturelle possible.

Voici donc le premier article d’une nouvelle série consacrée à ce projet dont se dégagent trois parties essentielles : l’intégration de la barre à Internet Explorer (IE) et l’installation sur la machine cible, l’IHM et enfin la logique d’arrière plan.

Dans une première partie, nous allons présenter en détails le projet dont nous vous proposerons une première version compilée. Ensuite, nous expliquerons comment réaliser et intégrer une barre d’outils à IE en .Net. Nous développerons finalement le projet de déploiement.

 

Présentation du projet

 

            Nous souhaitons réaliser une barre d’outils utilisable « normalement » (clavier et souris) ou exclusivement au stylet. Cette barre devra permettre la navigation sur le web, la recherche de mots via des moteurs de recherche, et la saisie assistée de formulaires web. Il faudra tenir compte des remarques concernant l’interface faites dans l’article « Introduction à la programmation sur Tablet PC ». En outre, la reconnaissance d’urls manuscrites étant délicate, il faudra le plus possible proposer des raccourcis à l’utilisateur : historique, concaténation des préfixes courants – http, www… – et de suffixes de domaines.

            Vous n’en êtes à lire que les premières lignes de ce projet ; cependant, la barre est, à la rédaction de ce premier article, quasiment finalisée. En voici donc une copie d’écran qui en dira plus long sur nos objectifs qu’un grand discours :

 

 

 

Comme vous pouvez le voir, le premier objectif était de permettre la saisie d’urls : à cet effet, trois boutons à cocher pour les préfixes, une zone de saisie pour le corps de l’url et cinq boutons de navigation. La zone de saisie s’agrandit lorsque le stylet s’approche et un historique apparaît dès le début de l’écriture :

 

 

Le second objectif était de lancer une recherche web sur les mots écrits dans la zone de saisie. C’est ce que permet le bouton le plus à droite.

 

Enfin, il fallait faciliter le remplissage au stylet de formulaires web. Pour cela, un menu contenant les mots les plus fréquents (vos nom, prénom, adresse mail…) apparaît lorsque vous cliquez sur le bouton « Paramètres utilisateur ». Cela dispense l’utilisateur de manœuvres parfois complexes lorsqu’il doit écrire des adresses, noms ou numéros de téléphone au stylet.

 

 


Le tout se devait d’être le plus configurable possible. Une boîte de dialogue devait permettre l’entrée des paramètres utilisateurs (un fichier de configuration par profil et non par machine).

 

Pour avoir une idée du résultat final, nous vous proposons de télécharger ici le fichier d’installation de notre InkToolBar. Il s’agit d’une première version β compilée à l’heure où nous rédigeons ce premier article ; de nouvelles versions seront donc certainement proposées dans les articles suivants. Comme d’habitude, les codes sources seront en téléchargement. Cependant, les différentes parties du projet ne seront disponibles qu’au fil des articles ; l’intégralité de la solution et de son code sera, quant à elle, fournie dans le dernier article.

 

Entrons maintenant dans le vif du sujet !

 

Création d’une ToolBar pour Internet Explorer

 

            La création d’une barre d’outils pour IE passe par l’implémentation de diverses interfaces COM et par l’enregistrement de la barre dans la base de registre. Ces opérations sont décrites à cette adresse. De nombreux exemples fourmillent sur le web (tapez « BandObject Internet Explorer » dans votre moteur préféré). Malheureusement, lorsque vous développez une barre pour IE en .Net, les choses se compliquent un peu et l’aide se fait plus rare…

Implémentation des interfaces COM

 

            Plusieurs interfaces sont à implémenter. Il faut tout d’abord les déclarer :

 

      [ComImport]

      [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

      [Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")]

      public interface IObjectWithSite

      {

            void SetSite([In ,MarshalAs(UnmanagedType.IUnknown)] Object

                  pUnkSite);

            void GetSite(ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)]

                  out Object ppvSite);

      }

           

Les trois premiers attributs permettent d’importer l’interface depuis le monde COM : ComImport  précise que l’interface est COM, puis les deux autres attributs indiquent le GUID de l’interface (que l’on peut trouver dans la base de registre en recherchant le nom de l’interface) et son type. Enfin, au sein de l’interface, on déclare toutes les méthodes sans oublier de « marshaller » les paramètres.

 

Une fois l’interface déclarée, c’est au développeur d’en réaliser l’implémentation. Pour cela, il faut créer une classe qui hérite de toutes les interfaces nécessaires. C’est dans cette classe qu’il faut implémenter chaque méthode des interfaces COM. Nos recherches préliminaires nous ont permis de trouver un site décrivant toute l’implémentation C# (http://www.codeproject.com/csharp/dotnetbandobjects.asp). Vous trouverez ici le projet, fortement inspiré de celui de Pavel Zolnikov, que nous allons utiliser pour la création de notre barre d’outils. Le projet contient à l’origine trois fichiers ; nous n’en conservons que deux, le fichier Attribute.cs étant inutile dans notre cas, comme nous l’expliquerons plus loin. Les deux autres fichiers sont : BandObject.cs et ComInterop.cs. ComInterop déclare toutes les interfaces COM tel qu’expliqué plus haut. BandObject.cs contient une classe BandObject qui dérive de UserControl ainsi que de toutes les interfaces COM nécessaires.

Nous avons également apporté quelques modifications à ces deux fichiers. Mis à part la correction d’une erreur de déclaration de constantes dans le projet de Zolnikov, nous avons modifié les fonctions d’enregistrement. Nous avons également complété la méthode TranslateAcceleratorIO. Cette méthode spécifie les messages que IE doit passer à notre barre lorsque celle-ci a le focus.

 

public virtual Int32 TranslateAcceleratorIO(ref MSG msg)

{

      int returnValue = 1; // S_FALSE

 

      if(msg.message == 0x100)

            switch(msg.wParam)

            {

                  case (uint)Keys.Tab:

                  case (uint)Keys.F6:

                        if(SelectNextControl(ActiveControl, ModifierKeys ==

                             Keys.Shift ? false : true, true, true, false))

                             returnValue = 0;  //S_OK

                        break;

                  case (uint)Keys.Back:

                  case (uint)Keys.Left:

                  case (uint)Keys.Right:

                  case (uint)Keys.Home:

                  case (uint)Keys.Delete:

                  case (uint)Keys.End:

                  case (uint)Keys.Shift:

                  case (uint)Keys.Up:

                  case (uint)Keys.Down:

                  case (uint)Keys.Return:

                  case (uint)Keys.Escape:

                        SendMessage((int)this.ActiveControl.Handle,

                             (int)msg.message, (int)msg.wParam,

                             (int)msg.lParam);

                        returnValue = 0; //S_OK

                        break;

                  case (uint)Keys.C: // Ce cas est traité pour le Ctrl+C

                        if((GetKeyState(0x11/*VK_CONTROL*/) & 0x80) ==

                        0x80) // Si la touche contrôle est appuyée

                        {

                        // On envoie le message "WM_COPY" au contrôle actif

                             SendMessage((int)this.ActiveControl.Handle,

                                   0x301 /*WM_COPY*/, 0, 0);

                             returnValue = 0; //S_OK

                        }

                        break;

                  default:

                        break;

            }

      return returnValue;

}

 

Nous utilisons ici la méthode SendMessage de l’API Windows qui permet d’envoyer un message à une fenêtre (en l’occurrence, au contrôle actif de notre barre d’outils). Il faut donc la déclarer de la manière suivante :

 

[DllImport("user32.dll",EntryPoint="SendMessage")]

private static extern int SendMessage(int _WindowHandler, int _WM_USER,

                  int _data, int _id);

 

Nous traitons également le cas du Ctrl + C (copier) car il semble particulier (les tests montrent qu’il n’est pas transmis à notre barre si nous ne le déclarons pas explicitement). Il suffit donc d’envoyer, sur appui simultané des deux touches, un message de copie au contrôle actif de la barre (ce problème ne se pose pas pour le Ctrl + V).

                       

Enfin, notez que ce projet nécessite l’ajout d’une référence COM vers shdocvw.dll. Cette dll contient en effet la classe WebBrowserClass qui permet d’instancier le membre Explorer qui représente l’instance de IE en cours d’exécution (c’est à partir de cet objet Explorer que l’on peut par exemple lancer une navigation dans IE avec la méthode Navigate). Cette dll, automatiquement wrappée, est présente dans le projet proposé ici (Interop.shdocvw.dll).

 


Voici comment on utilise ce projet : on écrit une classe qui dérive de BandObject dans une bibliothèque de classes .Net (.dll). On lui attribue un GUID : pour cela, ouvrez le menu « Outils », cliquez sur « Créer un GUID » :

 

 

Ensuite, ajoutez l’attribut GUID à la nouvelle classe :

 

      // Exposition comme objet COM

      [Guid("0AC1CE45-B85B-4675-9A3A-1F15EB4F590E")]

      // Attribut perso servant à passer le nom, le style... de notre

      ToolBar

 

      /// <summary>

      /// Classe de notre InkToolBar héritant de BandObject

      /// </summary>

      public class InkToolBar : BandObject

      {

 

Dans cette classe (qui hérite donc indirectement de UserControl), on réalise l’interface graphique de la barre ainsi que sa logique. Si l’on souhaite accéder à des fonctions de IE (comme la navigation sur une page web), il suffit d’appeler des méthodes de l’objet Explorer (Navigate par exemple).

Après la compilation, il y a normalement plusieurs opérations à effectuer :

-         l’enregistrement de toutes les dll du projet de la barre dans le GAC

-         l’enregistrement de la dll principale en tant que composant COM

-         la modification de la base de registre afin de notifier IE de la présence d’une nouvelle barre

 

L’inscription COM de la sortie principale de notre projet nécessite en effet dans notre cas que l’on place la dll dans le GAC pour que IE puisse la trouver. A partir de là, on se trouve obligé de placer également toutes les dll utilisées par cette sortie principale dans le GAC. Tout cela se faisait dans le projet original de Zolnikov au moment de la compilation du projet : l’inscription COM ainsi que la copie dans le GAC étaient configurées dans les actions de post-compilation (disponibles uniquement pour un projet C++) à l’aide des deux exécutables gacutil et regasm :

 


Les actions d’après génération du projet d’exemple d’utilisation de BandObject de Zolnikov

 

 

La modification de la base de registre se faisait quant à elle automatiquement lors de l’appel à regasm. En effet, BandObject contient deux méthodes qui sont lancées lors des appels à regasm (enregistrement) ou regasm /u (désenregistrement) :

 

            /// <summary>

            /// Called when derived class is registered as a COM server.

            /// </summary>

            [ComRegisterFunctionAttribute]

            public static void Register(Type t)

            {

                  . . .

 

et :

 

            /// <summary>

            /// Called when derived class is unregistered as a COM server.

            /// </summary>

            [ComUnregisterFunctionAttribute]

            public static void Unregister(Type t)

            {

                  . . .

 

 

Tout se déroule donc au moment de la compilation… Nous allons devoir changer ces méthodes d’enregistrement COM et de modification de la base de registre pour que l’on puisse déployer notre barre…

 

Programme d’installation

 

            En résumé : pour fonctionner correctement, toutes les dll de notre projet devront être placées dans le GAC. En outre, il faut enregistrer la dll principale de la solution (celle qui contient la classe dérivant de BandObject et qui implémente toutes les fonctionnalités de notre barre d’outils) en tant que composant COM. Enfin, il faut modifier la base de registre pour que IE soit notifié de l’arrivée de notre nouvelle barre.

            Nous allons donc réaliser un projet de déploiement. Placer toutes les dll de notre solution dans le GAC de la machine cible n’est pas un problème : le projet de setup permet de choisir le dossier de destination de chaque assembly sur la machine cible :

 


 

 

N’oubliez pas toutefois de signer chaque assembly (cela est nécessaire pour copier un assembly dans le GAC) : générez un fichier qui contient les clés publique et privée à l’aide de l’outil sn.exe, puis ajoutez l’attribut :

 

[assembly: AssemblyKeyFile(@"..\..\..\nomduficher.snk")]

 

Cette ligne est généralement présente à la fin du fichier AssemblyInfo.cs.

 

            Nous devons également enregistrer le composant principal en tant que composant COM sur la machine cible. Pour cela, la méthode traditionnelle consisterait à exécuter regasm. Cet utilitaire est normalement utilisé lorsque l’on souhaite inscrire un composant .Net en COM. Pour cela, il crée les clés nécessaires dans la base de registre.

Cependant, regasm peut ne pas être installé sur la machine cible (et dans tout les cas, pas dans un répertoire connu à l’avance). De plus, on s’interdit de déployer regasm sur la machine cible. Il faut donc enregistrer le composant en composant COM « à la main ».

Pour connaître les clés à ajouter, il suffit d’exécuter regasm une fois (sur la machine de développement) avec l’option regfile :

 

regasm nom_de_assembly /regfile:nom_fichier_sortie

 

Cela enregistre dans le fichier spécifié (créé au format .reg) les actions effectuées lors de l’enregistrement d’un composant .Net en composant COM.

En outre, il faut ajouter quelques clés à ce fichier .reg pour spécifier à IE l’existence de la barre. Ces clés sont ajoutées de la manière suivante :

 

[HKEY_CLASSES_ROOT\CLSID\{0AC1CE45-B85B-4675-9A3A-1F15EB4F590E}\Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]

 

[HKEY_CLASSES_ROOT\CLSID\{0AC1CE45-B85B-4675-9A3A-1F15EB4F590E}\Implemented Categories\{00021494-0000-0000-C000-000000000046}]

 

[HKEY_CLASSES_ROOT\CLSID\{0AC1CE45-B85B-4675-9A3A-1F15EB4F590E}\Implemented Categories\{00021492-0000-0000-C000-000000000046}]

 

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Toolbar]

"{0AC1CE45-B85B-4675-9A3A-1F15EB4F590E}"="InkToolBar"

 

Tout cela nous dispense, comme dit plus haut, de la création d’un attribut personnalisé comme dans le projet original de Zolnikov.

 

Une fois que vous avez ajouté ces dernières clés, votre fichier .reg représente entièrement les actions à effectuer pour l’enregistrement en composant COM. Dans le projet de setup, il est possible de modifier la base de registre de la machine cible, soit en ajoutant les clés une à une, soit en important un fichier .reg. C’est évidemment pour cette dernière option que nous allons opter :

 


 

 

Toutes les clés nécessaires sont ainsi incorporées au projet de setup.

 

Lorsque l’installation aura lieu sur la machine cible, les clés seront créées dans la base de registre de la même manière que lors de l’exécution de regasm.

Notez bien toutefois que les clés enregistrées dans le programme de setup correspondent à un numéro de version précis de la dll, ainsi qu’à une clé de signature publique précise pour la dll. Si vous changez le numéro de version, et/ou la clé publique de la dll, vous devez modifier les clés concernées, soit à la main, soit en générant à nouveau le fichier .reg comme décrit plus haut (sans oublier d’y ajouter les clés nécessaires à l’apparition de la barre dans IE).

 

Conclusion

 

            A ce stade, nous avons réalisé une barre d’outils générique en .Net. Le programme d’installation permet de déployer proprement cette barre sur les machines cibles.

            Il faut maintenant remplir la barre et lui ajouter toutes les fonctionnalités voulues. Pour cela, nous devons réaliser l’interface la plus ergonomique possible. Nous allons donc voir dans les prochains articles la création de contrôles dédiés à notre projet. Ensuite nous verrons les points délicats dans l’implémentation des fonctionnalités.

 




En Savoir Plus 
Evaluez cet article 


Pour afficher ou poster un commentaire, cliquez sur ce lien : Forum-Microsoft



Retrouvez ci-dessous les autres sections du Laboratoire Microsoft