The previous sections explained what VSTO projects are, how they are structured, and the features that you can use in the various project types. In this section, you look at implementing VSTO solutions.
Figure 40-5 outlines the structure of document-level customization solutions.
For document-level customizations you will interact with at least one host item, which will typically contain multiple host controls. You may use Office object wrappers directly, but for the most part, you will access the Office object model and its functionality through host items and host controls.
You will make use of host item and host control events, data binding, ribbon menus, action panes, and global objects in your code.
Figure 40-6 outlines the structure of application-level add-in solutions.
In this slightly simpler model, you are more likely to use the thinner wrappers around Office objects directly, or at least through the add-in class that encapsulates your solution. You will also use events exposed by the add-in class, ribbon menus, task panes, and global objects in your code.
In this section, you will look at both of these types of applications as appropriate, as well as the following topics:
- Managing application-level add-ins
- Interacting with applications and documents
- UI customization
Managing Application-Level Add-Ins
One of the first things you will find when you create an application-level add-in is that VS carries out all the steps necessary to register the add-in with the Office application. This means that registry entries are added so that when the Office application starts, it will automatically locate and load your assembly. If you subsequently want to add or remove add-ins, then you must either navigate through Office application settings or manipulate the registry manually.
For example, in Word, you must open the Office Button menu, click Word Options, and select the Add-Ins tab, as shown in Figure 40-7
Figure 40-7 shows two add-ins that have been created with VSTO:WordAddInl and WordDocEditTimer. To add or remove add-ins, you must select COM Add-Ins in the Manage drop-down (the default option) and click the Go button. The dialog box that appears is shown in Figure 40-8.
You can unload add-ins by deselecting them in the COM Add-Ins dialog box (as shown in Figure 40-8) and you can add new add-ins or remove old ones with the Add and Remove buttons.
Interacting with Applications and Documents
Whatever type of application you are creating, you will want to interact with the host application and/or documents in the host operation. In part, this includes using VI customizations, which you learn about in the next section. However, you may also need !o monitor documents within an application, which
means that you must handle some Office object model events. For example, to monitor documents in Word, you require event handlers for the following events of the Microsoft. Office. Interop. word .ApplicationEvents4_Event interface:
- DocumentOpen – Raised when a document is opened.
- NewDocument- Raised when a new document is created.
- DocumentBeforeClose – Raised when a document is saved.
Also, when Word first starts, it will have a document loaded, which will either be a blank new document or a document that was loaded.
The downloadable code for this chapter includes an example called WordDocEditTimer, which maintains a list of edit times for Word documents. Part of the functionality of this application is to monitor the documents that are loaded, for reasons that are explained later. Because this example also uses a custom task pane and ribbon menu, you will 100k at it after covering those topics.
You can access the currently active document in W d through ThisAddIn .Application.·ActiveDocument property, and the collection of open documents through ThisAddIn. Application . Documents. Similar properties exist for the other Office applications with a Multiple Document Interface (MOl). You can manipulate various properties of documents through the properties exposed by, for example, the Microsoft. Office. Interop. Word. Document class.
One point to note here is that the amount of classes and class members you must deal with when developing VSTO solutions is, frankly, enormous. Until you get used to it, it can be difficult to locate the features you are after. For example, it is not obvious why in Word the current active selection is available not through the active document, but through the application (through the ThisAddIn . Application. Selection property).
The selection is useful for inserting, reading, or replacing text through the Range property. For example:
ThisAddIn.Application.Selection.Range.Text = ‘Inserted text’;
Unfortunately, there is not enough space in this chapter to cover the object libraries in great depth. Instead, you willieam about the object libraries as they are relevant to the ongoing discussion.
Perhaps the most important aspect of the latest release of VSTO is the flexibility that is available for customizing the UI of your customizations and add-ins. You can add content to any of the existing ribbon menus, add completely new ribbon menus, customize task panes by adding action panes, add completely new task panes, and integrate Windows Forms and WPF forms and controls.
In this section, we look at each of these subjects.
You can add ribbon menus to any of the VSTO projects that you are looking at in this chapter. When you add a ribbon, you will see the designer window shown in Figure 40-9.
The designer aIlows you to customize this ribbon by adding controls to the Office button menu (shown in the top left of Figure 40-9) and to groups on the ribbon. You can also add additional groups.
The classes used in ribbons are found in the Microsoft. Office. Tools. Ribbon namespace. This includes the ribbon class that you derive from to create a ribbon, Office Ribbon. This class can contain
Ribbon Tab objects, each of which includes content for a single tab. Tabs contain Ribbon Group objects, like the group1 group in Figure 40-9. These tabs can contain a variety of controls.
It is possible for the groups on a tab to be positioned on a completely new tab, or on one of the existing tabs in the Office application that you are targeting. Where the groups appear is determined by the Ribbon Tab. Controlld property. This property has a ControlIdType property, which you can set to RibbonControlIdType. Custom or RibbonControlIdType. Office. If you use Custom, then you. must also set Ribbon Tab. Controlld. CustomId to a string value, which is the tab identifier. You can
use any identifier you like here. However, if you use Office for Control IdType, then you must set Ribbon Tab. Controlld. OfficeId to a string value that matches one of the identifiers used in the
Office product you are using. For example, in Excel you could set this property to Tab Home to add groups to the Home tab, Tab Insert for the Insert tab, and so on. The default for add-ins is Tab AddIns, which will be shared by all add-ins.
Many tabs are available, especially in Outlook; you can download a series of spreadsheets containing the full list from: www.microsoft.com/download details.aspx?FarnilyID=4329D9E9-4Dll-46AS-B9BD-23E4F331E9AE&displaylang=en.
Once you have decided where to put your ribbon groups, you can add any of the controls shown in the
RibbonBox: This is a container control that you can use to layout other controls in a group. You can layout controls in a RibbonBox horizontally or vertically by changing the BoxStyle property to RibbonBoxStyle . Horizontal or RibbonBoxStyle. Vertical.
RibbonButton: You can use this control to add a small or large button with or without a text label to a group. Set the Control Size property to RibbonControlSize.RibbonControlSizeLarge or RibbonControlSize. RibbonControlSizeRegular to control the size. The button has a Click event handler that you can use to respond to interaction. You can also set the image to a custom image or to one of the images stored in the Office system (described following this table).
RibbonButtonGroup: This is a container control that represents a group of buttons. contain RibbonButton, RibbonGallery, RibbonMenu, RibbonSplitButton, and RibbonToggleButton controls
RibbonCheckBox: A check box control with a Click event and a Checked property.
RibbonComboBox: A combo box (combined text entry with drop-down list of items). Use the Items property for items, the Text property for the entered text, and the TextChanged event to respond to changed.
RibbonDropDown: A container that can contain RibbonDropDownItem and RibbonButton items, in Items and Buttons properties respectively. The button and items are formatted into a drop-down list. You use the SelectionChanged event to respond to interaction
RibbonEditBox: A.text box that users can use to enter or edit text in the Text property. This control has a TextChanged event.
RibbonGallery: As with RibbonDropDown, this control can contain
RibbonDropDownItem and RibbonButton items, in Items and Buttons properties respectively. This control uses Click and ButtonClick events rather than the SelectionChanged event that
RibbonLabel Simple: Simple text display, set with the Label property.
RibbonMenu: A pop-up menu that you can populate with other controls, such as RibbonButton and nested RibbonMenu controls, when it is open in design view. Handle events for the items.on the menu.
RibbonSeparator: A simple separator used to customize control layout in groups.
RibbonSplitButton: Control that combines a RibbonButton or RibbonToggleButton with a RibbonMenu. Set the button style with ButtonType, which can be RibbonButtonType .But ton or RibbonBut tonType .ToggleButton. Use the Click event for the main button or individual button Click events in the menu to respond to interaction.
RibbonToggleButton: A button that can be in a selected or unselected state, as indicated by the Checked property. This control also has a Click event.
You can also set the DialogBoxLauncher property of a group so that an icon appears in the bottom right of the group. You can use this to display a dialog box as its name suggests, or to open a task pane,
or to perform any other action you want. You add or remove this icon through the Group View Tasks menu, as shown in Figure 40-10,which also shows some of the other controls in the previous table as they appear on a ribbon in design view.
To set the image for a control, for example a RibbonButton control, you can either set the Image property to a custom image and ImageName to a name for the image (so that you can optimize image loading in an OfficeRibbon. LoadImage event hander ), or you can use one of the built-in Office images. To do this, you set the OfficeImageId property to the ID of the image.
There are many images that you can use; you can download a spreadsheet that lists them from www.microsoft.com/downloads/details.aspx?familyid=12b99325-93e8-4ed4-85-74d0f7661318&displaylang=en. Figure 40-11shows a sample.
Figure 40-11 shows the Developer ribbon tab, which you can enable through the Office button, in the Excel Options dialog box, on the Popular tab.
When you click on an image, a dialog box appears to tell you what the image ID is, as shown in Figure 40-12.
The ribbon designer is extremely flexible, and you can provide pretty much any functionality that you would expect to find on an Office ribbon. However, if you want to customize your VI further, then you will want to use action and task panes, as you can create any VI and functionality you like there.
Action Panes and Custom Task Panes
You can use action and task panes to display content that is docked in the task pane area of the Office application interface. Task panes are used in application-level add-ins, and action panes are used in
document-level customizations. Both task and action panes must inherit from UserControl objects, which means that you create a VI by using Windows Forms. You can also use a WPF VI if you host a
WPF form in an ElementHost control on the UserControl. One difference between these controls is that you can add action panes to a document-level customization through the Action Pane Template item in the New Item Wizard or with a simple user control. Task panes must be added as plain user controls.
To add an action pane to a document in a document-level customization, you add an instance of the action pane class to the Controls colIection of the ActionsPane property of the document.
Note that the Add() method returns an object of type Microsoft. Office. Tools. CustomTaskPane. You can access the user control itself through the Control property of this object. You can also use other properties exposed by this type – for example, the Visible property as shown in the ‘previous code to control the task pane.
At this point, it is worth mentioning a slightly unusual feature of Office applications, and in particular, a difference between Word and Excel. For historical reasons, although both Word and Excel are MDI applications, the way in which these applications host documents is different. In Word, every document has a unique parent window. In Excel, ~very document shares the same parent window.
When you call the CustomTaskPanes. Add() method, the default behavior is to add the task pane to the currently active window. In Excel, this means that every document will display the task pane, as the same parent window is used for all of them. In Word, the situation is different. If you want the task pane to appear for every document, then you must add it to every window that contains a document.
To add the task pane to a specific document, you pass an instance of the Microsoft. Office.Interop.Word. window class to the Add() method as a third parameter. You can obtain the window associated with a document through the Microsoft. Office. Interop. Word. Document. Active window property.
In the next section, you will see how to do this in practice.