Understanding the events in the Word object model is critical, because this is often the primary way that your code is run. This chapter covers all the events in the Word object model, when they are raised, and the type of code you might associate with these events. Some of the events in the Word object model are repeated on the Application and Document objects. This repetition allows you to decide whether you want to handle the event for all documents or for a particular document. If you want to know when any document is closed, for example, you would handle the Application object's DocumentBeforeClose event. If you want to know when a particular document is closed, you would handle the Close event on a particular Document object. When an event is repeated on the Application and Document object, it is raised first on the Document object and then on the Application object.
Visual Studio Generation of Event HandlersAs you consider some of the code in this chapter, you might wonder how you will ever remember the syntax of complicated lines of code such as this one: Private Sub App_DocumentBeforeClose( _ ByVal document As Word.Document, _ ByRef cancel As Boolean) _ Handles app.DocumentBeforeClose Fortunately, Visual Studio 2005 helps by generating this code for you. When you have declared the app member variable as having events by using the WithEvents keyword, Visual Studio displays the app variable in the left drop-down list of the code editor. Select app from the left drop-down list; then select the event that is raised by app that you want to handle from the right drop-down listin this case, DocumentBeforeClose (see Figure 7.1). When you select the event you want to handle, Visual Studio generates the event handler method automatically. Figure 7.1. Visual Studio generates event handler code for you if you use the left and right drop-down lists in the code editor.If you are using VSTO, you can also use the Properties window to add event handlers to your document class. Double-click the project item for your document class. Make sure the Properties window is visible; if it is not, choose Properties Window from the View menu. Make sure that the document class (typically called ThisDocument) is selected in the combo box at the top of the Properties window. Then click the lightning-bolt icon to show events associated with the document. Type the name of the method you want to use as an event handler in the edit box to the right of the event you want to handle. Figure 7.2. shows the Properties window and an event handler we have added by typing the text ThisDocument_New in the edit box next to the New event. This will cause the New event to be handled by a method called ThisDocument_New in the document class. If the method does not already exist, Visual Studio will add the method for you. Figure 7.2. Adding a document event handler using the Properties window in VSTO.
Startup and Shutdown EventsSeveral events are raised when the application is started and shut down. The Word Application object has a Startup event that is raised when the application starts and before any documents are loaded. This event is marked as "restricted" in the COM object model, however, and probably should not be used. The only kind of customization that can handle this event is an add-in. The event is raised before documents are loaded and before an automation executable can establish an event handler. Even add-ins do not need to use this event because they already implement OnConnection, which serves the same purpose. Our recommendation is that you not use the Application object's Startup event. For VSTO customizations, we recommend that you use the Startup and Shutdown events raised by VSTO on a document project item. Startup is raised when the document is opened or created from a template. Shutdown is raised when the document is closed. In the project item created for you by VSTO, these events are already connected for you, as shown in Listing 7.2. Listing 7.2. A VSTO Customization That Handles the Startup and Shutdown Events
Word raises the Quit event when the application shuts down. Listing 7.3 shows an example of handling the Quit event. Note Quit is the name of both a method and an event on Word's Application object. Because of this collision, you will have to use the CType operator to cast the Application object to the ApplicationEvents4_Event interface when adding an event handler dynamically using the AddHandler statement. If you are adding an event handler declaratively using With Events and Handles as in Listing 7.3, you do not have to worry about this issue. Listing 7.3. A VSTO Customization That Handles the Quit Event
New and Open Document EventsWord raises a NewDocument event on the Application object and a New event on a Document object when a new document is created by the user either as a blank document or from a template or existing document. These events are never raised on subsequent opens of the document. Word also raises a DocumentOpen event on the Application object and an Open event on a Document object when an existing document is opened:
Listing 7.4 shows a VSTO customization that handles the Application object's NewDocument event and puts into the footer of every new document created in Word the date the document was created and the name of the user who created the document. It also handles the Application object's DocumentOpen event to put into the header of an existing document that is opened the date the document was opened and the name of the user who opened the document. Listing 7.4. A VSTO Customization That Handles the Application Object's NewDocument and DocumentOpen Events
Listing 7.5 shows VSTO code behind a template that handles the Document object's New event to display the time in the footer when the document is created from a template. It also handles the Document object's Open event to put into the header the date and user who last opened the document each time the document is opened. To understand this listing, it is important to understand how Word templates work in VSTO. You should write handlers for the Document object's New event only in a template project. When a user creates a new document from that template, the code associated with the template will be associated with the newly created document, and the New event will be raised on the newly created document. Also note that because the New event conflicts with the New keyword in Visual Basic, the Handles clause puts the New event in square brackets so the compiler knows that New is being used as an event name rather than a keyword. Listing 7.5. A VSTO Customization That Handles the Document Object's New and Open Events
Document Close EventsWord raises events when a document is closed. The DocumentBeforeClose event is raised on the Application object before the document closes, which allows the handler to cancel the closing of the document. The Close event raised on the Document object does not allow canceling the closing of the document. Unfortunately, the Close event is raised even in cases where the document is not really going to close. The event is raised before a dialog box is shown to the user prompting the user to save the document. Users are asked whether they want to save with a Yes, No, and Cancel button. If the user selects Cancel, the document remains open even though a Close event was raised. It is also possible for another add-in to handle the DocumentBeforeClose event and cancel the close of the document. For this reason, it is better to use VSTO's Shutdown event on the document, which is not raised until after the user and any handlers of the DocumentBeforeClose event have been given a chance to cancel the closing of the document. The following events are raised when documents are about to be closed:
Note Close is the name of both a method and an event on Word's Document object. Because of this collision, you will have to use the CType operator to cast the Document object to the DocumentEvents2_Event interface when adding an event handler dynamically using the AddHandler statement. If you are adding an event handler declaratively using WithEvents and Handles, you do not have to worry about this issue. Listing 7.6 shows a VSTO customization that handles the Application object's DocumentBeforeClose event and the Document object's Close event. In the handler of the DocumentBeforeClose event, the code checks to see whether the document contains any spelling errors. If it does, a dialog box displays the number of spelling errors, and the user is told to correct them before closing the document. The cancel parameter is set to TRue to prevent the document from closing. Another thing to try when running this code is to click the Cancel button when you are prompted to save and then observe that the Document object's Close event fires in this case. Listing 7.6. A VSTO Customization That Handles the Application Object's DocumentBeforeClose Event and the Document Object's Close Event
Document Save EventsWord raises the DocumentBeforeSave event on the Application object before any document is saved. Word passes the Document that is about to be saved as a parameter to this event. It also passes by reference a Boolean saveAsUI parameter and a Boolean cancel parameter. If you set saveAsUI to true, the Save As dialog box displays for the document. If you set the cancel parameter to true, the save will be canceled. Often, this event is handled to implement a custom save routine You might cancel the DocumentBeforeSave event but call the SaveAs method on Document to enforce a particular file format, for example. Note that the DocumentBeforeSave event is also raised when Word does an AutoSave on a document. You should be careful that you test your code to make sure that it works properly when AutoSave is triggered. Listing 7.7 shows a VSTO customization that handles the DocumentBeforeSave event. If the document contains any spelling errors, the event handler cancels the save by setting the cancel parameter to true. It also sets the saveAsUI parameter to true to force a Save As dialog box to be shown for every save. When the DocumentBeforeSave event is triggered for an AutoSave, the dialog box shown in Figure 7.3 displays. Figure 7.3. The message displayed by Word when an automatic save is canceled.
Listing 7.7. A VSTO Customization That Handles the Application Object's DocumentBeforeSave Event
Document Activation EventsWord raises several events on the Application object when the active document changes. One such event is the DocumentChange event. The name DocumentChange makes you think that maybe this event will tell you when the contents of the document change; unfortunately, Word does not have a general event that tells you this. The active document changes when you create a new document; the new document becomes the active document. The active document changes when you open an existing document; the document you opened becomes the active document. The active document changes when you switch between open documents by clicking a document that is not active or by selecting a document using the Window menu or the Windows taskbar. It is also possible to have multiple windows viewing the same documentbecause the user chose New Window from the Window menu, for example. Word raises an event called WindowActivate that tells you when a particular window becomes the active window and an event called WindowDeactivate when a particular window is deactivated. Unlike in Excel, switching to another application causes Word's WindowDeactivate event to be raised, and switching back to Word causes the WindowActivate event to be raised. The following events are raised when windows are activated and deactivated:
Listing 7.8 shows a VSTO customization that handles the DocumentChange, WindowActivate, and WindowDeactivate events and displays a message box when these events are raised. Listing 7.8. A VSTO Customization That Handles the Application Object's WindowActivate, WindowDeactivate, and DocumentChange Events
Document Print EventsWord raises a DocumentBeforePrint event on the Application object before a document is printed. Word passes the Document that is about to be printed as a parameter to this event. It also passes by reference a Boolean cancel parameter. If you set the cancel parameter to true, the default printing of the document will be canceled. Often, this event is handled to implement a custom print routine. You might cancel Word's default print behavior and use the PrintOut method on Document to enforce a certain print format, for example. Listing 7.9 shows a VSTO customization that handles the DocumentBeforePrint event to enforce some custom print settings. It forces two copies to be printed and collation to be turned on when the user prints the document. Listing 7.9. A VSTO Customization That Handles the Application Object's DocumentBeforePrint Event
Mouse EventsWord raises events when the user right-clicks or double-clicks the document area of a window. If the user right-clicks or double-clicks in area of the window such as the ruler or the scroll bar, no events are raised. The following events are raised when double-clicks or right-clicks occur:
Listing 7.10 shows a VSTO customization that handles the WindowBeforeDoubleClick and WindowBeforeRightClick events. When the document is double-clicked, this application sets the selected range of text to be all caps. The range of text that is selected depends on where the user double-clicked. If the user double-clicks a word, the selection changes to be the word. If the user triple-clicks, the selection changes to be a paragraph. If the user double-clicks the page margin, the selection changes to be the line next to where the user double-clicked. When a range of text is right-clicked, this customization sets the range of text to be title case. Finally, if you double-click a shape in the document, the color is set to dark red. We also set cancel to true to prevent the shape Properties dialog box from being shown when a shape is double-clicked and to prevent the right-click menu from appearing when a range of text is right-clicked. Listing 7.10. A VSTO Customization That Handles the Application Object's WindowBeforeDoubleClick and WindowBeforeRightClick Events
Selection EventsWord raises several events when the selection changes in the active document:
Listing 7.11 shows a VSTO customization that uses the Range.Start and Range.End properties to display the start and end locations of the selection. The code first checks whether the selection type is wdSelectionIP or wdSelectionNormal. It also prints the selection type using a helpful feature of Visual Studio; when you use the ToString method associated with an enumerated type, it displays the string name of the enumeration instead of just displaying a number. Listing 7.11. A VSTO Customization That Handles the Application Object's WindowSelectionChange Event
Window Sizing EventsWord raises a WindowSize event on the Application object when a window associated with a document is resized. Once again, the behavior of this event is different from the window-sizing event in Excel. The WindowSize event in Word is raised even when the document window is maximized to fill the Word application window and the Word application window is resized. The event is not raised for the Word application window when it is resized and no documents are open. Word passes the Document object associated with the window that was resized as a parameter to this event. Word also passes the Window object for the window that was resized. XML EventsWord raises several events when XML elements have been mapped into the document using the XML Structure feature of Word. You have already learned about the Application object's XMLSelectionChange that is raised when the selection changes from one XML element to another. Chapter 22, "Working with XML in Word," considers Word's XML features in more detail. The following events are raised as part of the XML Structure feature of Word:
Sync EventsWord raises the Document object's Sync event when a local document is synchronized with a copy on the server using Word's document workspace feature. Word passes a parameter of type MsoSyncEventType that gives additional information on the status of the document synchronization. E-Postage EventsWord supports a feature called electronic postage, which enables you to create an envelope or label with printed postage that is printed on an envelope or package along with the address. Figure 7.4 shows the Envelopes and Labels dialog box, which has an Add Electronic Postage check box and an E-Postage Properties button that are used to configure electronic postage. Word provides three events to allow third parties to create an e-postage add-in: EPostageInsert, EPostageInsertEx, and EPostagePropertyDialog. An e-postage add-in is distinguished from other Word add-ins by a special registry key. There can be only one active e-postage add-in installed in Word. This book does not consider these events further because it is unlikely that you will ever need to create your own electronic postage add-in. You can read more about e-postage add-ins by downloading the e-postage SDK at http://support.microsoft.com/?kbid=304095. Figure 7.4. The Envelopes and Labels dialog box with electronic postage options.Mail Merge EventsWord raises eight events associated with the mail merge feature. To understand these events, you must first understand how mail merge works and when and why each of these events is raised. The user starts a mail merge by choosing Tools > Letters and Mailings > Mail Merge. This causes the Application object's MailMergeWizardStateChange event to be raised, notifying us that we are moving from Step 0 to Step 1 of the Mail Merge Wizard. Then the Mail Merge task pane shown in Figure 7.5 displays. The Mail Merge task pane is a wizard that can move back and forth through six steps. Whenever we move from step to step, the MailMergeWizardStateChange event is raised. When we close the document, the MailMergeWizardStateChange event is raised, moving from Step 6 back to Step 0. Figure 7.5. Step 1 of the Mail Merge Wizard.
Step 2 is not shown here; it prompts us as to whether we want to start from the current document or from a template or existing document on disk. In Step 2, we will choose to use the current document. When we get to Step 3 of the Mail Merge Wizard, we are prompted to select a data source for the mail merge. Figure 7.6 shows Step 3. Figure 7.6. Step 3 of the Mail Merge Wizard.
We choose Use an Existing List and click the Browse link to locate an Access database we have previously created called Authors.mdb. Figure 7.7 shows the dialog box for picking a data source. Figure 7.7. Selecting a data source.After we select the data source and click Open, the Application object's MailMergeDataSourceLoad event is raised. This event lets us know that a data source has been chosen, and now we can examine the data source through the object model. After the MergeDataSourceLoad event has been raised, the Mail Merge Recipients dialog box appears, as shown in Figure 7.8. This dialog box shows each record in the data source and lets you further control which records you want to use for the mail merge. Figure 7.8. The Mail Merge Recipients dialog box.The Mail Merge Recipients dialog box has a button called Validate. When clicked, this button raises the Application object's DataSourceValidate event. It raises this event only for the special e-postage add-in described earlier in this chapter, however. Step 4 of the Mail Merge Wizard lets you insert address blocks, greeting blocks, and other fields into the body of your document. Step 5 lets you preview the final look of your document when Word loads the data from your data source into the blocks you have defined. Step 6 displays two actions you can take to complete the mail merge. The first is to print the generated letters. The second is to create a new document and insert each letter into the new document. You can also specify a third action by writing a line of code such as the following before Step 6 of the wizard is shown:
The MailMerge object's ShowSendToCustom property takes a String value and allows you to add a third custom action defined by your code to do at the end of a mail merge. When the user clicks this custom action, the Application object's MailMergeWizardSendToCustom event is raised. Figure 7.9 shows Step 6 of the Mail Merge Wizard with a custom action called My Custom Action. Figure 7.9. Step 6 of the Mail Merge Wizard.
When the user chooses Print or Edit Individual Letters, the Application object's MailMergeBeforeMerge event is raised. Word passes the start record and the end record that will be merged as Integer parameters. The default is to merge all the records. When all the records are going to be merged, Word passes 1 for the start record and 16 for the end record. Word also passes by reference a Booleancancel parameter. If you set the cancel parameter to true, the mail merge will be canceled. After the MailMergeBeforeMerge event is raised, Word shows a dialog box letting the user change the records to merge, as shown in Figure 7.10. Unfortunately, if the user changes the records to be merged, Word does not raise the MailMergeBeforeMerge event again. The next time the user does a mail merge, the user's last selection in the dialog box will be reflected in the parameters passed to MailMergeBeforeMerge. Figure 7.10. Selecting the records to merge.
When the user clicks the OK button in the dialog box shown in Figure 7.10, the mail merge begins in earnest. Before Word merges a record from the data source to create a letter, it first raises the Application object's MailMergeBeforeRecordMerge event; then it creates the letter from the record and raises the Application object's MailMergeAfterRecordMerge event when the letter for the record has been generated. This sequence of MailMergeBeforeRecordMerge followed by MailMergeAfterRecordMerge repeats for each record that is going to be merged. When all the records have been merged, Word raises the Application object's MailMergeAfterMerge event and passes the newly created Document object as a parameter if the user chose Edit Individual Letters in Figure 7.9. If the user chose Print, Nothing will be passed for the newly created document. Listing 7.12 shows a VSTO customization that handles all the mail merge events. Listing 7.12. A VSTO Customization That Handles Mail Merge Events
CommandBar EventsA common way to run your code is to add a custom toolbar button or menu item to Word and handle the click event raised by that button or menu item. Word uses the same object model as Excel to add toolbar buttons and menu items. Chapter 4, "Working with Excel Events," discusses this model in more detail. One difference between Excel and Word is that Word can save an added toolbar or menu item in a template or a document. The default location that a new toolbar or menu item is saved to is the Normal template (normal.dot). You can specify that the new toolbar or menu item be associated with another template or with a document by using the Application object's CustomizationContext property. The CustomizationContext property takes an Object that is either a Template object or a Document object. Subsequent calls to add toolbars or buttons (a CommandBarButton, for example) will be saved in the template or document you set using the CustomizationContext property. Listing 7.13 shows a listing similar to the Excel example in Listing 4.9 in Chapter 4, with two significant differences. First, we use the CustomizationContext property to make it so the toolbar we add will be associated with a particular document. Second, we pass true as the last parameter to the various Add methods so that the CommandBar, CommandBarButton, and CommandBarComboBox are added permanently rather than temporarily. Listing 7.13. A VSTO Customization That Adds a Custom CommandBar
|