If you developed smart tags in Office XP, you'll be interested in the changes in Office 2003.

Smart tag technology links text to resources that provide relevant information useful in creating a document. Or even better, relevant information can be inserted right into the document itself. Smart tags in Microsoft Office 2003 have been improved to make them even easier to develop, and they conquer a few limitations.

Smart tags were introduced in Microsoft Office XP, providing a new way to make more meaningful data in documents. A major change in Office 2003, the number of applications supporting smart tags has increased. In Office XP, smart tags were supported in Word, Excel, Outlook (with Word as the e-mail editor), and Internet Explorer, to a limited extent. In Office 2003, all these applications are supported and both PowerPoint 2003 and Access 2003 have been added.

New features have been added to the Microsoft Office Smart Tag Lists (MOSTL). MOSTL provides the capability to define smart tag recognizers in XML. Although it's not as flexible as implementing smart tags in a programming language, it's great when you have an easily defined list of words or phrases to be recognized. You can use regular expressions to define search patterns for your recognizer and you'll see a few examples using MOSTL and regular expressions later in this article.

Office 2003 smart tags now support cascading menus and dynamic captions.

In addition, the API library has been extended, supporting several new interfaces and enabling new functionality. The Microsoft Smart Tags 2.0 Type Library is backward compatible with the 1.0 version, allowing you to develop smart tags that work in both Office XP and Office 2003. This type library and an example of implementing a smart tag in .NET are discussed in more detail later in this article.

An Introduction to Smart Tags

Smart Tags identify words or phrases within a document, and several are provided with Microsoft Office. For a list of existing smart tags, and to enable and disable smart tags, go to Tools (from within any of the applicable Office 2003 applications) and then choose Auto Correct Options. Click on the Smart Tags tab and you'll see a list of available smart tags.

To experiment, enable the Financial Symbols smart tag. Then enter a stock symbol, such as MSFT, in a Word 2003 document. When the symbol is recognized, smart tags make a red-dotted underline under it. When you hover your mouse pointer over it, you'll see an information icon. Clicking on the icon displays a drop-down menu, as shown in Figure 1. The menu shows a list of actions relevant to the financial symbol.

Figure 1: The smart tag shows the financial symbol and its smart tag drop-down menu.
Figure 1: The smart tag shows the financial symbol and its smart tag drop-down menu.

Another smart tag might look up contact information in your Outlook 2003 contact list. Figure 2 shows the drop-down menu and the actions available with that smart tag.

Figure 2: The Outlook Contact List smart tag drop-down menu includes common tasks.
Figure 2: The Outlook Contact List smart tag drop-down menu includes common tasks.

Although these are good examples of smart tags in action, the number of provided smart tags is limited. It is possible to create your own smart tags using MOSTL or by developing them in a programming language. Then the possibilities of what you can do with smart tags are virtually endless!

Microsoft Office Smart Tag Lists (MOSTL)

Smart tag lists define smart tag recognizers and actions in XML. For example, you can create a MOSTL file that recognizes the terms VB.NET, C#, ADO.NET, and ASP.NET. The smart tag links to the MSDN Library Web site using a listing like the one you'll see in Listing 1.

This XML file needs to be stored in the directory C:\Program Files\Common Files\Microsoft Shared\Smart Tags\Lists.

Smart tags have been deployed in many industries such as finance, healthcare, and manufacturing.

If any Office 2003 applications are open, you must close them and re-open them to get the new smart tag recognized. Once you have done this, the new smart tag shows up on the Smart Tags tab of the Auto Correct dialog box (via the Tools menu). As long as that smart tag is enabled, when you enter any of the terms the smart tag recognizes, you'll be able to link to the MSDN Library Web site, as shown in Figure 3.

Figure 3: The custom smart tag defined in Listing 1 allows access to the MSDN Library for the term ADO.NET.
Figure 3: The custom smart tag defined in Listing 1 allows access to the MSDN Library for the term ADO.NET.

MOSTL and Regular Expressions

Regular expressions are a powerful form of wildcard searches. Most developers (and even power users) are familiar with regular expressions used to search for files, such as *.doc. When it comes to regular expression pattern matching, you will need more sophisticated patterns. The following pattern matches US phone numbers within a text string.

((\(\d{3}\))|(\d{3}-))?\d{3}-\d{4}

If you are not familiar with regular expressions, you might find this but of code a little difficult to read. Let's take a brief look at the syntax of regular expressions. Table 1 lists the most common meta-characters that are used in regular expression patterns.

Examine this by breaking down the phone number pattern shown above. Start at the end of the pattern:

\d{3}-\d{4}

This means that the expression must contain exactly three digits, followed by a hyphen, and then exactly four digits. Thus, 555-1234 is a match. Now look at the first part:

((\(\d{3}\))|(\d{3}-))?

Notice that there is a pipe (|) in the middle, indicating an or operator. On the right side of that you can see:

(\d{3}-)

This will match exactly three digits followed by a hyphen. On the left side of the or (|) you see:

(\(\d{3}\))

Notice that ( and ) are used to indicate that parenthesis are part of the pattern. In between these is the \d{3} indicating exactly three digits. So the pattern matches phone numbers in these formats:

(281)866-7444
281-866-7444

This portion of the pattern ends with a question mark, indicating that the pattern immediately prior to the question mark is optional. Because the area code pattern is grouped in parentheses and the question mark is outside the parentheses, the entire pattern inside the parentheses is optional. The pattern will also be a match:

866-7444

You could get even more sophisticated and match 281.866.7444 in addition to allowing a space between the various parts of the phone number and match foreign phone numbers.

Here's another example. Let's say you use a bug-tracking Web site to track issues that need to be addressed in your current project. You can define a smart tag that recognizes “Bug #123456” or “bug 123456” and link directly to that bug's details on the Web site. Here is the regular expression that matches these phrases:

[B|b]ug\s(#){0,1}\d{6}

You can create a smart tag definition to recognize this pattern and link to the Web site. It looks like Listing 2. Note that the URL in this example is a placeholder that should be replaced with the URL to your bug-tracking Web site. The resulting smart tag menu is shown in Figure 4.

Figure 4: The result of our example is this customized IP Address smart tag.
Figure 4: The result of our example is this customized IP Address smart tag.
Figure 5: A little bit of code leads to the custom bug tracking smart tag.
Figure 5: A little bit of code leads to the custom bug tracking smart tag.

For a great in-depth look at regular expressions, look at the May/June 2003 issue of CoDe for an article by Jim Duffey called “Getting Started With Regular Expressions.” Also, you can read Markus Egger's white paper on MSDN, entitled “Regular Expression Support in Microsoft Office System Smart Tags,” posted in August 2003.

Developing Custom Smart Tags in .NET

Since the release of Office XP, developers have been able to build custom smart tags. You can get the Office XP Smart Tag SDK Version 1.1 at: http://www.microsoft.com/downloads.

The Office XP SDK contains the documentation and samples for creating smart tags in Office XP and for Office 2003. There is also a new type library (Microsoft Smart Tags 2.0 Type Library, which adds new functionality for the new smart tag features in Office 2003. This type library will be available on MSDN when Office 2003 is released.

To implement smart tags, you'll typically create two classes: a Recognizer class and an Action class. (It is possible to create smart tags for special purposes that only have a Recognizer or an Action class, but that is beyond the scope of this article.) You can place both classes in the same DLL or create them in separate DLLs. In the example implemented later in this article, they will be in the same DLL.

The Recognizer class must implement the ISmartTagRecognizer interface. Table 2 lists the properties and methods in the ISmartTagRecognizer interface.

If you want to take advantage of the new smart tag features in Office 2003, you must also implement the ISmartTagRecognizer2 interface. One of the new features is a new Recognize method (Recognize2) that simplifies identifying recognized text and allows you to identify the application being used. Table 2 shows the properties and methods for the ISmartTagRecognizer2 interface.

The Action class must implement the ISmartTagAction interface. Table 4 displays the properties and methods for this interface.

If you want to take advantage of the new smart tag features in Office 2003, you must also implement the ISmartTagAction2 interface. This allows you to create cascading menus, use dynamic captions, and so forth. Table 5 displays the properties and methods for this interface.

Building the Smart Tag Recognizer

Now that you have looked at the interfaces to implement, let's get started creating the smart tag. You will build the smart tag using Visual Basic .NET (VB.NET). First, you need to start a new VB.NET Class Library project. Then add a reference to the Microsoft Smart Tags 2.0 Type Library to the project. This type library is on the COM tab of the Add Reference dialog box, as shown in Figure 6. Note that you don't have to add both the 1.0 and 2.0 versions. Version 2.0 of the type library has all the necessary interfaces.

Figure 6: The Add Reference dialog box shows that the Smart Tags 2.0 Type Library is selected.
Figure 6: The Add Reference dialog box shows that the Smart Tags 2.0 Type Library is selected.

Next, you'll need to add two Imports statements to the top of the source code:

Imports SmartTagLib
Imports System.Runtime.InteropServices

You need System.Runtime.InteropServices, as smart tags use COM Interop. And you'll need to register the DLL so that the Office applications can find it. Next, you'll create the Recognizer class. The entire code for the class is shown in Listing 3. I'll break down the less self-explanatory elements here.

The first things to look at are the ProgID, GUID, and ComVisible attributes applied to the class. These are for use by COM Interop services. You can create a GUID using the Create GUID option on the Tools menu. Use option 4. Registry Format… to generate the correct style for use here. Notice that the curly brackets have been removed, a necessary step to prevent compile errors.

The class is named Recognizer and implements both Recognizer interfaces. I have added a Public Sub New constructor to the class, necessary for COM Interop. Following the constructor, there are several properties that are pretty self-explanatory. Notice that the Recognize method is not implemented. Instead, you'll use the Recognize2 method, and you'll take a look at this method a little later. Next, there are a few more self-explanatory properties. The one that takes a little explanation is the SmartTagName property.

The SmartTagName property is the unique identifier for the smart tag type(s) that the recognizer supports. Each smart tag type is defined by a namespace to keep it unique. A namespace is an XML construct uniquely identifying a group of XML tags belonging to a logical category. A namespace groups related properties together for easy property discovery and, more importantly, to keep the property names unique.

Office 2003 adds smart tag support to PowerPoint 2003 and Access 2003.

Property names are constructed from a namespace URI and a tag name of the namespace URI.

Similarly, smart tag types are defined by a unique namespace URI plus its tag name. A pound character (#) is added to the namespace URI and is used to separate the namespace URI from its tag name.

For this example, you'll be using a smart tag of the type urn:samples-msdn-microsoft-com#MySmartTag. The namespace URI is urn:schemas-microsoft-com, and MySmartTag is the tag name. The type and name are combined to form a fully qualified name for the property, which, in this case, is a smart tag type.

As can been seen, the name is a fully qualified description of an XML tag. Every smart tag type is uniquely identified by its tag name in addition to its namespace.

The URI portion of the property name ensures that it is globally unique and unambiguous. Two properties with the same tag name can be differentiated using namespaces.

The role of an ISmartTagRecognizer is to assign smart tag types to data. For example, the recognizer sees the string SmartTag and assigns to it the smart tag type urn:samples-msdn-microsoft-com#MySmartTag, as you'll see in the Recognize2 method.

Now look at the Recognize2 method. This is where the real recognizer is implemented. Look for the term SmartTag in the text. If you find it, you collect some information and store it in a RecognizerSite PropertyBag object. Then you call the CommitSmartTag method of the RecognizerSite object passing the smart tag type as the first parameter. This is what “tags” the text as recognized.

Building the Smart Tag Action

Now that you recognize the terms, you need to build the actions. The code for the Action class is shown in Listing 4.

Again, use the attributes necessary for COM Interop. Make sure to generate a different GUID for the Action class. The properties for the Action class are similar to those found in the Recognizer class.

The Action class uses verbs corresponding with the menu options you define to be displayed in the on-application menu. The VerbCount property defines how many verbs your Action class supports.

Because you are only supporting one smart tag in this example, the VerbID property just returns the VerbIndex. The ShowSmartTagIndicator property defines whether the recognized terms are underlined, like regular smart tags. In most cases you'll want this, so return True for this property.

The VerbCaptionFromID property is called one time for each verb you are supporting: six, in this case. It takes a VerbID as a parameter, which is used in the CASE statement to build the cascading menu.

Now take a look at the InvokeVerb2 method. In the example, you collect information gathered in the Recognizer class along with the VerbID and Application Name, and you display a message box with this information.

Now you can compile the DLL. Before you test it, you must first register the two classes with the Office 2003 smart tag infrastructure so that the Office 2003 applications will know to use the smart tag.

Registering Smart Tag Classes

There are two ways to register your smart tag classes with the smart tag infrastructure. One way is to manually add keys to the HKEY_CURRENT_USER\Software\Microsoft\Office\Common\Smart Tag registry key. There is a key for Recognizers and a key for Actions. You need to add a new key to each section for the appropriate class using the GUIDs specified in the class attributes in your code. Make sure to add the curly brackets back to the GUIDs in these keys.

The second way to do this is to add code that uses reflection to your classes in order to register the smart tag at the same time the smart tag is registered with COM. This is the preferred method, especially if you will be distributing your smart tags. But it takes a bit of code to do it. To see how this is done, refer to the Technical Article on MSDN named Building Smart Tags in Microsoft Visual Basic .NET by J Sawyer.

Summary

Smart tags have been improved quite a bit in Office 2003. And more Office 2003 applications support smart tags than in Office XP. Developers get new flexibility in creating smart tags using MOSTL combined with regular expressions to define Recognizers. You also get a lot of power developing smart tags in VB.NET or C# with the new version of the Smart Tags 2.0 Type Library.

Listing 1: XML defining the recognizer, VB.NET, C#, ADO.NET, and ASP.NET

<FL:smarttaglist xmlns:FL="urn:schemas-microsoft-com:smarttags:list">
  <FL:name>.NET Products</FL:name>
  <FL:lcid>1033</FL:lcid>
  <FL:description>Recognizes 3 .NET terms</FL:description>
  &lt;FL:moreinfourl&gt;<a href="http://msdn.microsoft.com/library/default.asp";>http://msdn.microsoft.com/library/default.asp<;/a>&lt;/FL:moreinfourl&gt;
  
  &lt;FL:smarttag type="urn:schemas-manualtags#msproducts"&gt;
    &lt;FL:caption&gt;Microsoft .NET Products&lt;/FL:caption&gt;
    &lt;FL:terms&gt;
      &lt;FL:termlist&gt;VB.NET,C#,ADO.NET,ASP.NET&lt;/FL:termlist&gt;
    &lt;/FL:terms&gt;
    &lt;FL:actions&gt;
      &lt;FL:action id="ms"&gt;
        &lt;FL:caption&gt;MSDN Library&lt;/FL:caption&gt;
        &lt;FL:url&gt;<a href="http://msdn.microsoft.com/library/default.asp";>http://msdn.microsoft.com/library/default.asp<;/a>&lt;/FL:url&gt;
      &lt;/FL:action&gt;
    &lt;/FL:actions&gt;
  &lt;/FL:smarttag&gt;
&lt;/FL:smarttaglist&gt;

Listing 2: XML defining the recognizer for a BUG entry

&lt;FL:smarttaglist xmlns:FL="urn:schemas-microsoft-com:smarttags:list"&gt;
  &lt;FL:name&gt;Bugs&lt;/FL:name&gt;
  &lt;FL:lcid&gt;1033&lt;/FL:lcid&gt;
  &lt;FL:description&gt;Recognizes references to bugs&lt;/FL:description&gt;

  &lt;FL:smarttag type="urn:schemas-manualtags#bugs"&gt;
    &lt;FL:caption&gt;Link to Bug Web Site&lt;/FL:caption&gt;
    &lt;FL:re&gt;
      &lt;FL:exp&gt;[B|b]ug\s(#){0,1}\d{6}&lt;/FL:exp&gt;
    &lt;/FL:re&gt;
    &lt;FL:actions&gt;
      &lt;FL:action id="bug"&gt;
        &lt;FL:caption&gt;Open the Bug Database&lt;/FL:caption&gt;
        &lt;FL:url&gt;<a href="http://www.MyUrl.com/ShowBug.aspx?id=";>http://www.MyUrl.com/ShowBug.aspx?id=<;/a>{TEXT}&lt;/FL:url&gt;
      &lt;/FL:action&gt;
    &lt;/FL:actions&gt;
  &lt;/FL:smarttag&gt;
&lt;/FL:smarttaglist&gt;

Listing 3: The code for the Recognizer class

&lt;ProgId("MySmartTag.Recognizer"), _
  Guid("57D8FC4A-4ED8-43c9-9716-7D378D03F2FC"), _
  ComVisible(True)&gt; _
Public Class Recognizer
  Implements ISmartTagRecognizer
  Implements ISmartTagRecognizer2

  ' this is requred for com interop
  Public Sub New()

  End Sub

  Public ReadOnly Property Desc(ByVal LocaleID As Integer) As _
    String Implements SmartTagLib.ISmartTagRecognizer.Desc
      Get
        Return "My first smart tag description."
      End Get
  End Property

  Public ReadOnly Property Name(ByVal LocaleID As Integer) As _
    String Implements SmartTagLib.ISmartTagRecognizer.Name
      Get
        Return "My first smart tag name."
      End Get
  End Property

  Public ReadOnly Property ProgId() As String _
    Implements SmartTagLib.ISmartTagRecognizer.ProgId
      Get
        Return "MySmartTag.Recognizer"
      End Get
    End Property
  
  Public Sub Recognize(ByVal strRecText As String, _ 
    ByVal DataType As SmartTagLib.IF_TYPE, _
    ByVal LocaleID As Integer, _
    ByVal RecognizerSite As SmartTagLib.ISmartTagRecognizerSite) _
    Implements SmartTagLib.ISmartTagRecognizer.Recognize

      ' we are not using this method, see Recognize2
  End Sub

  ' we are only supporting 1 smart tag
  Public ReadOnly Property SmartTagCount() As Integer _
    Implements SmartTagLib.ISmartTagRecognizer.SmartTagCount
      Get
        Return 1
      End Get
  End Property

  ' we are not supporting a download url
  Public ReadOnly Property SmartTagDownloadURL _
    (ByVal SmartTagID As Integer) As String _
    Implements SmartTagLib.ISmartTagRecognizer.SmartTagDownloadURL
      Get
        Return ""
      End Get
  End Property

  Public ReadOnly Property SmartTagName _
    (ByVal SmartTagID As Integer) As String _
    Implements SmartTagLib.ISmartTagRecognizer.SmartTagName
      Get
        Return "urn:samples-msdn-microsoft-com#MySmartTag"
      End Get
  End Property

  ' we are not supporting a property page
  Public Sub DisplayPropertyPage(ByVal SmartTagID As Integer, _
   ByVal LocaleID As Integer) _
   Implements SmartTagLib.ISmartTagRecognizer2.DisplayPropertyPage

  End Sub

  ' we are not supporting a property page
  Public ReadOnly Property PropertyPage _
    (ByVal SmartTagID As Integer, _
     ByVal LocaleID As Integer) As Boolean _
     Implements SmartTagLib.ISmartTagRecognizer2.PropertyPage
      Get

      End Get
  End Property

  Public Sub Recognize2(ByVal strRecText As String, _
   ByVal DataType As SmartTagLib.IF_TYPE, _
   ByVal LocaleID As Integer, _
   ByVal RecognizerSite2 As SmartTagLib.ISmartTagRecognizerSite2, _
   ByVal ApplicationName As String, _
   ByVal TokenList As SmartTagLib.ISmartTagTokenList) _
   Implements SmartTagLib.ISmartTagRecognizer2.Recognize2

    Dim intLocation As Integer = _
      InStr(strRecText, "SmartTag", CompareMethod.Text)

    If intLocation &gt; 0 Then
        Dim stPropBag As ISmartTagProperties = _
          RecognizerSite2.GetNewPropertyBag()
        Dim strPropType As String

        Select Case DataType
          Case IF_TYPE.IF_TYPE_CELL
            strPropType = "IF_TYPE_CELL"
          Case IF_TYPE.IF_TYPE_CHAR
            strPropType = "IF_TYPE_CHAR"
          Case IF_TYPE.IF_TYPE_PARA
            strPropType = "IF_TYPE_PARA"
          Case IF_TYPE.IF_TYPE_REGEXP
            strPropType = "IF_TYPE_REGEXP"
          Case IF_TYPE.IF_TYPE_SINGLE_WD
            strPropType = "IF_TYPE_SINGLE_WD"
        End Select

        stPropBag.Write("DataType", strPropType)
        stPropBag.Write("LocalID", LocaleID.ToString())
        RecognizerSite2.CommitSmartTag _
          ("urn:samples-msdn-microsoft-com#MySmartTag", _
            intLocation, 8, stPropBag)
    End If
  End Sub

  ' we are not implementing the initialize method
  Public Sub SmartTagInitialize(ByVal ApplicationName As String) _
    Implements SmartTagLib.ISmartTagRecognizer2.SmartTagInitialize

  End Sub
End Class

Listing 4: The code for the Action class

&lt;ProgId("MySmartTag.Action"), _
    Guid("C1751811-6739-4614-AB28-9FB9E988A630"), _
    ComVisible(True)&gt; _
Public Class Action
    Implements ISmartTagAction
    Implements ISmartTagAction2

  ' this is requred for com interop
  Public Sub New()

  End Sub

  Public ReadOnly Property Desc(ByVal LocaleID As Integer) _
    As String Implements SmartTagLib.ISmartTagAction.Desc
      Get
        Return "My SmartTag Action Description"
      End Get
  End Property

  Public Sub InvokeVerb(ByVal VerbID As Integer, _
    ByVal ApplicationName As String, _
    ByVal Target As Object, _
    ByVal Properties As SmartTagLib.ISmartTagProperties, _
    ByVal strText As String, _
    ByVal Xml As String) _
    Implements SmartTagLib.ISmartTagAction.InvokeVerb

      ' we are not using this method, see InvokeVerb2
  End Sub

  Public ReadOnly Property Name(ByVal LocaleID As Integer) _
    As String Implements SmartTagLib.ISmartTagAction.Name
      Get
        Return "My SmartTag Action"
      End Get
  End Property

  Public ReadOnly Property ProgId() As String _
    Implements SmartTagLib.ISmartTagAction.ProgId
      Get
        Return "MySmartTag.Action"
      End Get
  End Property

  Public ReadOnly Property SmartTagCaption _
    (ByVal SmartTagID As Integer, _
     ByVal LocaleID As Integer) As String _
     Implements SmartTagLib.ISmartTagAction.SmartTagCaption
      Get
        Return "My Smart Tag Caption"
      End Get
  End Property

  ' we are only supporting 1 smart tag
  Public ReadOnly Property SmartTagCount() As Integer _
    Implements SmartTagLib.ISmartTagAction.SmartTagCount
      Get
        Return 1
      End Get
  End Property

  ' use the same smart tag name as the recognizer
  Public ReadOnly Property SmartTagName _
    (ByVal SmartTagID As Integer) As String _
    Implements SmartTagLib.ISmartTagAction.SmartTagName
      Get
        Return "urn:samples-msdn-microsoft-com#MySmartTag"
      End Get
  End Property

  Public ReadOnly Property VerbCaptionFromID _
    (ByVal VerbID As Integer, _
     ByVal ApplicationName As String, _
     ByVal LocaleID As Integer) As String _
     Implements SmartTagLib.ISmartTagAction.VerbCaptionFromID
      Get
  ' we are not using this method, see VerbCaptionFromID2
      End Get
  End Property

  ' we are using 6 verbs in a cascading menu
  ' see VerbCaptionFromID2
  Public ReadOnly Property VerbCount _
    (ByVal SmartTagName As String) As Integer _
    Implements SmartTagLib.ISmartTagAction.VerbCount
      Get
        Return 6
      End Get
  End Property

  ' to get the verb id, just return the VerbIndex
  Public ReadOnly Property VerbID(ByVal SmartTagName As String, _
    ByVal VerbIndex As Integer) As Integer _
    Implements SmartTagLib.ISmartTagAction.VerbID
      Get
        Return VerbIndex
      End Get
  End Property

  Public ReadOnly Property VerbNameFromID _
    (ByVal VerbID As Integer) As String _
    Implements SmartTagLib.ISmartTagAction.VerbNameFromID
      Get
        Return "ShowTag"
      End Get
  End Property

  Public ReadOnly Property IsCaptionDynamic _
    (ByVal VerbID As Integer, _
     ByVal ApplicationName As String, _
     ByVal LocaleID As Integer) As Boolean _
     Implements SmartTagLib.ISmartTagAction2.IsCaptionDynamic
      Get
        Return False
      End Get
  End Property

  ' This is necessary to underline the text the smart tag
  ' recognized.
  Public ReadOnly Property ShowSmartTagIndicator _
    (ByVal VerbID As Integer, _
     ByVal ApplicationName As String, _
     ByVal LocaleID As Integer) As Boolean _
     Implements SmartTagLib.ISmartTagAction2.ShowSmartTagIndicator
      Get
        Return True
      End Get
  End Property

  ' we are not implementing the initialize method
  Public Sub SmartTagInitialize(ByVal ApplicationName As String) _
    Implements SmartTagLib.ISmartTagAction2.SmartTagInitialize

  End Sub

  ' build the cascading menu for the on-application menu
  Public ReadOnly Property VerbCaptionFromID2 _
    (ByVal VerbID As Integer, _
     ByVal ApplicationName As String, _
     ByVal LocaleID As Integer, _
     ByVal Properties As SmartTagLib.ISmartTagProperties, _
     ByVal Text As String, _
     ByVal Xml As String, _
     ByVal Target As Object) As String _
     Implements SmartTagLib.ISmartTagAction2.VerbCaptionFromID2
      Get
        Dim lcString As String

        Select Case VerbID
          Case 1
            lcString = "Test 1///Show My Smart Tag Verb ID 1"
          Case 2
            lcString = "Test 1///Show My Smart Tag Verb ID 2"
          Case 3
            lcString = "Test 2///Show My Smart Tag Verb ID 3"
          Case 4
            lcString = "Test 2///Show My Smart Tag Verb ID 4"
          Case 5
            lcString = "Test 3///Show My Smart Tag Verb ID 5"
          Case 6
            lcString = "Test 3///Show My Smart Tag Verb ID 6"
        End Select

        Return lcString
      End Get
  End Property

  ' our action just displays a messagebox of information
  ' collection during recognition
  Public Sub InvokeVerb2(ByVal VerbID As Integer, _
    ByVal ApplicationName As String, _
    ByVal Target As Object, _
    ByVal Properties As SmartTagLib.ISmartTagProperties, _
    ByVal strText As String, _
    ByVal Xml As String, _
    ByVal LocaleID As Integer) _
    Implements SmartTagLib.ISmartTagAction2.InvokeVerb2
      Dim strMsg As String = strText
      Dim i As Integer

      For i = 0 To Properties.Count - 1
        strMsg &amp;= vbCrLf &amp; Properties.KeyFromIndex(i) &amp; "=" &amp; _
          Properties.ValueFromIndex(i)
      Next

      ' add the Verb ID and Application Name
      strMsg &amp;= vbCrLf &amp; "Verb ID=" &amp; VerbID
      strMsg &amp;= vbCrLf &amp; "Application=" &amp; ApplicationName
      MsgBox(strMsg, MsgBoxStyle.Information, "My SmartTag Action")
  End Sub
End Class

Table 1: This Smart Tag Meta-character listing will make it easy to follow the exploration.

Meta-CharacterMeaning
Character Matching
. (period)Matches any single character except the newline character
[]Matches any one of the enclosed characters. Ranges can be specified by using a hyphen, such as [0-9]
|The OR operator. For example, x|y will match either x or y
Position Matching
^Matches the beginning of string
$Matches the end of string
Repetition Matching
?Matches 0 or 1 instances of the preceding character
+Matches 1 or more instances of the preceding character
\Indicates that the next character should not be interpreted as a regular expression special character
*Matches 0 or more instances of the preceding character
()Groups a series of characters together
{n}Matches exactly n instances of the preceding character
{n,}Matches at least n instances of the preceding character
{n,m}Matches at lease n but no more than m instances of the preceding character
Special Characters
\sMatches any single white space character, including space, tab, line feed, and form feed
\wMatches any alphanumeric character, including the underscore character
\dMatches a single-digit character
\fMatches a form feed
\nMatches a line feed
\rMatches a carriage return
\tMatches a tab
\vMatches a vertical tab
\bMatches a word boundary, such as a space

Table 2: ISmartTagRecognizer properties and methods

Property/Method NameTypeDescription
ProgIDStringThe programmatic identifier of the recognizer interface
NameStringA short title reflecting what the recognizer does
DescStringA longer description of what the recognizer does
SmartTagCountIntegerThe number of smart tag types that the recognizer supports
SmartTagDownloadURLStringThe URL embedded in documents to let users download new or updated actions
SmartTagNameStringThe unique identifiers of smart tag types that the recognizer supports
RecognizeN/AThe method that recognizes the terms

Table 3: ISmartTagRecognizer2 properties and methods

Property/Method NameTypeDescription
SmartTagInitializeN/AThe initialize method that is fired before any other event
Recognize2N/AA new Recognize method that simplifies identifying recognized text
PropertyPageStringDisplays a custom dialog box for configuring a smart tag through the smart tag's dialog box. This property tells the calling application that the smart tag supports customization
DisplayPropertyPageN/ACalled when the user requests configuring the smart tag

Table 4: ISmartTagAction properties and methods

Property/Method NameTypeDescription
ProgIDStringThe programmatic identifier of the DLL action interface
NameStringA short title reflecting what the action does
DescStringA longer description of what the action does
SmartTagCountIntegerThe number of smart tag types that the DLL supports
SmartTagNameStringThe unique string identifiers of smart tag types that the DLL supports
SmartTagCaptionStringA caption for a smart tag type for use in on-object menus
VerbCountIntegerThe total number of verbs supported by the DLL for a given smart tag type
VerbIDIntegerA unique integer identifier for a verb
VerbCaptionFromIDStringA caption for a smart tag type action for use in on-object menus
VerbNameFromIDStringA language-agnostic identifier string for a verb
InvokeVerbN/AThe method that is called to invoke a verb

Table 5: ISmartTagAction2 properties and methods

Property/Method NameTypeDescription
SmartTagInitializeN/AFires before any other event
ShowSmartTagIndicatorBooleanSpecifies if the smart tag underline indicator is displayed
IsCaptionDynamicBooleanIndicates if the caption for the action in the smart tag menu is dynamic. If so, the SmartTagInitialize method is called every time the menu is displayed.
VerbCaptionFromID2StringThe caption for an action menu item. Allows for cascading menus.
InvokeVerb2N/ASimilar to the InvokeVerb method, however this new method passes in a local ID (LCID for locale identification.