Programming MicrosoftВ® OutlookВ® and Microsoft Exchange 2003, Third Edition (Pro-Developer)

You can build smart tags in two ways. The first way does not require code. You simply provide a list of terms and associated actions to the Microsoft Office Smart Tag List (MOSTL) component. Using MOSTL limits your ability to dynamically recognize terms and perform actions, but you can set up update intervals for your smart tag lists and update them from a content source on your network. The second and more flexible way to build smart tags is by writing a COM component that implements the recognizer and action interfaces. This approach provides the most flexibility by enabling you to dynamically recognize terms and define actions. I'll describe how to build smart tags using code after describing MOSTL in more detail.

Using MOSTL

If you've ever enabled the MSN financial smart tag list, which enables a hyperlink to stock symbols, you have used MOSTL. This list is built as a smart tag list. To create a smart tag list for use with MOSTL, you create an XML file that contains your hit list and the actions associated with those hits. The following example from the MSN stock symbol smart tag list shows of the format of the XML file for MOSTL:

<FL:smarttaglist xmlns:FL="urn:schemas-microsoft-com:smarttags:list"> <FL:name>MSN MoneyCentral Financial Symbols</FL:name> <FL:lcid>1033,0</FL:lcid> <FL:description>A list of stock ticker symbols for recognition, as well as a set of actions that work with them.</FL:description> <FL:moreinfourl>http://office.microsoft.com</FL:moreinfourl> <FL:updateable>true</FL:updateable> <FL:autoupdate>true</FL:autoupdate> <FL:lastcheckpoint>100</FL:lastcheckpoint> <FL:lastupdate>5123942</FL:lastupdate> <FL:updateurl>http://office.microsoft.com/smarttags/stockupdate.xml</FL:upda teurl> <FL:updatefrequency>20160</FL:updatefrequency> <FL:smarttag type="urn:schemas-microsoft-com:office:smarttags#stockticker"> <FL:caption>Financial Symbol</FL:caption> <FL:terms> <FL:termfile><FL:filename>stocks.dat</FL:filename></FL:termfile> </FL:terms> <FL:actions> <FL:action id="LatestQuoteData"> <FL:caption>Stock quote on MSN MoneyCentral</FL:caption> <FL:url>http://moneycentral.msn.com/redir/moneycentralredi rect.asp?pageid=SmartTag_1&amp;Target=/scripts/web quote.dll?ipage=qd%26Symbol={TEXT}</FL:url> </FL:action> <FL:action id="CompanyReportData"> <FL:caption>Company report on MSN MoneyCentral</FL:caption> <FL:url>http://moneycentral.msn.com/redir/moneycentralredi rect.asp?pageid=SmartTag_2&amp;Target=/investor/research/profile.asp?Sym bol={TEXT}</FL:url> </FL:action> <FL:action id="RecentNews"> <FL:caption>Recent news on MSN MoneyCentral</FL:caption> <FL:url>http://moneycentral.msn.com/redir/moneycentralredi rect.asp?pageid=SmartTag_3&amp;Target=http://news.moneycentral.msn.com/ticker/ rcnews.asp?Symbol={TEXT}</FL:url> </FL:action> </FL:actions> </FL:smarttag> </FL:smarttaglist>

As you can see in the XML, you must declare the Smart Tag namespace and use that namespace throughout your file. Table 9-1 describes the elements of the schema used in the XML file.

Table 9-1: Elements of the Smart Tag XML Schema

Element

Description

smarttaglist

The schema namespace declaration for the Smart Tag namespace. This tag is required.

name

The friendly name for the smart tag recognizer.

lcid

A comma-separated list of locale IDs that specify the languages of words that the list will identify.

description

A string that describes the smart tag.

Moreinfourl

The URL at which the user can get more information about the smart tag.

Updateable

A Boolean flag that indicates whether the list is updatable.

Autoupdate

A Boolean flag that specifies whether the list should update automatically.

Lastcheckpoint

An integer that specifies the version number for the smart tag list. If a newer version is available and autoupdate is set to True , the newer version will be downloaded.

Lastupdate

An integer that specifies when the last update occurred. It is specified in the number of minutes since 1970.

Updateurl

A string indicating the URL that the smart tag should check for any updates to the list.

Updatefrequency

An integer that specifies in minutes how often the smart tag should check for updates. If blank, 7 days (10080 minutes) is assumed.

smarttag

A smart tag type specified by a unique namespace. Smart tag types contain terms and actions.

Terms

The XML section that contains the term nodes for the smart tag.

Termfile

A link to a binary file that contains your terms. You will most likely use the termlist element. A filename subelement is required if termfile is used.

Termlist

A comma-separated list that contains your terms. To place quotation marks around terms, use three quotation marks ”for example, """Tom""" will appear as "Tom".

Property

A name and value pair that you attach to the term if it is recognized. You can have only one property attached to any action.

Actions

The XML section that contains the action nodes for the smart tag.

Action

A particular action for the smart tag type. You must specify a unique ID for the action in the action element.

Caption

A string for the caption you want to display for the action.

url

A string that specifies the URL to call for the action. You can specify special terms in your url element, such as {LCID} to pass the locale ID and {TEXT} to pass the smart-tagged text. The MSN stock ticker list uses {TEXT} to pass the stock symbol name to a Web page to look up the company specified.

Creating and Storing Your XML Definitions

To create your XML smart tag list files, you can use any text editor. You can copy and modify an existing list, such as the MSN one, which makes creating the list easier and limits mistakes in your coding. The MSN list is located in the directory where you should save your XML definition files, which is drive :\Program Files\Common Files\Microsoft Shared\Smart Tag\Lists. Another possible location, if you want the list to roam with the user, is drive :\Documents and Settings\ username \Application Data\Microsoft\Smart Tag Lists. When you save your list, be sure to make the extension for the list .xml.

Updating a MOSTL List via a Web Server

If you fill in the schema elements for automatic updating and place a URL in the updateurl schema element, MOSTL will automatically update the smart tag list. For the smart tag list to be updated, you need to place an update file at the URL you specify. The following sample shows an update file:

<FLUP:smarttaglistupdate xmlns:FLUP="urn:schemas-microsoft-com:smarttags:list update"> <FLUP:checkpoint>400</FLUP:checkpoint> <FLUP:smarttaglistdefinition>new.xml</FLUP:smarttaglistdefinition> </FLUP:smarttaglistupdate>

You must link to this file from the updateurl element defined in the smart tag XML schema and set the checkpoint element in the update file to be greater than the checkpoint in the original file. If the smart tag list needs to be updated, MOSTL will grab the file listed in the smarttaglistdefinition element and download it to the client. The sample just shown, new.xml, is just a new smart tag list file that has the same format and schema elements as any smart tag list file. The downloaded filename becomes whatever the original list's filename was. For example, if new.xml is an update to original.xml, when new.xml is downloaded, it will be renamed original.xml and will replace the earlier original.xml.

Be sure that the checkpoint value you put in your update list XML file, shown in our example with a value of 400 , matches exactly the checkpoint value you put in your list definition file, which in this example is new.xml. Otherwise, your smart tag will always update or never update, depending on which checkpoint value is the greater of the two.

Note  

Even though new file list definitions are downloaded automatically, Office XP applications do not refresh their smart tag lists until you shut down and restart those applications.

Writing Custom Smart Tags

MOSTL will not always meet the needs of your application. For example, if you need dynamic terms or dynamic action lists and you don't want to download and update a file every time the terms or actions change, MOSTL is not a good solution. To make smart tag development more extensible than MOSTL, Office XP and Office 2003 offer you the ability to write a COM component that can implement the smart tag interfaces for recognizers and actions. You can write your smart tag using any COM-compliant language, such as Visual Basic or Visual C++. We will look at Visual Basic examples in this chapter; the smart tag SDK, which is among the book's companion files, includes examples for Visual C++.

Building Custom Smart Tag Recognizers Using Visual Basic

When you build a custom smart tag recognizer, you should follow some general development guidelines. First, you should not implement any sort of visual user interface in the recognizers that you build, especially modal forms. This can cause unexpected behavior in the smart tag hosting application. Second, you should build your smart tags generically and not assume that Office applications will always be your client because other Microsoft applications or even third-party applications can add the capability to host smart tags.

One thing to note about building smart tag recognizers is that one recognizer can call multiple action DLLs and multiple recognizers can leverage a single action DLL.

The basic step in building a smart tag recognizer with Visual Basic is to build the recognizer and action DLLs as ActiveX DLLs. Your DLLs will leverage the Microsoft Smart Tags 1.0 type library, so you only need to implement the smart tag interfaces and the action functionality for your smart tag.

Creating the ActiveX DLL

If you are still using Visual Basic 6.0, your first step is to create an ActiveX DLL that contains both recognizer and action functionality. You could separate this functionality into two DLLs, but for this example we will use the same DLL. Next you add a reference to the smart tag type library, as shown in Figure 9-4.

Figure 9-4: Adding a reference to the smart tag type library in Visual Basic 6.0

The next step is to implement the ISmartTagRecognizer interface. Table 9-2 lists the properties and method of the smart tag recognizer interface.

Table 9-2: Elements of the Smart Tag Recognizer Interface

Property

Description

Desc

A string that specifies what the smart tag does.

Name

A string that specifies the name of the smart tag. It's displayed as the caption for the smart tag in the Office user interface.

ProgID

A string that specifies the ProgID of the smart tag, such as mysmarttag.recognizer .

SmartTagCount

An integer value that specifies the number of smart tag types that this recognizer supports.

SmartTagDownloadURL

A string property that specifies a URL that allows the user to download the actions for the smart tag if they are not already on the system. This download can be performed by users when they choose the Check For New Actions menu command.

SmartTagName

A string that specifies the smart tag types that the recognizer supports. This string must be in the format namespaceURI# tagname , as in myURI#Categories .

Method

Description

Recognize

Recognizes the terms in the document. It passes four parameters. The first is a string that defines the text that should be recognized. The second is an enumeration of the data type for the text. For example, the enumeration can specify whether the text is sent a character at a time, is sent as a word, or is an Excel cell. Only paragraph and cell types are currently supported. The third parameter is the locale ID of the text. The final parameter is a RecognizerSite object (described later in this chapter) that allows you to interact with the smart tag host.

Before we examine the code used to create a recognizer, we need to look at two other types of objects that you will use with smart tags. The first is the ISmartTagRecognizerSite object, which you'll use to commit new smart tags to Word and Excel as well as to create property bags with which to pass arbitrary properties that you create between recognizers and actions. The second object is ISmartTagProperties , which is used in conjunction with the smart tag property bag you create with the ISmartTagRecognizerSite object. Table 9-3 describes the methods defined in the ISmartTagRecognizerSite interface. Table 9-4 describes the members of the ISmartTagProperties interface.

Table 9-3: Methods of the ISmartTagRecognizerSite Interface

Method

Description

CommitSmartTag

Creates a new smart tag in the host. You must pass four parameters to this method. The first is the smart tag type string, which must be in the format namespaceURI#tagname . The second is an integer value that specifies the location at which to start the smart tag in the text. The underlining in Word for the smart tag begins at this location. The next parameter is an integer that specifies the number of characters the smart tag will span. The final parameter is a property bag object that you want to include with the smart tag.

GetNewPropertyBag

Returns an ISmartTagProperties -based object.

Table 9-4: Elements of the ISmartTagProperties Interface

Element

Description

Count

An integer that specifies the number of properties stored.

KeyFromIndex

Returns the key string corresponding to the integer index you pass.

Read

Gets the value corresponding to the key string you pass. If the key does not exist, this property returns Null .

ValueFromIndex

Returns the value string corresponding to the integer index you pass.

Write

Writes a key/value pair into the property bag. You must pass this method a key string and a value string.

Following is the smart tag recognizer code from our recognizer DLL that queries a setup of the Training application (presented later in the chapter) for the application categories you create. This code is written in the DLL for our smart tag. If the recognizer recognizes those categories in a document, it will tag the words as smart tags.

Implements SmartTagLib.ISmartTagRecognizer 'Declare path variables for the location where the Training Application 'and the Categories folder for the Training Application are 'installed. This path is used by the WebDAV query to figure out the 'categories for the application. Dim strTrainingAppCategoriesURL As String Dim strTrainingAppURL As String 'Recognized Categories Private arrCategoriesRecognized As Variant Private Sub Class_Initialize() 'Lookup the training application categories so that we know 'what to recognize. 'Categories are stored as comma separated values in a 'document called Categories.eml On Error Resume Next strTrainingAppCategoriesURL = _ "http://thomriznt52/public/trainingst/Categories/Categories.EML" strTrainingAppURL = "http://thomriznt52/trainingst/" Set oXMLHTTP = CreateObject("microsoft.XMLHTTP") oXMLHTTP.Open "PROPFIND", strTrainingAppCategoriesURL, False oXMLHTTP.setRequestHeader "Content-type:", "text/xml" oXMLHTTP.setRequestHeader "translate", "f" strRequest = "<?xml version=""1.0"" encoding=""utf-8""?>" & _ "<a:propfind xmlns:a=""DAV:"">" & _ "<a:prop xmlns:m=""urn:schemas:httpmail:"">" & _ "<m:textdescription/></a:prop></a:propfind>" oXMLHTTP.send strRequest 'Load up the result into an XMLDOM and parse out the 'categories. Set oXMLDOM = CreateObject("microsoft.xmldom") oXMLDOM.async = False oXMLDOM.LoadXML oXMLHTTP.ResponseText Set CategoryNode = oXMLDOM.getelementsbytagname("d:textdescription") 'Get the value from the node strCategories = CategoryNode.Item(0).nodeTypedValue arrCategoriesRecognized = Split(strCategories, ",") End Sub Private Property Get ISmartTagRecognizer_ProgId() As String ' Create a unique identifier for this recognizer ' that corresponds to the ProgID of this dll. ISmartTagRecognizer_ProgId = "STTrainingApp.Recognizer" End Property Private Property Get ISmartTagRecognizer_Name _ (ByVal LocaleID As Long) As String ' Add a short phrase that describes this recognizer that will be ' shown in the Tools > Autocorrect Option > Smart Tags ' dialog box in Word, Excel and PowerPoint. ISmartTagRecognizer_Name = "Training Application Category" End Property Private Property Get ISmartTagRecognizer_Desc _ (ByVal LocaleID As Long) As String ' Create a longer description of this recognizer. ISmartTagRecognizer_Desc = "Recognizes the Training" & _ "Application Sample Application Categories" End Property Private Sub ISmartTagRecognizer_Recognize _ (ByVal Text As String, _ ByVal DataType As SmartTagLib.IF_TYPE, _ ByVal LocaleID As Long, _ ByVal RecognizerSite As SmartTagLib.ISmartTagRecognizerSite) Dim oPropBag As SmartTagLib.ISmartTagProperties Dim position As Integer Dim Length As Integer On Error Resume Next 'Remove any question marks (??????) Length = Len(Text) If (Length > 0) Then position = InStr(1, Text, ChrW(-4)) Else position = 0 End If While (Length > 0 And position > 0) Mid$(Text, position, 1) = " " Length = Length - 1 If (Length > 0) Then position = InStr(1, Text, ChrW(-4)) Else position = 0 End If position = InStr(1, Text, ChrW(-4)) Wend Text = RTrim(Text) position = InStr(1, Text, ChrW(-4)) If (position > 0) Then Length = Len(Text) Mid$(Text, position, (Length - position + 1)) = _ Space$(Length - position + 1) Text = RTrim(Text) End If 'Now trim off the carriage return at the end of the string 'if there is one If (Right(Text, 1) = ChrW(13)) Then Text = Left(Text, Len(Text) - 1) End If 'See if we match any of the terms returned by the Text property 'UCASE both properties strUCASEText = UCase(Text) For i = LBound(arrCategoriesRecognized) To _ UBound(arrCategoriesRecognized) iLoc = 1 IndexLoc = InStr(1, strUCASEText, _ UCase(arrCategoriesRecognized(i))) Do While IndexLoc > 0 'We found a match somewhere in the string 'Since there could be multiple matches, 'find all occurrences of the string. 'Make sure there is a space after the phrase 'so we're not at the beginning of a word strNextChar = " " 'Figure out the end of the word by taking 'the location and adding the length 'of the term recognized. iEndOfWord = IndexLoc + Len(arrCategoriesRecognized(i)) strNextChar = Mid(strUCASEText, iEndOfWord, 1) If strNextChar = "" Then strNextChar = " " End If 'Make sure that a space precedes the beginning of 'the phrase so we're not in the middle of the word. strPrevChar = " " strPrevChar = Mid(strUCASEText, IndexLoc - 1, 1) If strPrevChar = "" Then strPrevChar = " " End If If strPrevChar = " " And strNextChar = " " Then Err.Clear 'Ask the recognizer site for a property bag. Set oPropBag = RecognizerSite.GetNewPropertyBag 'Store the URL to the training site and 'pass it to the action. oPropBag.Write "TrainingAppURL", strTrainingAppURL 'Commit the Smart Tag RecognizerSite.CommitSmartTag "trainingapp#categories", _ IndexLoc, Len(arrCategoriesRecognized(i)), oPropBag Set oPropBag = Nothing End If IndexLoc = _ InStr(IndexLoc + Len(arrCategoriesRecognized(i)), _ strUCASEText, UCase(arrCategoriesRecognized(i))) Loop Next End Sub Private Property Get ISmartTagRecognizer_SmartTagCount() As Long 'Specify the number of smart tag types this recognizer supports. '1 in this case. ISmartTagRecognizer_SmartTagCount = 1 End Property Private Property Get ISmartTagRecognizer_SmartTagName _ (ByVal SmartTagID As Long) As String 'Provide the name of the smart tag type supported. 'SmartTag names are always in the format of namespaceURI#tagname. If (SmartTagID = 1) Then ISmartTagRecognizer_SmartTagName = "trainingapp#categories" End If End Property Private Property Get ISmartTagRecognizer_SmartTagDownloadURL _ (ByVal SmartTagID As Long) As String 'For this particular smart tag type, there is a Web site 'to support a smart tag download URL. Note that '"http://trainingapp" supplied below is a hypothetical 'Web site used to demonstrate the Check for New Actions... 'menu item. ISmartTagRecognizer_SmartTagDownloadURL = "http://trainingapp" End Property

As you can see, the code sets up the ProgID, name, description, download URL, and other required properties to implement the ISmartTagRecognizer interface. During the initialization of the class, the application sends a WebDAV PROPFIND query to the server to retrieve the categories, which are stored as a comma-delimited string in a message in the categories folder.

The most important part of the code is in the Recognize subroutine. This routine is called by the smart tag host application. In Word, for example, the recognizer is called when the user presses the Spacebar, hits Return, or hits Tab. You might be wondering why the code removes question marks and carriage returns. For performance reasons, Word buffers user input by creating a memory allocation and filling the blank space in the memory allocation with the Unicode character FFFC. This character appears as question marks. The code in your Recognize subroutine must therefore remove these question marks at the end of the string and also in middle of strings because the character is used as a placeholder for images and/or OLE objects. The code then removes any carriage returns from the string at the end to make tokenizing the string easier.

The next step is to convert the incoming text to uppercase so the code doesn't run into case issues. The code then loops through the categories from the Training application, checking the text passed to see whether any of it matches a category. Notice that the code does not stop after a single recognition. It continues because the text passed to your application might be an entire sentence or a paragraph, which could contain multiple instances of the phrase. The code also checks before and after the recognized word for spaces or blank characters. It does this because a category might be common letters embedded in a word that has nothing to do with the Training application. For example, if one of the categories in the application is MIS, you do not want to have the application match on the word mistakes . The code stops this from happening. This also means that categories must be single words with no spaces. You can code around this by looking for complete words, but the sample does not have this capability.

Next the code asks the RecognizerSite object to return a new property bag. This property bag contains name/value pairs that you can use to store and pass information to the actions for your smart tag, as you'll see in the action component later in this chapter. Once the property bag is returned, the application writes the key name and the key value to the property bag, which in this case is the URL to the Training application. The next step in the application is to commit the smart tag to the smart tag host. This operation is performed by calling the CommitSmartTag method.

All recognizers are stored in the registry under HKEY_CURRENT_USER \Software\Microsoft\Office\Common\Smart Tag\Recognizers\. Therefore, when you create a new recognizer, you must compile and register your DLL and then add either the ProgID or CLSID of your recognizer as a new key in this part of the registry. You should use the CLSID to register your component because registering it using the ProgID does not retain the user settings as to whether the user enabled or disabled the smart tag by using the AutoCorrect interface in Office between Office application sessions. This is a known bug with ProgID registrations. After you use the CLSID to register your component, you can try out your new recognizer in Word or Excel. Note, however, that when you work with smart tags, Excel matches entire cell values only, which means that if the entire cell value is not the value you recognize, the cell will not be tagged.

Note  

Because Office runs recognition of smart tags on a background thread, it might take some time for Office applications to recognize your smart tags. Actions, on the other hand, are run in an active, foreground thread.

Now that we have a recognizer, we need to create a corresponding action for it. To do this, we can create another ActiveX DLL, or we can just add another module to our existing DLL. To create an action, all you do is implement the ISmartTagAction interface. This interface is very straightforward and is described in Table 9-5.

Table 9-5: Elements of the ISmartTagAction Interface

Element

Description

Desc

A string that specifies what the action does. You are passed the locale ID of the text being passed to your DLL so that you can localize the description.

Name

A string that specifies the name of the action.

ProgID

A string that specifies the ProgID of the action DLL.

SmartTagCaption

A string that specifies the caption to use for the action in the smart tag actions user interface. You are passed a smart tag ID and a locale ID. If your action is used by multiple smart tags, this method will be called with the recognizer's unique ID so you can customize the caption for each recognizer.

SmartTagCount

An integer that specifies the number of smart tag types supported by this DLL.

SmartTagName

A string value that specifies the smart tag types this DLL supports. This string must be in the format namespaceURI#tagname , as in trainingapp#categories .

VerbCaptionFromID

A string value that specifies the caption to use for your action in the action's drop-down list. This call passes three parameters. The first is the VerbID , which is the unique identifier for the verb. The second is the ProgID of the application. The third is the locale ID. You can disable actions by not setting this property for a particular action.

VerbCount

An integer that specifies the number of verbs this DLL supports.

VerbID

An integer property that is a unique identifier for your verbs. You are passed the smart tag name, such as trainingapp#categories , and a verbindex that is a unique identifier for your verb. The easiest way to handle this property is to pass back the verbindex passed to you as the value for this property.

VerbNameFromID

A string property that specifies a language- agnostic identifier for a verb. You are passed the VerbID .

InvokeVerb

A method that is called when a verb is invoked. It allows you to implement the functionality for that verb. The method is passed six parameters. The first is the VerbID . The second is the application name of the host, such as Word.Application.10. The third is an object that is the application-specific object responsible for calling the action. In Excel, this object is a Cell object, and in Word this object is a Range object. The next parameter is the property bag passed by the recognizer or by the action itself. The next parameter is the text of the smart tag. The final parameter is an XML representation of the smart tag.

The following code defines the actions for the recognizer we created earlier. This action DLL supports two verbs. Both verbs launch a new instance of Internet Explorer and take the user to the Web site that is passed from the recognizer to the action DLL in the property bag.

Implements ISmartTagAction Private Property Get ISmartTagAction_ProgId() As String 'Create a language-independent unique identifier 'that corresponds to the ProgID of this DLL. ISmartTagAction_ProgId = "STTrainingApp.Actions" End Property Private Property Get ISmartTagAction_Name _ (ByVal LocaleID As Long) As String 'Add a short phrase that describes this action provider DLL. ISmartTagAction_Name = "Training Application Actions" End Property Private Property Get ISmartTagAction_Desc _ (ByVal LocaleID As Long) As String 'Create a longer description of this recognizer. ISmartTagAction_Desc = "Provides actions for " & _ "Training Application smart tag" End Property Private Property Get ISmartTagAction_SmartTagCount() As Long 'How many smart tag types will this recognizer support? '1 in this case. ISmartTagAction_SmartTagCount = 1 End Property Private Property Get ISmartTagAction_SmartTagName _ (ByVal SmartTagID As Long) As String If (SmartTagID = 1) Then ISmartTagAction_SmartTagName = "trainingapp#categories" End If End Property Private Property Get ISmartTagAction_SmartTagCaption _ (ByVal SmartTagID As Long, _ ByVal LocaleID As Long) As String 'Specify the caption for smart tag(s) we support. ISmartTagAction_SmartTagCaption = "Categories" End Property Private Property Get ISmartTagAction_VerbCount _ (ByVal SmartTagName As String) As Long 'For a given smart tag type, how many verbs do we support? If (SmartTagName = "trainingapp#categories") Then ISmartTagAction_VerbCount = 2 End If End Property Private Property Get ISmartTagAction_VerbID _ (ByVal SmartTagName As String, _ ByVal VerbIndex As Long) As Long ISmartTagAction_VerbID = VerbIndex End Property Private Property Get ISmartTagAction_VerbCaptionFromID _ (ByVal VerbID As Long, _ ByVal ApplicationName As String, _ ByVal LocaleID As Long) As String Select Case VerbID Case 1 ISmartTagAction_VerbCaptionFromID = _ "View Training Application" Case 2 'If we only wanted to support Excel 'If ApplicationName = "Excel.Application.10" Then ISmartTagAction_VerbCaptionFromID = _ "View Training Courses for this month" 'End If End Select End Property Private Property Get ISmartTagAction_VerbNameFromID _ (ByVal VerbID As Long) As String Select Case VerbID Case 1 ISmartTagAction_VerbNameFromID = "ViewTrainingApp" Case 2 ISmartTagAction_VerbNameFromID = "ViewMonthCourses" End Select End Property Public Sub ISmartTagAction_InvokeVerb _ (ByVal VerbID As Long, ByVal ApplicationName As String, _ ByVal Target As Object, _ ByVal Properties As SmartTagLib.ISmartTagProperties, _ ByVal Text As String, ByVal XML As String) On Error Resume Next 'If you want to retrieve the location of the text, 'use the following code: 'If ApplicationName = "Word.Application.10" Then ' Dim rWord As Word.Range ' Set rWord = Target 'ElseIf ApplicationName = "Excel.Application.10" Then ' Dim rExcel As Excel.Range ' Dim oWorksheet As Excel.Worksheet ' Set rExcel = Target ' Set oWorksheet = rExcel.Worksheet 'End If Select Case VerbID Case 1 'Get the URL to the training app from the PropertyBag strTrainingURL = Properties.Read("TrainingAppURL") If strTrainingURL <> "" Then Set oIE = CreateObject("InternetExplorer.Application") If Right(strTrainingURL, 1) <> "/" Then strTrainingURL = strTrainingURL & "/" End If oIE.Navigate2 (strTrainingURL) oIE.Visible = True End If Case 2 'Show the courses for this month 'Get the URL to the training app from the PropertyBag strTrainingURL = Properties.Read("TrainingAppURL") If strTrainingURL <> "" Then Set oIE = CreateObject("InternetExplorer.Application") If Right(strTrainingURL, 1) <> "/" Then strTrainingURL = strTrainingURL & "/" End If oIE.Navigate2 (strTrainingURL & _ "calendar.asp?Date=Month&Command=Init") oIE.Visible = True End If End Select End Sub

As you can see, the code is straightforward. The most interesting piece of the code is the InvokeVerb method, which actually performs the functionality for our actions. Figure 9-5 shows the recognizer and action DLL working in Word.

Figure 9-5: Our recognizer and action DLL working in Word

Категории