Building Smart Tags Using .NET


Note  

You should read the white paper "Building Smart Tags in Microsoft Visual Basic .NET" at http://msdn.microsoft.com/office before reading this section. This section includes information adapted from that white paper and also provides additional details.

Building smart tags in .NET is similar to building COM add-ins. The chief difference is that .NET doesn't include a wizard for smart tags, as it does for COM add-ins. You have to create the necessary references, event handlers, and code manually to build your smart tag.

Because the process is so similar, I'll show you one completed smart tag, written in Visual Basic .NET, to help get you started. The code in this section is from the DotNet Smart Tag sample application. In Visual Basic .NET, you create a class library. The smart tag contains a recognizer that recognizes the word Outlook and a single action that displays in a message box the information recognized, such as the data type, locale ID, and the text. Here's the code for the recognizer:

 Imports SmartTagLib Imports System.Runtime.InteropServices      <ProgId("DotNetSmartTag.Recognizer"), _ GuidAttribute("8981FE26-D112-402e-9A01-06C8A2F01207"), _ ComVisible(True)> Public Class Recognizer     Implements ISmartTagRecognizer          <ComRegisterFunction()> Shared Sub Register( _         ByVal RegKey As String)              RegSmartTag(RegKey, True)     End Sub          <ComUnregisterFunction()> Shared Sub Unregister( _         ByVal RegKey As String)              RegSmartTag(RegKey, False)     End Sub          'Default Constructor with no arguments     'Required for COM Interop     Public Sub New()     End Sub          'A substantive description of what the recognizer does.     Public ReadOnly Property Desc( _         ByVal LocaleID As Integer) As String _         Implements SmartTagLib.ISmartTagRecognizer.Desc              Get             Return "Sample DotNet Smart Tag"         End Get     End Property          'A short title reflecting what the recognizer does.     Public ReadOnly Property Name( _         ByVal LocaleID As Integer) As String _         Implements SmartTagLib.ISmartTagRecognizer.Name              Get             Return "DotNet Sample Smart Tag"         End Get     End Property          'The COM ProgID of the Smart Tag     Public ReadOnly Property ProgId() As String _         Implements SmartTagLib.ISmartTagRecognizer.ProgId              Get             Return "DotNetSmartTag.Recognizer"         End Get     End Property          'Recognizes terms.     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              Dim position As Integer         Dim lLength As Integer              'Remove any ????         lLength = Len(strRecText)         If (lLength > 0) Then             position = InStr(1, strRecText, ChrW(-4))         Else             position = 0         End If              While (lLength > 0 And position > 0)             Mid$(strRecText, position, 1) = ""             lLength = lLength - 1             If (lLength > 0) Then                 position = InStr(1, strRecText, ChrW(-4))             Else                 position = 0             End If             position = InStr(1, strRecText, ChrW(-4))         End While              strRecText = RTrim(strRecText)              position = InStr(1, strRecText, ChrW(-4))         If (position > 0) Then             lLength = Len(strRecText)             Mid$(strRecText, (lLength - position + 1)) = _                 Space$(lLength - position + 1)             strRecText = RTrim(strRecText)         End If              If Right(strRecText, 1) = ChrW(13) Then             strRecText = Left(strRecText, Len(strRecText) - 1)         End If              Dim intLocation As Integer = InStr(UCase(strRecText), _                                            UCase("Outlook"), _                                            CompareMethod.Binary)         If intLocation > 0 Then             Dim stPropBag As ISmartTagProperties = _                               RecognizerSite.GetNewPropertyBag()             Dim strPropType As String                  'Determine the data type (as a 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                  'Add the data to the propbag             stPropBag.Write("DataType", strPropType)             'Add the text so the function can receive it             stPropBag.Write("Text", strRecText)             'Add the LocaleID             stPropBag.Write("LocaleID", LocaleID)             'Commit the SmartTag             On Error Resume Next             RecognizerSite.CommitSmartTag( _                 "urn:thomriz:com#DotNetSmartTag", _                 intLocation, 7, stPropBag)         End If     End Sub          'The number of smart tag types that this recognizer supports     Public ReadOnly Property SmartTagCount() As Integer _         Implements SmartTagLib.ISmartTagRecognizer.SmartTagCount              Get             Return 1         End Get     End Property          'We have no download URL, so return empty     Public ReadOnly Property SmartTagDownloadURL( _         ByVal SmartTagID As Integer) As String _         Implements SmartTagLib.ISmartTagRecognizer.SmartTagDownloadURL              Get             Return ""         End Get     End Property          'The unique IDs of smart tag types the recognizer supports.     Public ReadOnly Property SmartTagName( _         ByVal SmartTagID As Integer) As String _         Implements SmartTagLib.ISmartTagRecognizer.SmartTagName              Get             Return "urn:thomriz:com#DotNetSmartTag"         End Get     End Property End Class 

Notice that the recognizer leverages the built-in COM interoperability features of the .NET platform. Otherwise , the recognizer looks like the standard recognizers we built using Visual Basic 6.0. The only difference is the register and unregister functions included for COM, which we will discuss in the next section. For the action, the code is as follows . (It is in a different class file.)

 Imports SmartTagLib Imports System.Runtime.InteropServices      <ProgId("DotNetSmartTag.Action"), _ GuidAttribute("A7253D8D-B8B0-4769-A8BB-65584AC3C9EF"), _ ComVisible(True)> _ Public Class Action     Implements ISmartTagAction          Public ReadOnly Property Desc( _         ByVal LocaleID As Integer) As String _         Implements SmartTagLib.ISmartTagAction.Desc              Get             Return "DotNet Smart Tag Action"         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              Dim strMsg As String = strText         Dim i As Short         For i = 0 To Properties.Count - 1             strMsg &= vbCrLf & Properties.KeyFromIndex(i)             strMsg &= "=" & Properties.ValueFromIndex(i)         Next         MsgBox(strMsg, , "DotNet Smart Tag")     End Sub          Public ReadOnly Property Name( _         ByVal LocaleID As Integer) As String _         Implements SmartTagLib.ISmartTagAction.Name              Get             Return "DotNet Action"         End Get     End Property          Public ReadOnly Property ProgId() As String _         Implements SmartTagLib.ISmartTagAction.ProgId              Get             Return "DotNetSmartTag.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 "DotNet Smart Tag"         End Get     End Property          Public ReadOnly Property SmartTagCount() As Integer _         Implements SmartTagLib.ISmartTagAction.SmartTagCount              Get             Return 1         End Get     End Property          Public ReadOnly Property SmartTagName( _         ByVal SmartTagID As Integer) As String _         Implements SmartTagLib.ISmartTagAction.SmartTagName              Get             Return "urn:thomriz:com#DotNetSmartTag"         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             Return "Show DotNet Smart Tag"         End Get     End Property          Public ReadOnly Property VerbCount( _         ByVal SmartTagName As String) As Integer _         Implements SmartTagLib.ISmartTagAction.VerbCount              Get             Return 1         End Get     End Property          Public ReadOnly Property VerbID( _         ByVal SmartTagName As String, _         ByVal VerbIndex As Integer) As Integer _         Implements SmartTagLib.ISmartTagAction.VerbID              Get             Return 1         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 End Class 

Again, the code looks like a standard smart tag action except for the COM interoperability. Building smart tags with .NET is easy because .NET performs all the interoperability work for you.

Automatic Registration with Reflection

One useful function that the sample application called DotNet Smart Tag provides is a function for the smart tag to register itself as a smart tag in the registry when .NET registers the DLL for COM interoperability. You do this through Reflection, which is the ability of your application to obtain information about itself or other components at run time. When .NET registers the DLL, the code contained in the recognizer's Register function fires and runs code that queries the component and places the information that's required to register the component as a smart tag recognizer in the registry. When the .NET component is unregistered, the opposite occurs, and the registry information is removed. The code for this functionality is shown in the following example and is explained more fully in the white paper cited at the beginning of this section.

 Imports Microsoft.Win32 Imports System.Runtime.InteropServices Imports System.Reflection Imports System      Module FileRegistration     'Registration flag so we know if this registration code     'has already been executed.  (We only want it to run once.)     Private fReg As Boolean = False          Public Sub RegSmartTag( _         ByVal RegKey As String, _         ByVal Register As Boolean)              If Not fReg Then             OutputMsg("*****  Beginning SmartTag Registration *****")             OutputMsg(vbTab & "Register=" & Register.ToString())             OutputMsg("")                  'Main SmartTags Registry Key             Dim rkeySmartTags As RegistryKey _                 = Registry.CurrentUser.OpenSubKey _                 ("Software\Microsoft\Office\Common\Smart Tag", True)                  'Actions Sub Key             Dim rkeyActions As RegistryKey _                 = rkeySmartTags.OpenSubKey("Actions", True)                  'Recognizers Sub Key             Dim rkeyRecognizers As RegistryKey _                 = rkeySmartTags.OpenSubKey("Recognizers", True)                  'Get the current assembly             Dim reflAssembly As [Assembly] = _                 [Assembly].GetExecutingAssembly()                  'Get all public types for the assembly             Dim reflTypes As Type() = reflAssembly.GetExportedTypes()             Dim reflType As Type                  'Loop through the exported types.             For Each reflType In reflTypes                 'Get the interfaces to look for the SmartTag interfaces.                 If reflType.IsClass Then  'Make sure that it's a class.                     Dim reflInterfaces As Type() = _                         reflType.GetInterfaces()                     Dim reflInterface As Type                          For Each reflInterface In reflInterfaces                         Select Case reflInterface.Name                             'SmartTag Action Interface                             Case "ISmartTagAction"                                 HandleReg(reflType, rkeyActions, Register)                                  'SmartTag Recognizer Interface                             Case "ISmartTagRecognizer"                                 HandleReg(reflType, _                                           rkeyRecognizers, Register)                         End Select                     Next reflInterface                 End If             Next reflType                  'Done.  Now clean up.             reflTypes = Nothing             reflAssembly = Nothing             rkeyActions.Close()             rkeyActions = Nothing             rkeyRecognizers.Close()             rkeyRecognizers = Nothing             rkeySmartTags.Close()             rkeySmartTags = Nothing                  fReg = True '<-- Set our shared variable to True                  OutputMsg("")             OutputMsg("*****  Completed SmartTag Registration *****")             OutputMsg("")         End If     End Sub          Private Sub HandleReg( _         ByVal sysType As Type, _         ByVal RegKey As RegistryKey, _         ByVal Register As Boolean)         'Code to actually do the registration of the SmartTag.         'INPUTS:         '   sysType:  Type for the class that's getting registered.         '   RegKey:   RegKey to register the class in.         '             Should be the Actions or Recognizers Key.         '   Register: True to register, False to Unregister.              'Get the type of the GuidAttribute class.  We'll need this.         Dim typGUIDAttr As Type = GetType(GuidAttribute)              'Check to see if the GuidAttribute is defined on the class.         If Attribute.IsDefined(sysType, typGUIDAttr) Then             Dim attrValue As GuidAttribute                  'Get the GuidAttribute.             attrValue = CType(Attribute.GetCustomAttribute( _                             sysType, typGUIDAttr), GuidAttribute)                  'Get the string representation of the GUID.             Dim strGuidVal As String = "{" & attrValue.Value & "}"                  If Register Then                 Try                     Dim newKey As RegistryKey _                         = RegKey.CreateSubKey(strGuidVal)                     newKey.SetValue("Assembly", _                                     sysType.Assembly.FullName)                     newKey.SetValue("Type", sysType.FullName)                     OutputMsg(sysType.Name & _                               " registered with SmartTags successfully")                 Catch                     OutputMsg("Failed to register " & _                               sysType.Name & " with SmartTags")                     OutputMsg(Err.GetType.Name & ":" & Err.Description)                 End Try             Else                 Try                     RegKey.DeleteSubKey(strGuidVal, False)                     OutputMsg(sysType.Name & _                               " unregistered with SmartTags successfully")                 Catch                     OutputMsg("Failed to unregister " & _                               sysType.Name & " with SmartTags")                     OutputMsg(Err.GetType.Name & ":" & Err.Description)                 End Try             End If         Else             'If we don't find the guid attribute,             'write to the system console.             OutputMsg("Could not register " & _                       sysType.Name & " as SmartTag")             OutputMsg("GUID Attribute not found on class")         End If     End Sub          Private Sub OutputMsg(ByVal Msg As String)         'Use DEBUG conditional compile constant to only output         'when compiling the DEBUG version. #If DEBUG Then         System.Console.WriteLine(Msg) #End If     End Sub End Module 

Testing Your Smart Tag in .NET

When you test your smart tag, be sure to set macro security in your Office application to Medium ”otherwise, the smart tag will not work. After you launch an Office application such as Word, you will then be prompted to enable or disable a DLL called mscoree.dll. If you are running Office 2003, you will not be prompted for .NET smart tags. This DLL is the DLL that contains the common language runtime (CLR). Be sure to enable this macro. You can then type the word Outlook wherever you want, and the smart tag should work as shown in Figure 9-8.

click to expand
Figure 9-8: The .NET smart tag working in Word



Programming Microsoft Outlook and Microsoft Exchange 2003
Programming MicrosoftВ® OutlookВ® and Microsoft Exchange 2003, Third Edition (Pro-Developer)
ISBN: 0735614644
EAN: 2147483647
Year: 2003
Pages: 227
Authors: Thomas Rizzo

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net