Comment migrer une solution basée sur les documents vers un Add-In applicatif

Paru le 26 janvier 2007

Résumé : Apprenez à migrer vos solutions basées sur des documents vers des compléments de niveau application. Les compléments permettent de personnaliser de nouvelles fonctionnalités du système Microsoft Office 2007, telles que les volets de tâches de niveau application et le ruban. (43 pages imprimées)

Brian A. Randell, MCW Technologies, LLC

Décembre 2006

S'applique à : Système Microsoft Office 2007, Microsoft Visual Studio 2005 Tools pour le système Microsoft Office 2007, Microsoft Visual Studio 2005 Tools pour le Système Microsoft Office

Migrate a Document-Level Customization to an Application-Level Add-In in 2007 Office System 

Sur cette page

Présentation : Outils de développement pour Microsoft Office Présentation : Outils de développement pour Microsoft Office
Elaboration d'une solution Office 2003 Elaboration d'une solution Office 2003
Modifications de la conception Modifications de la conception
Conclusion Conclusion
Ressources supplémentaires Ressources supplémentaires

Présentation : Outils de développement pour Microsoft Office

Chaque version de Microsoft Visual Studio Tools pour le systè me Microsoft Office (les outils Visual Studio pour Office) a fourni aux développeurs programmant à l'aide de Microsoft Visual Basic et Microsoft Visual C# de nouvelles façons d'étendre et d'améliorer le système Microsoft Office. La version actuelle, Microsoft Visual Studio 2005 Tools pour le système Microsoft Office, apporte plusieurs fonctionnalités nouvelles, notamment la prise en charge à la conception des documents Microsoft Office Excel 2003 et Microsoft Office Word 2003, la prise en charge des volets de tâches Actions de document , une riche prise en charge de la liaison de données, des options de déploiement améliorées et la prise en charge des balises actives (voir What's New in Visual Studio 2005 Tools for Office [en anglais] pour plus d'informations). Cependant, le temps passe. Actuellement, le système Microsoft Office 2007 en est à la version correspondant à la dernière phase bêta. Cette nouvelle version d'Office introduit des centaines de nouvelles options pour les développeurs. Pour permettre aux développeurs de code géré de tirer parti de ces nouvelles fonctionnalités dès que possible, Microsoft introduit une version mise à jour de Visual Studio Tools pour Office, connue sous la dénomination de Microsoft Visual Studio 2005 Tools pour le système Microsoft Office 2007 (également appelé Visual Studio 2005 Tools pour Office Second Edition). Cette nouvelle version apporte des options de programmabilité supplémentaires à l'ensemble d'outils de Visual Studio Tools pour Office, avant la prochaine version complète.

Remarque :

Cet article a été développé et testé avec Visual Studio 2005 Tools pour Office (la version actuellement lancée) et le Visual Studio 2005 Tools pour Office Second Edition. Si vous utilisez une version ultérieure, vos résultats peuvent être différents.

Visual Studio 2005 Tools pour Office Second Edition introduit une nouveauté attendue depuis longtemps : la prise en charge de l'élaboration de compléments de niveau application, la modification du ruban et la création de volets de tâches de niveau application. Le Tableau 1 propose la liste complète des applications hôtes Visual Studio 2005 Tools pour Office Second Edition prises en charge. Il montre que vous pouvez élaborer des compléments d'application gérés destinés à la prochaine version d'Office, et à certaines applications Microsoft Office 2003.

Tableau 1. Hôtes des compléments d'application

Hôte/label

Visual Studio 2005 Tools pour Office Second Edition

Microsoft Office Access 2003

Non

Microsoft Office Excel 2003

Oui

Microsoft Office FrontPage 2003

Non

Microsoft Office Outlook 2003

Oui (il est également possible de créer des compléments d'application Outlook 2003 à l'aide de Visual Studio 2005 Tools pour Office, sans utiliser Visual Studio 2005 Tools pour Office Second Edition).

Microsoft Office PowerPoint 2003

Oui

Microsoft Office Project 2003

Non

Microsoft Office Publisher 2003

Non

Microsoft Office Visio 2003

Oui

Microsoft Office Word 2003

Oui

Microsoft Office Access 2007

Non

Microsoft Office Excel 2007

Oui

Microsoft Office InfoPath 2007

Oui

Microsoft Office Outlook 2007

Oui

Microsoft Office PowerPoint 2007

Oui

Microsoft Office Project 2007

Non

Microsoft Office Publisher 2007

Non

Microsoft Office SharePoint Designer 2007

Non

Microsoft Office Visio 2007

Oui

Microsoft Office Word 2007

Oui

Comme vous le voyez, l'avenir s'annonce radieux, avec des choix nouveaux et très attrayants. A l'aide de Visual Basic ou Visual C#, vous pouvez désormais fournir des solutions plus riches et peut-être même meilleures qu'auparavant. Cependant, ces choix peuvent parfois semer la confusion, surtout si vous avez déjà créé une solution Visual Studio Tools pour Office à l'aide d'une version antérieure des outils.

Le volet de tâches Actions de document est un exemple d'une importance fondamentale illustrant un élément dont l'accès a été facilité. Microsoft Office XP a introduit le volet de tâches dans le but de regrouper les commandes fréquemment utilisées dans un élément d'interface utilisateur (IU) accessible pendant que l'utilisateur travaille activement sur un document. Par comparaison avec les boîtes de dialogue, l'avantage est évident : avec le volet de tâches, les utilisateurs ne sont pas empêchés de travailler comme ils le sont avec une boîte de dialogue modale. En outre, de nombreux volets de tâches, tels que le volet de tâches Styles et mise en forme, permettent de voir immédiatement les mises à jour apportées aux documents. Office 2003 a introduit une programmabilité de document intelligente qui vous permet de créer votre propre volet de tâches Actions de document personnalisé. Vous pouvez joindre un volet de tâches Actions de document à un document Word 2003 ou à un classeur Excel 2003. Microsoft expose l'interface de programmation d'application (API) de document intelligente de base via une série d'interfaces basées sur COM. Maintenant, COM est devenu un vieil ami. Cependant, on devient parfois trop grand pour ses amis. On peut dîner avec eux de temps en temps, mais il n'est pas question de les voir tous les jours. La bonne nouvelle est que l'équipe Visual Studio Tools pour Office partage ce point de vue. Son objectif est d'exposer une riche API gérée vous permettant d'élaborer de formidables solutions intégrant le système Microsoft Office sans devoir passer trop de temps avec COM.

Elaboration d'une solution Office 2003

Visual Studio Tools pour Office assure une prise en charge gérée des volets de tâches Actions de document dans Excel 2003 et Word 2003. La meilleure façon de comprendre ce qui fonctionne avec les volets de tâches Actions de document est d'examiner un exemple. L'exemple que j'ai créé pour cet article est une solution simple permettant de créer des citations de livre. Vous fournissez un ISBN à la solution, et celle-ci fournit toutes les données nécessaires pour citer le livre dans un document Word. Pour cela, il faut se connecter au service Web XML public (et gratuit) d'Amazon.com. Pour démarrer, vous devez élaborer la solution à l'aide de Visual Studio Tools pour Office. Ensuite, vous migrez vers le système Office 2007 à l'aide de Visual Studio 2005 Tools pour Office Second Edition.

La solution présentée ci-dessous n'est pas une option uniformisée. Dans cet exemple, vous voyez d'abord comment créer une solution spécifique au document en utilisant Word 2003 et un volet de tâches Actions de document. Cette conception initiale est simple. Ensuite, vous voyez cette solution dans Office Word 2007, en utilisant cette fois le nouveau volet de tâches de niveau application. La solution Word 2007 utilise une conception factorisée, élément que vous pouvez utiliser dans vos solutions Office 2003. Dans certains cas, une migration telle que celle présentée ici se justifie. Dans d'autres, une solution utilisant un volet de tâches Actions de document peut être plus adéquate. Cependant, il est intéressant de réaliser une solution factorisée conçue pour être réutilisée.

Créez la solution en utilisant Visual Basic ou Visual C#. Pour recréer cet échantillon par vous-même, vous devez obtenir une clé gratuite de développeur de services Web Amazon.com. Vous trouverez des instructions et des informations supplémentaires sur la page Amazon Web Services.

Remarque :

Même s'il est possible d'écrire du Visual Basic et du Visual C# de façon quasiment identique, le code étudié dans cet article utilise généralement des constructions de langage intégrées (telles que des fonctionnalités Visual Basic MsgBox et WithEvents) à la place d'une alternative Microsoft .NET Framework.

Pour élaborer la solution Office 2003

  • Dans le menu Fichier, pointez sur Nouveau puis cliquez sur Projet.

  • Dans la boîte de dialogue Nouveau projet, dans la liste des types de projet, développez le nœud Visual Basic ou le nœud Visual C#.

  • Sélectionnez le nœud Office dans la liste des types de projet.

  • Dans le volet Modèles, sélectionnez Document Word.

  • Saisissez les Citations de nom et un emplacement pour votre personnalisation, puis cliquez sur OK.

    L'Assistant Projet Visual Studio Tools pour Office s'ouvre.

  • Cliquez sur OK pour accepter les paramètres par défaut.

    Au bout de quelques instants, le document Word 2003 s'ouvre en tant que document d'onglet dans Microsoft Visual Studio 2005.

  • Dans le menu Affichage, cliquez sur Code pour ouvrir le fichier de code du document.

La classe initiale, ThisDocument, ne contient que deux gestionnaires d'événements : ThisDocument_Startup et ThisDocument_Shutdown.

La première chose à faire est de définir des variables de niveau classe destinées aux contrôles Microsoft Windows Forms que le volet de tâches Document Actions (Actions sur les documents) hébergera. Ajoutez huit contrôles Windows Forms : deux boutons, une zone de texte et cinq étiquettes. C'est dans la zone de texte que les utilisateurs saisissent l'ISBN des livres à rechercher. Le premier bouton permet aux utilisateurs de soumettre l'ISBN au service Web. Le second place la citation dans le document Word à l'emplacement actuel du curseur. Quatre des étiquettes affichent l'auteur principal du livre (déterminé par le service Web), le titre, l'éditeur et la date de publication. La dernière étiquette sert à tenir l'utilisateur informé de l'état de l'appel de service Web pendant l'extraction des informations sur le livre.

Les blocs de code suivants affichent toutes les modifications de la classe ThisDocument.

        Visual Basic

        Public Class ThisDocument
        Private WithEvents btnGetBookInfo As Button
        Private WithEvents btnPutInfoInDoc As Button
        Private lblGetBookInfoStatus As Label

        Private txtISBN As TextBox
        Private lblAuthor As Label
        Private lblPublisher As Label
        Private lblTitle As Label
        Private lblYearPublished As Label

        Private Sub ThisDocument_Startup(>ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles Me.Startup

        End Sub

        Private Sub ThisDocument_Shutdown(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles Me.Shutdown

        End Sub

        End Class
      
        C#

        namespace CitationsCS
        {
        public partial class ThisDocument
        {
        private Button btnGetBookInfo;
        private Button btnPutInfoInDoc;
        private Label lblGetBookInfoStatus;

        private TextBox txtISBN;
        private Label lblAuthor;
        private Label lblPublisher;
        private Label lblTitle;
        private Label lblYearPublished;

        private void ThisDocument_Startup(object sender, System.EventArgs e)
        {
        }

        private void ThisDocument_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region VSTO Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
        this.Startup += new System.EventHandler(ThisDocument_Startup);
        this.Shutdown += new System.EventHandler(ThisDocument_Shutdown);
        }

        #endregion
        }
        }
      

Dans le gestionnaire d'événements ThisDocument_Startup, les contrôles sont initialisés en fonction des besoins. Le code utilise ensuite la méthode Add de la collection Controls de l'objet ActionsPane pour ajouter les différents contrôles au volet de tâches Actions de document dans l'ordre dans lequel ils s'affichent, de haut en bas.

        Visual Basic

        Public Class ThisDocument
        Private Sub ThisDocument_Startup(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles Me.Startup

        btnGetBookInfo = New Button()
        btnGetBookInfo.Text = "Get Book Data"

        btnPutInfoInDoc = New Button()
        btnPutInfoInDoc.Text = "Put Book Data"
        btnPutInfoInDoc.Enabled = False

        lblGetBookInfoStatus = New Label
        lblGetBookInfoStatus.Text = "Ready"
        txtISBN = New TextBox
        txtISBN.Text = String.Empty
        lblAuthor = New Label
        lblYearPublished = New Label
        lblPublisher = New Label
        lblTitle = New Label

        With ActionsPane.Controls
        .Add(btnGetBookInfo)
        .Add(btnPutInfoInDoc)
        .Add(lblGetBookInfoStatus)
        .Add(txtISBN)
        .Add(lblAuthor)
        .Add(lblYearPublished)
        .Add(lblPublisher)
        .Add(lblTitle)
        End With
        End Sub

        Private Sub ThisDocument_Shutdown(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles Me.Shutdown

        End Sub

        End Class
      
        C#

        public partial class ThisDocument
        {
        private void ThisDocument_Startup(object sender, System.EventArgs e)
        {
        btnGetBookInfo = new Button();
        btnGetBookInfo.Text = "Get Book Data";
        btnGetBookInfo.Click += new EventHandler(btnGetBookInfo_Click);

        btnPutInfoInDoc = new Button();
        btnPutInfoInDoc.Text = "Put Book Data";
        btnPutInfoInDoc.Enabled = false;
        btnPutInfoInDoc.Click += new EventHandler(btnPutInfoInDoc_Click);

        lblGetBookInfoStatus = new Label();
        lblGetBookInfoStatus.Text = "Ready";
        txtISBN = new TextBox();
        txtISBN.Text = string.Empty;
        lblAuthor = new Label();
        lblPublisher = new Label();
        lblTitle = new Label();
        lblYearPublished = new Label();

        ActionsPane.Controls.Add(btnGetBookInfo);
        ActionsPane.Controls.Add(btnPutInfoInDoc);
        ActionsPane.Controls.Add(lblGetBookInfoStatus);
        ActionsPane.Controls.Add(txtISBN);
        ActionsPane.Controls.Add(lblAuthor);
        ActionsPane.Controls.Add(lblPublisher);
        ActionsPane.Controls.Add(lblYearPublished);
        ActionsPane.Controls.Add(lblTitle);
        }
        void btnPutInfoInDoc_Click(object sender, EventArgs e)
        {
        throw new Exception("The method or operation is not implemented.");
        }

        void btnGetBookInfo_Click(object sender, EventArgs e)
        {
        throw new Exception("The method or operation is not implemented.");
        }

        private void ThisDocument_Shutdown(object sender, System.EventArgs e)
        {
        }
        }
      

A ce stade, vous disposez de suffisamment de code pour pouvoir effectuer des essais. Appuyez sur F5 pour démarrer Word et exécuter la solution. Le volet de tâches Actions de document s'ouvre et tous les contrôles sont disposés comme dans la Figure 1.

Figure 1. Volet de tâches Actions de document rempli
Volet de tâches Actions de document rempli

Maintenant que l'interface utilisateur de base est définie, ajoutez la logique permettant d'obtenir les informations sur le livre issues du service Web Amazon.com. Pour tenir l'utilisateur informé de la progression de l'extraction des données sur le livre, un contrôle Label affiche des informations d'état. Ce bloc de code suivant crée une procédure d'aide générique pour modifier la propriété Text de l'étiquette et l'actualiser.

        Visual Basic

        Public Class ThisDocument
        Private Sub UpdateStatus(ByVal Message As String)
        lblGetBookInfoStatus.Text = Message
        lblGetBookInfoStatus.Update()
        End Sub
        End Class
      
        C#

        public partial class ThisDocument
        {
        private void UpdateStatus(string Message)
        {
        lblGetBookInfoStatus.Text = Message;
        lblGetBookInfoStatus.Update();
        }
        }
      

Pour utiliser le service Web Amazon.com, ajoutez une référence Web au projet.

Pour ajouter une référence de service Web

  • Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le nœud de projet, puis cliquez sur Ajouter une référence Web.

  • Dans la boîte de dialogue Ajouter une référence Web, saisissez l'adresse suivante dans la zone URL, puis cliquez sur OK :

    http://webservices.amazon.com/AWSECommerceService/2006-05-17/AWSECommerceService.wsdl

Remarque :

Au moment où cet article a été rédigé, un problème empêchait la version la plus récente de la définition WSDL du service Web e-commerce Amazon.com, utilisée via le proxy de service Web généré. Cette version-ci est donc la dernière en date que j'ai pu utiliser. La version la plus récente de leur WSDL se trouve sur http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl .

    Une fois que la description du service Web s'affiche, tapez AmazonECS4 dans la zone Nom de la référence Web, puis cliquez sur Ajouter une référence pour terminer le processus et créer la classe de proxy locale.

Maintenant que la référence Web est prête, ajoutez les trois champs supplémentaires suivants à la classe ThisDocument.

        Visual Basic

        Private Const AWS_Access_KeyId As String = "<i>Your Access
        Key ID</i>"
        Private aws As AmazonECS4.AWSECommerceService = Nothing
        Private savedISBN As String
      
        C#

        private const string AWS_Access_KeyId = "<i>Your Access Key ID</i>";
        private AmazonECS4.AWSECommerceService aws = null;
        private string savedISBN;
      

Le premier champ est une constante qui représente l'ID de votre clé d'accès au développeur de service Web Amazon. Comme nous l'avons vu, vous pouvez obtenir une clé gratuite sur la page Amazon Web Services. Le deuxième champ est une référence au proxy e-commerce Amazon local que vous avez créé précédemment, et le troisième sert à stocker l'ISBN demandé.

Le dernier bit de code comporte deux parties. La première concerne le code qui appelle le service Web Amazon, et la seconde le code utilisé pour ajouter l'information sur le livre au document actuel.

La première section de code correspond au gestionnaire d'événements Click du bouton btnGetBookInfo. En premier lieu, le code effectue une validation de base des données entrées. Il s'assure que le champ n'est pas nul ou n'est pas une chaîne vide. Vous pouvez ajouter du code permettant de vérifier si la valeur que l'utilisateur entre est un ISBN valide. Ensuite, le code crée une instance de la classe de service Web Amazon de niveau supérieur et stocke une référence à celle-ci dans la variable de niveau classe aws. Le code initialise l'ItemLookupRequest avec les données nécessaires pour rechercher les informations sur le livre. Ces données concernent notamment l'ISBN que l'utilisateur a entré, le type de recherche que le service Web doit effectuer et la quantité de données que le service Web doit retourner.

Amazon.com a conçu l'API de service Web en vue de la rendre flexible. Vous pouvez spécifier différents types d'informations à retourner sous la forme de ResponseGroups. Pour ce complément, le ResponseGroup moyen comporte toutes les données nécessaires pour remplir les contrôles du volet de tâches. Lorsque le code a configuré l'ItemLookupRequest, il compresse l'instance dans un objet ItemLookup. Chaque ItemLookupRequest peut contenir jusqu'à dix objets ItemLookupRequest. Cet exemple n'en utilise qu'un. C'est dans l'ItemLookupRequest que vous indiquez votre clé de service Web Amazon (qui est déjà définie comme une constante de niveau classe).

Vous avez maintenant définir tout ce dont le code a besoin pour effectuer l'appel de service Web proprement dit. La méthode ItemLookup de l'instance aws exécute l'appel de service Web et transmet les données à Amazon.com. La méthode retourne un objet ItemLookupResponse. Etant donné que la méthode peut retourner des résultats liés à plusieurs éléments, le bit de code suivant décompresse la première collection Items (Eléments) et obtient ensuite le premier Item de la collection. Dans cet exemple, il doit y avoir une seule collection Items, contenant un seul Item, parce que le code effectue une recherche fondée sur l'ISBN, qui est propre à un titre particulier. Le code accède ensuite à la collection ItemAttributes pour charger l'auteur, la date de publication, l'éditeur et le titre dans leurs contrôles respectifs. Enfin, et surtout, le code active le bouton btnPutInfoInDoc.

Compte tenu des risques, encapsulez le code de base dans un bloc Try..Catch..Finally, comme indiqué. En outre, le code effectue des appels vers la méthode UpdateStatus pour tenir l'utilisateur informé de la progression de la recherche.

        Visual Basic

        Private Sub btnGetBookInfo_Click(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles btnGetBookInfo.Click

        Dim finalStatus As String = "Last Lookup Complete"
        btnPutInfoInDoc.Enabled = False

        If txtISBN.Text Is Nothing OrElse txtISBN.Text = String.Empty Then
        MsgBox("Please enter a valid ISBN.", _
        MsgBoxStyle.Exclamation, "Warning")
        txtISBN.Focus()
        Return
        End If

        Try
        UpdateStatus("Preparing ...")

        If aws Is Nothing Then
        aws = New AmazonECS4.AWSECommerceService()
        End If

        ' Define a specific item to look up.
        Dim ilr As New AmazonECS4.ItemLookupRequest
        ilr.ItemId = New String() {txtISBN.Text.Trim()}
        ilr.IdType = AmazonECS4.ItemLookupRequestIdType.ASIN
        ilr.IdTypeSpecified = True
        ilr.ResponseGroup = New String() {"Medium"}

        Dim il As New AmazonECS4.ItemLookup()
        With il
        .AWSAccessKeyId = AWS_Access_KeyId
        .Request = New AmazonECS4.ItemLookupRequest() {ilr}
        End With

        UpdateStatus("Making Request ...")

        ' Make the request from the Web service.
        Dim ilresp As AmazonECS4.ItemLookupResponse = aws.ItemLookup(il)
        UpdateStatus("Processing Response ...")

        ' Unpack the results.
        Dim resultsItems As AmazonECS4.Items = ilresp.Items(0)
        Dim mainItem As AmazonECS4.Item = resultsItems.Item(0)

        ' Load the results into the UI.
        With mainItem.ItemAttributes
        savedISBN = .ISBN
        lblAuthor.Text = .Author(0)
        lblYearPublished.Text = CDate(.PublicationDate).Year.ToString()
        lblPublisher.Text = .Publisher
        lblTitle.Text = .Title
        End With

        btnPutInfoInDoc.Enabled = True

        Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.Critical, ex.Source)
        finalStatus = "Error on last request. Try again."

        Finally
        UpdateStatus(finalStatus)
        End Try
        End Sub
      
        C#

        void btnGetBookInfo_Click(object sender, EventArgs e)
        {
        string finalStatus = "Last Lookup Complete";
        btnPutInfoInDoc.Enabled = false;

        if (txtISBN.Text == null || txtISBN.Text == string.Empty)
        {
        MessageBox.Show("Please enter a valid ISBN.", "Warning",
        MessageBoxButtons.OK, MessageBoxIcon.Warning );
        txtISBN.Focus();
        return;
        }

        try
        {
        UpdateStatus("Preparing ...");
        if (aws == null)
        {
        aws = new AmazonECS4.AWSECommerceService();
        }

        // Define a specific item to look up.
        AmazonECS4.ItemLookupRequest ilr =
        new AmazonECS4.ItemLookupRequest();
        ilr.ItemId = new string[] {txtISBN.Text.Trim()};
        ilr.IdType = AmazonECS4.ItemLookupRequestIdType.ASIN;
        ilr.IdTypeSpecified = true;
        ilr.ResponseGroup = new string[] {"Medium"};

        AmazonECS4.ItemLookup il = new AmazonECS4.ItemLookup();
        il.AWSAccessKeyId = AWS_Access_KeyId;
        il.Request = new AmazonECS4.ItemLookupRequest[]{ilr};

        UpdateStatus("Making Request ...");

        // Make the request from the Web service.
        AmazonECS4.ItemLookupResponse ilresp = aws.ItemLookup(il);
        UpdateStatus("Processing Response ...");

        // Unpack the results.
        AmazonECS4.Items resultsItems = ilresp.Items[0];
        AmazonECS4.Item mainItem = resultsItems.Item[0];

        // Load the results into the UI.
        savedISBN = mainItem.ItemAttributes.ISBN;
        lblAuthor.Text = mainItem.ItemAttributes.Author[0];
        lblYearPublished.Text = System.Convert.ToDateTime(
        mainItem.ItemAttributes.PublicationDate).Year.ToString();
        lblPublisher.Text = mainItem.ItemAttributes.Publisher;
        lblTitle.Text = mainItem.ItemAttributes.Title;

        btnPutInfoInDoc.Enabled = true;
        }
        catch (Exception ex)
        {
        MessageBox.Show(ex.Message, ex.Source,
        MessageBoxButtons.OK, MessageBoxIcon.Stop);
        finalStatus = "Error on last request. Try again.";
        }
        finally
        {
        UpdateStatus(finalStatus);
        }
        }
      

Lorsque le service Web a pris fin et que les données sont chargées dans les contrôles, le code active le bouton btnPutInfoInDoc . Le dernier bloc de code que vous avez besoin d'ajouter est le code de gestionnaire d'événements Click. Le code crée un tableau de chaînes devant contenir toutes les données de contrôle, puis met à jour la chaîne citation en utilisant String.Format avec les valeurs issues du tableau. Le code utilise ensuite la méthode InsertAfter de l'objet Range pour insérer la citation à l'emplacement actuel du curseur. Lorsque vous avez ajouté ce code, la solution est terminée et vous pouvez la tester.

        Visual Basic

        Private Sub btnPutInfoInDoc_Click(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles btnPutInfoInDoc.Click

        Dim data() As String = {lblTitle.Text, lblAuthor.Text, _
        lblYearPublished.Text, lblPublisher.Text, _
        savedISBN}
        Dim citation As String = _
        String.Format("{0} by {1}.
        Copyright {2} {3}, {4}", data)
        Me.Range.InsertAfter(citation)
        End Sub
      
        C#

        void btnPutInfoInDoc_Click(object sender, EventArgs e)
        {
        string[] data = { lblTitle.Text, lblAuthor.Text,
        lblYearPublished.Text, lblPublisher.Text, savedISBN };
        string citation = string.Format(
        "{0} by {1}. Copyright {2} {3}, {4}", data);
        object missingValue = System.Reflection.Missing.Value;
        this.Range(ref missingValue, ref missingValue).InsertAfter(citation);
        }
      

Comment avancer

Si la solution présentée fonctionne, elle est cependant loin d'être parfaite. Du point de vue de la conception, le fait de stocker tout le code dans la classe ThisDocument empêche une réutilisation. En outre, le placement de contrôles dans le volet de tâches est fonctionnel mais simple. La difficulté est que vous devez toujours utiliser le document particulier concerné pour exploiter le volet de tâches de service Web Amazon. Le fait de le transformer en projet de modèle Word apporterait une certaine aide. Cependant, ce que l'on recherche vraiment est un volet de tâches de niveau application. Heureusement, Word 2007 prend en charge les volets de tâches de niveau application. La prochaine section vous montre comment créer la solution pour qu'elle s'exécute comme un volet de tâches de niveau application. En outre, vous pouvez refactoriser la conception de manière à pouvoir l'utiliser plus facilement dans une autre application hôte.

Modifications de la conception

La solution est assez simple, mais elle peut être refactorisée de plusieurs manières. Les fonctionnalités présentées se composent de trois domaines principaux : intégration de volet de tâches, intégration de document hôte et code de service Web. La première étape consiste à créer un assembly séparé et élaborer un contrôle utilisateur Windows Forms permettant d'héberger les contrôles d'interface utilisateur. L'étape suivante consiste à élaborer un assembly contenant tout le code de service Web. La dernière étape réunit ces éléments : Le contrôle utilisateur est connecté à l'assembly de service Web, puis l'assembly de contrôle utilisateur est chargé dans un volet de tâches de niveau application par un complément d'application Word 2007.

Elaboration du contrôle utilisateur

Pour élaborer le contrôle utilisateur, vous avez besoin d'un nouveau projet de bibliothèque de contrôles Windows. Dans cette version de la solution, vous devez créer une grande solution Visual Studio contenant tous les projets définis. Vous pouvez également créer une solution Visual Studio distincte pour chaque élément.

Pour élaborer un contrôle utilisateur

  • Dans le menu Fichier, pointez sur Nouveau puis cliquez sur Projet.

  • Dans la boîte de dialogue Nouveau projet, dans la liste des types de projet, développez le nœud Visual Basic ou le nœud Visual C#.

  • Sélectionnez le nœud Windows dans la liste des types de projet.

  • Dans le volet Modèles , sélectionnez la Bibliothèque de contrôles Windows.

  • Nommez le projet CitationsUC, spécifiez un emplacement réservé au contrôle utilisateur, nommez la solution CitationsSolution, sélectionnez Créer le répertoire pour la solution , puis cliquez sur OK.

  • Dans l'Explorateur de solutions, cliquez avec le bouton droit sur Usercontrol.vb ou Usercontrol.cs, puis cliquez sur Renommer.

  • Modifiez le nom en Citation.vb ou Citation.cs.

Précédemment, vous avez ajouté de manière programmatique les contrôles Windows Forms au volet de tâches. Toutefois, vous pouvez créer visuellement un contrôle utilisateur, en utilisant le concepteur, ou en code. Ce choix vous appartient. Souvenez-vous simplement que vous devez ajouter cinq étiquettes, une zone de texte et deux boutons. C'est vous qui choisissez leur disposition. La Figure 2 vous propose un exemple de disposition.

Figure 2. Contrôle utilisateur Citation terminé
Contrôle utilisateur Citation terminé

Lorsque vous avez ajouté et disposé des contrôles, vous devez créer l'assembly de service Web avant d'écrire du code dans le contrôle utilisateur.

Encapsuler le code de service Web

Après l'élaboration du contrôle utilisateur, l'étape suivante est de créer un assembly devant héberger tout le code de service Web.

Pour créer l'assembly de service Web

  • Ouvrez la solution que vous avez créée précédemment.

  • Dans le menu Fichier, pointez sur Ajouter puis cliquez sur Nouveau projet .

  • Dans la boîte de dialogue Nouveau projet, dans la liste des types de projet, développez le nœud Visual Basic ou le nœud Visual C#.

  • Sélectionnez le nœud Windows dans la liste des types de projet.

  • Dans le volet Modèles , sélectionnez Bibliothèque de classes.

  • Saisissez le nom CitationWS, puis cliquez sur OK.

  • Dans Explorateur de solutions, cliquez avec le bouton droit sur Class1.vb ou Class1.cs, puis cliquez sur Renommer.

  • Modifier le nom en Amazon.vb ou en Amazon.cs.

  • Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud de projet CitationWS, puis cliquez sur Ajouter une référence Web.

  • Dans la boîte de dialogue Ajouter une référence Web, saisissez l'adresse suivante dans le champ URL, puis cliquez sur OK : http://webservices.amazon.com/AWSECommerceService/2006-05-17/AWSECommerceService.wsdl

  • Une fois que la description du service Web s'affiche, tapez AmazonECS4 dans la zone Nom de référence Web, puis cliquez sur Ajouter une référence pour terminer le processus et créer la classe de proxy locale.

Maintenant que le projet de bibliothèque de classes est configuré, remplacez le fichier de classe Amazon vide par le code répertorié ci-dessous. Le code de base est semblable au code utilisé dans le gestionnaire d'événements Click du bouton btnGetBookInfo de la solution Word 2003. Cependant, il y a des modifications :

  • La classe a un nouvel événement Status défini. Le code élève cet événement pour permettre à l'interface utilisateur de proposer à l'utilisateur des informations sur la progression, si on le souhaite. Dans l'exemple précédent, le code a mis à jour directement un contrôle Label.

  • Etant donné que le code ne peut pas mettre à jour directement les contrôles, il lui faut une façon de transmettre les données de résultats à l'appelant. Il en existe plusieurs. Dans cet exemple, le code utilise une classe imbriquée appelée BookData. La classe BookData est la valeur de retour d'une nouvelle méthode, GetBookInfo, qui accepte un ISBN sous forme de chaîne comme entrée. Dans cette méthode, le code crée une instance locale de BookData, stocke l'ISBN dans l'instance, puis configure l'appel de service Web exactement comme dans l'exemple fondé sur Word 2003. Lorsque l'appel de service Web prend fin, le code stocke les données de retour dans les champs de l'instance BookData au lieu de mettre à jour l'interface utilisateur directement, parce que le code n'a pas accès à cette dernière.

  • Le code lance des exceptions dans les cas où, avec la solution Word 2003, des appels d'affichage d'une zone de message étaient utilisés.

  • Au lieu d'intercepter des exceptions, le code permet au runtime de relancer des exceptions vers l'appelant.

        Visual Basic

        Public Class Amazon
        Public Event Status(ByVal Message As String)

        Private Const AWS_Access_KeyId As String = "<i>Your
        Access Key ID</i>"
        Private aws As AmazonECS4.AWSECommerceService = Nothing

        ' Nested class used to return search results.
        Public Class BookData
        Public ISBN As String
        Public Author As String
        Public Publisher As String
        Public Title As String
        Public YearPublished As String
        End Class

        Public Function GetBookInfo(ByVal ISBN As String) As BookData
        If ISBN Is Nothing OrElse ISBN = String.Empty Then
        Throw New Exception("Please provide a valid ISBN.")
        Else
        RaiseEvent Status("Preparing
        ...")

        If aws Is Nothing Then
        aws = New AmazonECS4.AWSECommerceService()
        End If

        ' Create an instance of the return value.
        Dim localBookData As New BookData
        localBookData.ISBN = ISBN.Trim()

        ' Define a specific item to look up.
        Dim ilr As New AmazonECS4.ItemLookupRequest
        ilr.ItemId = New String() {localBookData.ISBN}
        ilr.IdType = AmazonECS4.ItemLookupRequestIdType.ASIN
        ilr.IdTypeSpecified = True
        ilr.ResponseGroup = New String() {"Medium"}

        Dim il As New AmazonECS4.ItemLookup()
        With il
        .AWSAccessKeyId = AWS_Access_KeyId
        .Request = New AmazonECS4.ItemLookupRequest() {ilr}
        End With

        RaiseEvent Status("Making
        Request ...")
        ' Make the request from the Web service.
        Dim ilresp As AmazonECS4.ItemLookupResponse = aws.ItemLookup(il)
        RaiseEvent Status("Processing
        Response ...")

        Dim resultsItems As AmazonECS4.Items = ilresp.Items(0)
        Dim mainItem As AmazonECS4.Item = resultsItems.Item(0)
        With mainItem.ItemAttributes
        localBookData.Author = .Author(0)
        localBookData.YearPublished = _
        CDate(.PublicationDate).Year.ToString()
        localBookData.Publisher = .Publisher
        localBookData.Title = .Title
        End With

        RaiseEvent Status("Last
        Lookup Complete")

        Return localBookData
        End If
        End Function
        End Class
      
        C#

        public class Amazon
        {
        public delegate void StatusEventHandler(string Message);
        public event StatusEventHandler Status;

        private const string AWS_Access_KeyId = "<i>Your Access Key ID</i>";
        private AmazonECS4.AWSECommerceService aws = null;

        // Nested class used to return search results.
        public class BookData
        {
        public string ISBN;
        public string Author;
        public string Publisher;
        public string Title;
        public string YearPublished;
        }

        public BookData GetBookInfo(string ISBN)
        {
        if (ISBN == null || ISBN == string.Empty)
        {
        throw new Exception("Please provide a valid ISBN.");
        }
        else
        {
        if (Status != null)
        {
        Status("Preparing ...");
        }
        if (aws == null)
        {
        aws = new AmazonECS4.AWSECommerceService();
        }

        // Create an instance of the return value.
        BookData localBookData = new BookData();
        localBookData.ISBN = ISBN.Trim();

        // Define a specific item to look up.
        AmazonECS4.ItemLookupRequest ilr =
        new AmazonECS4.ItemLookupRequest();
        ilr.ItemId = new string[] { localBookData.ISBN };
        ilr.IdType = AmazonECS4.ItemLookupRequestIdType.ASIN;
        ilr.IdTypeSpecified = true;
        ilr.ResponseGroup = new string[] { "Medium" };

        AmazonECS4.ItemLookup il = new AmazonECS4.ItemLookup();
        il.AWSAccessKeyId = AWS_Access_KeyId;
        il.Request = new AmazonECS4.ItemLookupRequest[] { ilr };

        // Make the request from the Web service.
        if (Status != null)
        {
        Status("Making Request ...");
        }
        AmazonECS4.ItemLookupResponse ilresp = aws.ItemLookup(il);
        if (Status != null)
        {
        Status("Processing Response ...");
        }

        AmazonECS4.Items resultsItems = ilresp.Items[0];
        AmazonECS4.Item mainItem = resultsItems.Item[0];
        localBookData.Author = mainItem.ItemAttributes.Author[0];
        localBookData.YearPublished =
        System.Convert.ToDateTime(
        mainItem.ItemAttributes.PublicationDate).Year.ToString();
        localBookData.Publisher = mainItem.ItemAttributes.Publisher;
        localBookData.Title = mainItem.ItemAttributes.Title;
        if (Status != null)
        {
        Status("Last Lookup Complete");
        }
        return localBookData;
        }
        }
        }
      

Cette nouvelle conception vous permet de réutiliser le service Web sans vous préoccuper du type d'application d'hébergement. Si vous le souhaitez, nous pouvons tout compiler maintenant. En l'absence d'erreurs, passez à la section suivante.

Associer les choses

Comme nous l'avons vu, Visual Studio 2005 Tools pour Office Second Edition fournit des compléments d'application gérés tenant lieu de nouvelles fonctionnalités. Utilisez un projet de complément Word 2007 pour regrouper les choses.

Pour associer les projets

  • Dans le menu Fichier, pointez sur Ajouter puis cliquez sur Nouveau projet .

  • Dans la boîte de dialogue Nouveau projet, dans la liste des types de projet, développez le nœud Visual Basic ou le nœud Visual C#.

  • Développez le nœud Office, puis sélectionnez le nœud des compléments 2007.

  • Dans le volet Modèles, sélectionnez Word Add-in (Complément Word).

  • Saisissez le nom CitationsAddinWord, puis cliquez sur OK.

  • Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud de projet CitationsAddinWord, puis cliquez sur Ajouter une référence.

  • Cliquez sur l'onglet Projets, sélectionnez le projet CitationsUC, puis cliquez sur OK.

  • Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud de projet CitationsUC, puis cliquez sur Ajouter une référence.

  • Cliquez sur l'onglet Projets, sélectionnez le projet CitationsWS, puis cliquez sur OK.

  • Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud de projet CitationsAddinWord, puis cliquez sur Définir comme projet de démarrage.

Etant donné que les applications du système Office 2007 qui prennent en charge les volets de tâches de niveau application prennent en charge plusieurs volets de tâches de niveau application actifs en même temps, le code permettant d'en créer un est légèrement différent du code utilisé pour créer des volets de tâches Actions de document. Le code suivant montre comment ajouter le contrôle utilisateur (créé précédemment) à un volet de tâches de niveau application.

        Visual Basic

        Imports Microsoft.Office.Tools

        Public Class ThisAddIn
        Private WithEvents citationsUI As CitationsUC.Citation
        Private citationTaskPane As CustomTaskPane

        Private Sub ThisAddIn_Startup(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles Me.Startup

        citationsUI = New CitationsUC.Citation
        citationTaskPane = CustomTaskPanes.Add( _
        citationsUI, "Citations")

        citationTaskPane.Visible = True
        End Sub

        Private Sub ThisAddIn_Shutdown(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles Me.Shutdown

        CustomTaskPanes.Remove(citationTaskPane)
        End Sub
        End Class
      
        C#

        using Microsoft.Office.Tools;

        namespace CitationsAddinWordCS
        {
        public partial class ThisAddIn
        {
        private CitationsUC.Citation citationsUI;
        private CustomTaskPane citationTaskPane;

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
        citationsUI = new CitationsUC.Citation();
        citationTaskPane = CustomTaskPanes.Add(citationsUI, "Citations");

        citationTaskPane.Visible = true;
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        CustomTaskPanes.Remove(citationTaskPane);
        }
        }
        }
      

Quelques points méritent d'être notés :

  • Il existe une collection de volets de tâches personnalisés. Une application hôte peut afficher plusieurs volets de tâches à la fois.

  • Vous devez rendre visible le volet de tâches. Cependant, cette opération ne doit s'effectuer que pendant les tests. Dans le système Office 2007, les éléments d'interface utilisateur tels que volets de tâches ne doivent jamais apparaître. La meilleure pratique est d'ajouter un élément d'interface utilisateur au ruban pour permettre à l'utilisateur de rendre visible le volet de tâches Citations.

  • Etant donné que le volet de tâches personnalisé n'est plus associé à un document particulier, il doit être supprimé lorsque le complément est déchargé. Naturellement, si l'hôte est déchargé ce n'est pas très important. Cependant, l'utilisateur peut décharger le complément à tout moment, et vos éléments d'interface utilisateur ne doivent pas rester derrière.

Vous avez écrit du code permettant de charger le contrôle utilisateur. Maintenant, vous pouvez écrire le code permettant de charger les données de livre dans le contrôle utilisateur issu du service Web. Après quoi, le morceau de code suivant que vous devez écrire est le code permettant de placer des données de livre dans le document actif. Ensuite, vous devez vous employer à intégrer votre complément au ruban pour lui apporter la touche finale qui le rendra adéquat.

La connexion du contrôle utilisateur au service Web ne nécessite qu'une petite quantité de code. Vous avez déjà défini la référence à l'assembly de service Web. Vous devez définir deux variables de niveau classe : la première concerne le service Web, et la seconde l'ISBN que l'utilisateur a entré. De même, vous devez définir deux gestionnaires d'événements : L'un concerne l'événement Click de l'objet btnGetBookInfo et l'autre l'événement Status de la classe Amazon. Le listing suivant présente la classe Citation.

        Visual Basic

        Public Class Citation
        Private WithEvents amznWS As CitationsWS.Amazon
        Private savedISBN As String

        Private Sub btnGetBookInfo_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles btnGetBookInfo.Click

        If amznWS Is Nothing Then
        amznWS = New CitationsWS.Amazon
        End If

        Dim bookInfo As CitationsWS.Amazon.BookData = Nothing
        Try
        bookInfo = amznWS.GetBookInfo(txtISBN.Text)

        Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.Critical, ex.Source)
        lblGetBookInfoStatus.Text = "Error on last request. Try
        again"
        Return
        End Try

        If bookInfo IsNot Nothing Then
        With bookInfo
        savedISBN = .ISBN
        lblAuthor.Text = .Author
        lblPublisher.Text = .Publisher
        lblTitle.Text = .Title
        lblYearPublished.Text = .YearPublished
        End With
        lblGetBookInfoStatus.Text = "Ready"
        End If
        End Sub

        Private Sub amznWS_Status(ByVal Message As String) Handles amznWS.Status
        lblGetBookInfoStatus.Text = Message
        lblGetBookInfoStatus.Refresh()
        End Sub
        End Class
      
        C#

        public partial class Citation : UserControl
        {

        private CitationsWS.Amazon amznWS;
        private string savedISBN;

        public Citation()
        {
        InitializeComponent();
        }

        private void btnGetBookInfo_Click(object sender, EventArgs e)
        {
        if ((amznWS == null))
        {
        amznWS = new CitationsWS.Amazon();
        amznWS.Status +=
        new CitationsWS.Amazon.StatusEventHandler(amznWS_Status);
        }

        CitationsWS.Amazon.BookData bookInfo = null;
        try
        {
        bookInfo = amznWS.GetBookInfo(txtISBN.Text);
        }
        catch (Exception ex)
        {
        MessageBox.Show(ex.Message, ex.Source,
        MessageBoxButtons.OK, MessageBoxIcon.Stop);
        lblGetBookInfoStatus.Text = "Error on last request. Try again";
        return;
        }

        if (bookInfo != null)
        {
        savedISBN = bookInfo.ISBN;
        lblAuthor.Text = bookInfo.Author;
        lblPublisher.Text = bookInfo.Publisher;
        lblTitle.Text = bookInfo.Title;
        lblYearPublished.Text = bookInfo.YearPublished;
        lblGetBookInfoStatus.Text = "Ready";
        }
        }

        void amznWS_Status(string Message)
        {
        lblGetBookInfoStatus.Text = Message;
        lblGetBookInfoStatus.Refresh();
        }
        }
      

Il faut un peu plus de travail pour introduire les informations de citation dans Word 2007 que dans Word 2003. En fait, étant donné que vous avez factorisé la conception, le contrôle utilisateur ne doit pas être tributaire d'une exécution interne à Word, ni à aucune autre application Office. A cet effet, l'une des solutions est d'exposer les données issues des étiquettes comme des propriétés du contrôle. En outre, vous devez définir un événement de sorte que tout hôte utilisant le contrôle utilisateur puisse savoir quand un utilisateur clique sur le bouton btnPutInfoInDoc.

Remarque :

Vous pouvez exposer le bouton en faisant passer sa visibilité de Friend (ami) ou internal (interne) à Public (publique). Cependant, cela exposera toute l'encapsulation de contrôle et rupture.

Tout d'abord, encapsulez la propriété Text de tous les contrôles Label pertinents, pour que les données soient accessibles à partir de l'application hôte. Ensuite, définissez un événement qui signale le complément d'hôte pour lequel l'utilisateur veut que les données soient transférées du contrôle utilisateur vers le document actif. Enfin, écrivez le code d'écriture qui élève l'événement dans le gestionnaire d'événements Click du bouton btnPutInfoInDoc. Le code suivant présente ces modifications dans la classe Citation.

        Visual Basic

        Public Class Citation
        Private WithEvents amznWS As CitationsWS.Amazon
        Private savedISBN As String
        Public Event PutInfo As System.EventHandler

        Private Sub btnPutInfoInDoc_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles btnPutInfoInDoc.Click

        RaiseEvent PutInfo(Me, EventArgs.Empty)
        End Sub

        Public ReadOnly Property Author() As String
        Get
        Return lblAuthor.Text
        End Get
        End Property
        Public ReadOnly Property ISBN() As String
        Get
        Return savedISBN
        End Get
        End Property
        Public ReadOnly Property Publisher() As String
        Get
        Return lblPublisher.Text
        End Get
        End Property
        Public ReadOnly Property Title() As String
        Get
        Return lblTitle.Text
        End Get
        End Property
        Public ReadOnly Property YearPublished() As String
        Get
        Return lblYearPublished.Text
        End Get
        End Property
        End Class
      
        C#

        public partial class Citation : UserControl
        {
        private CitationsWSCS.Amazon amznWS;
        private string savedISBN;
        public event System.EventHandler PutInfo;

        private void btnPutInfoInDoc_Click(object sender, EventArgs e)
        {
        PutInfo(this, EventArgs.Empty);
        }

        public string Author
        {
        get { return lblAuthor.Text; }
        }
        public string ISBN
        {
        get { return savedISBN; }
        }
        public string Publisher
        {
        get { return lblPublisher.Text; }
        }
        public string Title
        {
        get { return lblTitle.Text; }
        }
        public string YearPublished
        {
        get { return lblYearPublished.Text; }
        }
        }
      

Ensuite, ajoutez un gestionnaire d'événements à la classe ThisAddIn qui intercepte l'événement PutInfo et charge la citation dans le document Word actif. Dans le gestionnaire d'événements, extrayez les données du contrôle utilisateur et placez-les dans un tableau de chaînes. Transmettez alors le tableau à la méthode String.Format, qui crée la chaîne de citation. Enfin, insérez la citation dans le document actif, exactement comme dans la solution Word 2003.

        Visual Basic


        Public Class ThisAddIn
        Private Sub citationsUI_PutInfo(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles citationsUI.PutInfo

        Dim data(4) As String
        With citationsUI
        data(0) = .Title
        data(1) = .Author
        data(2) = .YearPublished
        data(3) = .Publisher
        data(4) = .ISBN
        End With

        Dim citation As String = _
        String.Format("{0} by {1}.
        Copyright {2} {3}, {4}", Data)

        Me.Application.ActiveDocument.Range.InsertAfter(citation)
        End Sub
        End Class
      
        C#

        public partial class ThisAddIn
        {
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
        citationsUI = new CitationsUCCS.Citation();
        citationTaskPane = CustomTaskPanes.Add(citationsUI, "Citations");
        citationsUI.PutInfo += new EventHandler(citationsUI_PutInfo);
        citationTaskPane.Visible = true;
        }

        void citationsUI_PutInfo(object sender, EventArgs e)
        {
        string[] data = new string[5];
        data[0] = citationsUI.Title;
        data[1] = citationsUI.Author;
        data[2] = citationsUI.YearPublished;
        data[3] = citationsUI.Publisher;
        data[4] = citationsUI.ISBN;
        string citation =
        string.Format("{0} by {1}. Copyright {2} {3}, {4}", data);
        object missingValue = System.Reflection.Missing.Value;
        this.Application.ActiveDocument.Range(
        ref missingValue, ref missingValue).InsertAfter(citation);
        }
        }
      

Démarrez la solution et vérifiez si tout fonctionne. Le résultat est le même qu'avant ; cependant, vous avez maintenant une conception beaucoup plus factorisée et professionnelle, facilitant considérablement la réutilisation des composants dans d'autres applications hôtes Office ou même dans d'autres applications gérées. Cependant, vous n'avez pas encore terminé.

Ajout de la prise en charge du ruban

Actuellement, le complément rend visible le volet de tâches Citations au démarrage. Celui-ci fonctionne, jusqu'à ce que l'utilisateur ferme le volet de tâches. Comment l'utilisateur rétablit-il le volet de tâches ? Ce type de comportement va également à l'encontre des normes de conception fournies par l'équipe Office. Vous devez ajouter un bouton d'un certain type au ruban pour permettre à l'utilisateur de contrôler la visibilité du volet de tâches.

Pour ajouter la prise en charge du ruban, exécutez les étapes de base suivantes :

  • Ajoutez un bouton d'activation à un onglet Ruban existant (l'onglet Insérer semble adéquat).

  • Ajoutez un rappel qui est activé lorsque l'utilisateur clique sur le bouton.

  • Modifiez l'état visible du volet de tâches lorsque le rappel a lieu.

  • Assurez-vous que le bouton affiche l'état correct du volet de tâches si l'utilisateur le ferme à partir du volet de tâches et non à partir du bouton.

Visual Studio 2005 Tools pour Office Second Edition offre une prise en charge de la programmation du ruban.

Pour ajouter la prise en charge du ruban à votre projet

  • Dans Explorateur de solutions, sélectionnez le projet de complément Word.

  • Dans le menu Projet, cliquez sur Ajouter un nouvel élément.

  • Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Ribbon support (Prise en charge de ruban).

  • Modifiez le nom de fichier en RibbonCode.vb ou RibbonCode.cs, puis cliquez sur Ajouter.

Visual Studio ajoute deux nouveaux éléments au projet : un fichier source RibbonCode et Ribboncode.xml, qui est défini pour être compilé en tant que ressource intégrée. Vous devez mettre à jour le fichier XML pour que le nouveau bouton d'activation apparaisse correctement sur l'onglet Insérer. Pour cela, ouvrez Ribboncode.xml et remplacez le XML par défaut par le XML suivant.

        Xml

        <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui"
        onLoad="OnLoad">
        <ribbon>
        <tabs>
        <tab idMso="TabInsert">
        <group id="amznCitation"
        label="Citation">
        <toggleButton id="showCitationActionPane"
        size="large"
        label="Citation from WS"
        screentip="Insert a citation from Amazon"
        onAction="showCitationActionPane_onAction"
        imageMso="CitationInsert" />
        </group>
        </tab>
        </tabs>
        </ribbon>
        </customUI>
      

Le XML indique au ruban d'ajouter un nouveau groupe à l'onglet Insérer. En outre, le XML déclare que le bouton doit être un grand bouton d'activation, avoir une étiquette et une info-bulle, utiliser une image intégrée et appeler une méthode nommée showCitationActionPane_onAction lorsque l'utilisateur clique sur le bouton.

Vous pouvez maintenant modifier la classe contenant le code de prise en charge de ruban. Retirez les commentaires de la section de code au-dessous des instructions Imports ou using. Ce code indique à l'application hôte Office que votre complément veut fournir des gestionnaires personnalisés destinés au ruban. Le code effectue cette implémentation sous forme de deux classes. La première section de code est une classe partielle qui est liée à votre classe de complément. La deuxième classe, RibbonCode, fournit les points de rappel nécessaires pour fournir le XML au ruban à la demande, et pour traiter les événements de ruban. Après avoir retiré les commentaires du code, faites passer le nom de la méthode de rappel par défaut de OnToggleButton1 à showCitationActionPane_onAction. La méthode se trouve dans une région étiquetée Ribbon Callbacks (Rappels de ruban). Ensuite, vous pouvez essayer vos modifications et vérifier si le bouton d'activation s'affiche correctement sur l'onglet Insérer. En outre, si vous cliquez sur le bouton, vous devez recevoir des zones de message vous indiquant l'état du bouton d'activation.

Maintenant que l'infrastructure de base est en place, vous pouvez ajouter le code nécessaire pour modifier l'état de visibilité du volet de tâches, en fonction de l'état du bouton d'activation. Le problème est que le code qui traite le rappel appartient à une classe différente de la classe de complément, qui contient la référence au volet de tâches. Pour traiter le rappel, la classe RibbonCode a besoin d'une référence à la classe de complément. Une façon facile de la lui procurer est de modifier la classe RibbonCode de manière à la doter d'un constructeur acceptant une référence à la classe de complément. Utilisez le code suivant comme exemple.

          Visual Basic

          Public Sub New(ByVal Parent As ThisAddIn)
          parentAddIn = Parent
          End Sub
        
          C#

          public RibbonCode(ThisAddIn Parent)
          {
          parentAddIn = Parent;
          }
        

Ajoutez une variable de niveau classe nommée m_Parent du type ThisAddin. Ensuite, retirez les commentaires et modifiez la méthode RequestService qui crée une instance de la classe RibbonCode de sorte qu'elle utilise ce nouveau constructeur. Le code suivant présente les modifications que vous avez besoin d'effectuer.

          Visual Basic

          Protected Overrides Function RequestService( _
          ByVal serviceGuid As Guid) As Object

          If serviceGuid = GetType(Office.IRibbonExtensibility).GUID Then
          If ribbon Is Nothing Then
          ribbon = New RibbonCode(Me)
          End If
          Return ribbon
          End If

          Return MyBase.RequestService(serviceGuid)
          End Function
        
          C#

          protected override object RequestService(Guid serviceGuid)
          {
          if (serviceGuid == typeof(Office.IRibbonExtensibility).GUID)
          {
          if (ribbon == null)
          ribbon = new RibbonCode(this);
          return ribbon;
          }

          return base.RequestService(serviceGuid);
          }
        

Vous pouvez désormais modifier la méthode de rappel OnAction du bouton d'activation pour modifier l'état de visibilité du volet de tâches. Remplacez la procédure showCitationActionPane_onAction existante par le code suivant.

          Visual Basic

          Public Sub showCitationActionPane_onAction( _
          ByVal control As Office.IRibbonControl, _
          ByVal isPressed As Boolean)

          Me.parentAddIn.citationTaskPane.Visible = isPressed
          End Sub
        
          C#

          public void showCitationActionPane_onAction(
          Office.IRibbonControl control, bool isPressed)
          {
          this.parentAddIn.citationTaskPane.Visible = isPressed;
          }
        

Cependant, pour que ce code fonctionne, vous devez modifier la visibilité du volet de tâches dans la classe ThisAddin. Ouvrez le fichier de classe ThisAddin, et faites passer la visibilité de la variable citationTaskPane de private (privé) à Friend (ami) (si vous utilisez Visual Basic), ou internal (interne) (si vous utilisez Visual C#). Vous devez également supprimer la ligne de code de la procédure ThisAddIn_Startup qui rend le volet de tâches visible par défaut. Après avoir effectué ces deux opérations, faites un essai. Vous devez être capable de cliquer sur le bouton pour modifier la visibilité du volet de tâches.

Vous avez presque terminé. Il reste un problème à résoudre : Si un utilisateur affiche le volet de tâches et utilise ensuite le X situé dans le coin supérieur du volet de tâches pour le fermer, l'état du bouton d'activation n'est pas modifié. Pour y remédier, vous devez ajouter du code permettant de déterminer l'état correct du bouton d'activation. Cela nécessite trois modifications. Tout d'abord, ajoutez une procédure de rappel à la classe RibbonCode que le ruban utilisera pour consulter l'état du bouton d'activation. Ajoutez le code suivant à la classe RibbonCode.

          Visual Basic

          Public Function showCitationActionPane_getPressed( _
          ByVal control As Office.IRibbonControl) As Boolean

          Return Me.parentAddIn.citationTaskPane.Visible
          End Function
        
          C#

          public bool showCitationActionPane_getPressed(
          Office.IRibbonControl control)
          {
          return this.parentAddIn.citationTaskPane.Visible;
          }
        

Ensuite, ajoutez la nouvelle procédure de rappel au ruban. Pour cela, ajoutez un attribut supplémentaire au XML existant. Utilisez le XML suivant comme guide.

          Xml

          <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui"
          onLoad="OnLoad">
          <ribbon>
          <tabs>
          <tab idMso="TabInsert">
          <group id="amznCitation"
          label="Citation">
          <toggleButton id="showCitationActionPane"
          size="large"
          label="Citation from WS"
          screentip="Insert a citation from Amazon"
          onAction="showCitationActionPane_onAction"
          getPressed="showCitationActionPane_getPressed"
          imageMso="CitationInsert" />
          </group>
          </tab>
          </tabs>
          </ribbon>
          </customUI>
        

Enfin, ajoutez du code indiquant au ruban de vérifier son état. Pour cela, fournissez un gestionnaire d'événements destiné à l'événement VisibleChanged du volet de tâches. Dans ce gestionnaire d'événements, le code doit invalider le bouton d'activation, qui indique lui-même au ruban d'appeler la procédure de rappel précédemment ajoutée.

Tout d'abord, ajoutez le gestionnaire d'événements suivant à la classe RibbonCode.

          Visual Basic
          Public Sub OnVisibleChanged( _
          ByVal sender As Object, ByVal e As EventArgs)

          Me.ribbon.InvalidateControl("showCitationActionPane")
          End Sub
        
          C#
          public void OnVisibleChanged(object sender, EventArgs e)
          {
          this.ribbon.InvalidateControl("showCitationActionPane");
          }
        

Le code que vous venez d'ajouter invalide le bouton d'activation en transmettant l'ID de ce dernier à la méthode InvalidateControl. Ensuite, modifiez la procédure ThisAddIn_Startup pour associer ce gestionnaire d'événements nouvellement ajouté.

          Visual Basic
          Private Sub ThisAddIn_Startup(ByVal sender As Object, _
          ByVal e As System.EventArgs) Handles Me.Startup
          citationsUI = New CitationsUC.Citation
          citationTaskPane = CustomTaskPanes.Add( _
          citationsUI, "Citations")

          AddHandler citationTaskPane.VisibleChanged, _
          AddressOf ribbon.OnVisibleChanged
          End Sub
        
          C#
          private void ThisAddIn_Startup(object sender, System.EventArgs e)
          {
          citationsUI = new CitationsUCCS.Citation();
          citationTaskPane = CustomTaskPanes.Add(citationsUI, "Citations");
          citationsUI.PutInfo += new EventHandler(citationsUI_PutInfo);
          citationTaskPane.VisibleChanged +=
          new EventHandler(ribbon.OnVisibleChanged);
          }
        

Maintenant, lorsque l'hôte charge le code de prise en charge de ruban, la classe associe l'événement VisibleChanged. Si l'utilisateur ferme le volet de tâches, l'événement VisibleChanged est élevé, et le code invalide donc le bouton d'activation. Le ruban appelle alors la procédure showCitationActionPane_getPressed pour extraire son état enfoncé actuel. Faites un essai et voyez si cela fonctionne.

Cela fonctionne, mais cela pourrait être mieux

Le complément fonctionne avec le ruban. Cependant, la solution n'est pas factorisée comme le reste du complément. Le ruban est lié à une application hôte particulière. Vous ne pouvez donc pas réutiliser le code de ruban dans une autre application hôte sans modifier la mise en œuvre. Vous devez déplacer le code de Ruban et le XML vers un assembly distinct. Le code de ruban a besoin de pouvoir communiquer avec tout hôte utilisant le volet de tâches Citations, sans savoir quel complément l'héberge. Pour que cela fonctionne, définissez une interface que le complément pourra implémenter dans le fichier source RibbonCode.

          Visual Basic
          ' Add to the top of the source file with the other Imports statements.
          Imports Microsoft.Office.Tools

          Public Interface ICitationParent
          ReadOnly Property CitationTaskPane() As CustomTaskPane
          End Interface
        
          C#
          // Add to the top of the source file with the other using statements.
          using Microsoft.Office.Tools;

          namespace CitationsAddinWordCS
          {
          public interface ICitationParent
          {
          CustomTaskPane CitationTaskPane
          { get; }
          }
          }
        

La classe ThisAddin a besoin d'implémenter cette interface. En outre, vous devez supprimer le code que vous avez ajouté à la procédure ThisAddIn_Startup qui associe l'événement de VisibleChanged. Vous devez également refaire passer le paramètre de visibilité CustomTaskPane à private (privé) et modifier son nom. Le code suivant présente les parties pertinentes de la classe mise à jour.

          Visual Basic
          Public Class ThisAddIn
          Implements ICitationParent

          Private WithEvents citationsUI As CitationsUC.Citation
          Private m_citationTaskPane As CustomTaskPane

          Private Sub ThisAddIn_Startup(ByVal sender As Object, _
          ByVal e As System.EventArgs) Handles Me.Startup
          citationsUI = New CitationsUC.Citation
          m_citationTaskPane = CustomTaskPanes.Add( _
          citationsUI, "Citations")
          ' AddHandler call removed.
          End Sub

          Private Sub ThisAddIn_Shutdown(ByVal sender As Object, _
          ByVal e As System.EventArgs) Handles Me.Shutdown

          CustomTaskPanes.Remove(m_citationTaskPane)
          End Sub

          Public ReadOnly Property CitationTaskPane() As _
          CustomTaskPane Implements ICitationParent.CitationTaskPane

          Get
          Return m_citationTaskPane
          End Get
          End Property
          End Class
        
          C#
          public partial class ThisAddIn : ICitationParent
          {
          private CitationsUCCS.Citation citationsUI;
          private CustomTaskPane m_citationTaskPane;

          public CustomTaskPane CitationTaskPane
          {
          get { return m_citationTaskPane; }
          }

          private void ThisAddIn_Startup(object sender, System.EventArgs e)
          {
          citationsUI = new CitationsUCCS.Citation();
          m_citationTaskPane = CustomTaskPanes.Add(citationsUI, "Citations");
          citationsUI.PutInfo += new EventHandler(citationsUI_PutInfo);
          // Removed event handler for citationTaskPane.VisibleChanged.
          }

          private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
          {
          CustomTaskPanes.Remove(m_citationTaskPane);
          }
          }
        

Vous avez besoin d'apporter un ensemble de modifications à la classe RibbonCode et la méthode RequestService, en plus de celles que vous venez d'apporter à la classe ThisAddin. La première modification à effectuer porte sur le type de la variable de niveau classe parentAddIn, qui doit passer de ThisAddIn à ICitationParent. Supprimez ensuite le constructeur personnalisé que vous avez ajouté précédemment.

L'un des problèmes entourant la façon dont un hôte Office charge un complément est qu'Office raccorde le code de ruban avant la fin de la méthode Startup. Cela empêche le code de ruban d'ajouter un gestionnaire d'événements pendant la construction : le volet de tâches n'existe pas encore. Ajoutez plutôt une propriété permettant au complément de définir le parent de code de ruban pendant la méthode Startup. En outre, étant donné que vous avez supprimé le constructeur personnalisé, vous devez réparer la méthode RequestService pour utiliser le constructeur par défaut de la classe RibbonCode. Le code suivant présente la nouvelle propriété que vous avez besoin d'ajouter à la classe RibbonCode. L'accesseur Set de cette propriété ajoute le gestionnaire d'événements lié à l'événement VisibleChanged du volet de tâches.

Remarque :

Si vous utilisez C#, vous devez réparer une erreur de compilation de mise en majuscule de showCitationActionPane_onAction et showCitationActionPane_getPressed liée au nom d'objet CitationTaskPane. Il est répertorié comme citationTaskPane et doit impérativement être CitationTaskPane.

          Visual Basic
          Public Property Parent() As ICitationParent
          Get
          Return m_Parent
          End Get
          Set(ByVal value
          As ICitationParent) parentAddIn = value AddHandler parentAddIn.CitationTaskPane.VisibleChanged,
          _ AddressOf Me.OnVisibleChanged End Set End Property
        
          C#

          public ICitationParent Parent { get { return m_Parent; } set { parentAddIn = value;
          parentAddIn.CitationTaskPane.VisibleChanged += new EventHandler(this.OnVisibleChanged);
          } }
        

Pour terminer, ajoutez la ligne suivante de code comme dernière ligne de la procédure ThisAddIn_Startup.

          Visual Basic

          Me.ribbon.Parent = Me
        
          C#

          this.ribbon.Parent = this;
        

A supposer que tout se compile, vous pouvez désormais factoriser le code de ruban et le XML dans leur propre assembly de bibliothèque de classes. Référencez ce nouvel assembly à partir du complément Word et déplacez le code.

Pour factoriser le code de ruban et le XML

  • Dans le menu Fichier, pointez sur Ajouter puis cliquez sur Nouveau projet .

  • Dans la boîte de dialogue Nouveau projet, dans la liste des types de projet, développez le nœud Visual Basic ou le nœud Visual C#.

  • Sélectionnez le nœud Windows.

  • Dans le volet Modèles , sélectionnez Bibliothèque de classes.

  • Saisissez le nom CitationsRibbon, puis cliquez sur OK.

  • Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud de projet CitationsAddinWord, puis cliquez sur Ajouter une référence.

  • Cliquez sur l'onglet Projets, sélectionnez le projet CitationsRibbon, puis cliquez sur OK.

  • Dans Explorateur de solutions, dans le projet CitationsRibbon, cliquez avec le bouton droit sur Class1.vb ou Class1.cs, puis cliquez sur Supprimer. Cliquez sur OK pour confirmer la suppression.

  • Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud de projet CitationsRibbon, pointez sur Ajouter, puis cliquez sur Elément existant .

  • Dans la boîte de dialogue Ajouter un élément existant, naviguez vers le dossier contenant le fichier RibbonCode.vb ou RibbonCode.cs, et le fichier RibbonCode.xml. Ajustez la boîte de dialogue pour qu'elle affiche tous les fichiers, sélectionnez les deux fichiers, puis cliquez sur Ajouter.

  • Dans Explorateur de solutions, sélectionnez le fichier RibbonCode.xml. Ensuite, en utilisant la fenêtre Propriétés, faites passer la propriété Action de génération à Ressource incorporée.

  • Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud de projet CitationsRibbon, puis cliquez sur Ajouter une référence.

  • Cliquez sur l'onglet .NET, puis sélectionnez les assemblys suivants (appuyez sur CTRL pour en sélectionner plusieurs) :

    • Microsoft.Office.Tools.Common

    • Microsoft.Office.Tools.Common2007

    • Microsoft.VisualStudio.Tools.Applications.Runtime

  • Cliquez sur OK.

  • Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud de projet CitationsRibbon, puis cliquez sur Ajouter une référence.

  • Cliquez sur l'onglet COM, sélectionnez Bibliothèque d'objets Microsoft Office 12.0 , puis cliquez sur OK.

  • Dans Explorateur de solutions, dans le projet CitationsAddInWord, cliquez avec le bouton droit sur RibbonCode.xml, puis cliquez sur Supprimer. Cliquez sur OK pour confirmer la suppression.

Dans le projet CitationsRibbon, ouvrez le fichier source RibbonCode.vb ou RibbonCode.cs. Supprimez l'instruction Imports ou using de System.Windows.Forms. Vous devez également supprimer tout le code relatif à la classe partielle ThisAddIn. Si vous utilisez C#, faites passer l'espace de nom de CitationsAddinWord à CitationsRibbon. De retour dans le projet CitationsAddInWord, ouvrez le fichier source RibbonCode. Supprimez la classe RibbonCode et la définition d'interface ICitationParent. Ajoutez ensuite l'instruction Imports ou using suivante tout en haut dans le fichier de classe RibbonCode et le fichier de classe ThisAddin, tous les deux dans le projet CitationsAddInWord.

          Visual Basic

          Imports CitationsRibbon
        
          C#

          using CitationsRibbon;
        

La dernière chose que vous avez à faire est de modifier la méthode GetCustomUI de la classe RibbonCode dans votre projet CitationsRibbon pour transmettre le nom entièrement qualifié correct de la ressource XML dans l'appel à GetResourceText. A ce stade, vous pouvez compiler et tester. Maintenant que vous avez entièrement factorisé la conception, vous pouvez modifier le complément pour un autre hôte sans refaire une bonne partie de votre travail.

Conclusion

La capacité de créer des compléments gérés et des volets de tâches de niveau application ouvre littéralement les portes sur un monde de nouvelles possibilités en matière de solutions générées élaborées sur des applications Microsoft Office. Moyennant un effort réduit, vous pouvez factoriser vos conceptions pour une plus grande réutilisation dans d'autres solutions.

À propos de l'auteur

Brian A. Randell est consultant senior chez MCW Technologies, LLC. Il passe son temps à enseigner les technologies Microsoft aux développeurs, travaillant sur des technologies nouvelles et émergeantes telles que le système Microsoft Office 2007, Visual Studio 2005 et Visual Studio Team System. Il aide également des clients du monde entier, tels que Microsoft, American Honda et DELL, à la conception et la mise en œuvre de systèmes. En tant que MVP pour Microsoft, Brian aime aider les gens à tirer le meilleur parti de leurs logiciels. Pour cela, il dispense des formations, donne des consultations et effectue des interventions lors de manifestations telles que VSLive!, Tech•Ed et le symposium PDC. En outre, Brian écrit. Il est co-auteur de Effective Visual Basic et a rédigé des articles pour MSDN Magazine et Microsoft. Membre du personnel technique de Pluralsight, il est l'auteur du cours Applied Team System de Pluralsight. Vous pouvez joindre Brian via son blog.

Ressources supplémentaires

Pour en savoir plus sur les produits et les technologies cités ou utilisés dans cet article, consultez les ressources suivantes :

Afficher: