如何:在 ATL 中建立智慧標籤 DLL 以便於 Office XP 中使用

本文曾發行於 CHT292596
本文已封存。本文係以「現狀」提供且不會再更新。
結論
智慧標籤是由 Office XP 推出的技術,可為 Office 使用者提供更多 Office 文件內容的互動功能。智慧標籤是 Office 文件中的文字元素,可識別為具有關聯的自訂動作。這些特殊文字元素的其中一個範例,是鍵入 Word 文件或 Excel 活頁簿的電子郵件名稱。如果電子郵件名稱識別為智慧標籤,則可為使用者提供一或多動作來執行該文字。可能與電子郵件名稱關聯的動作包括查詢其他連絡人資訊,或者傳送新的電子郵件訊息給該連絡人。

您可以開發個人智慧標籤識別器 / 動作動態連結程式庫 (DLL),以便延伸 Office XP 的功能並於 Office 文件中使用。本文說明如何使用 Active Template Library (ATL) 建立智慧標籤,並討論 Office XP 需要哪些登錄設定來識別及使用您的智慧標籤 DLL。

注意:Excel 2002 和 Word 2002 是唯一可支援智慧標籤的 Office XP 應用程式。不過,在所有可接受智慧標籤技術的應用程式中,皆可套用本文中所呈現的資訊來進行智慧標籤開發工作。智慧標籤 DLL 是實作兩種特殊介面的標準「元件物件模型 (COM) DLL」:ISmartTagRecognizerISmartTagActionISmartTagRecognizer介面可識別出以智慧標籤方式鍵入文件中的文字。ISmartTagAction介面則負責在使用者要求下,於特定智慧標籤上執行動作。這些介面並不需要在相同的 DLL 中實作。您可以有單一識別元 DLL 和一或多個動作 DLL,以便為不同的動作延伸單一智慧標籤類型。

回到頁首


在 ATL 中建立智慧標籤 DLL


下列步驟可建立出簡易的智慧標籤 DLL,以識別 Microsoft Network (MSN) Instant Messenger 連絡人,並提供使用者傳送電子郵件或即時訊息給已知連絡人的功能。您必須具備 Instant Messenger 才能使用本範例。如果您沒有 Instant Messenger,可自以下 MSN 網站取得:
  1. 在 Visual C++ 中,建立新的 ATL COM AppWizard 專案。將專案命名為 MessengerSmartTag。
  2. 按一下[確定]以啟動 ATL COM 精靈。在下一個對話方塊中,確實選取[動態連結程式庫]並按一下[完成]。按一下[確定]以建立專案。
  3. 要建立Recognizer類別,請於[插入]功能表上,按一下[New ATL Object]。選取[Simple Object]並按一下[下一步]。在短名稱部份,鍵入「Recognizer」並按一下[確定]
  4. 要建立Action類別,依步驟 3 的指示但鍵入「Action」作為短名稱。
  5. 開啟 ClassView 並展開MessengerSmartTag 類別。用滑鼠右鍵按一下[CRecognizer]類別,並選取[Implement Interface]。於顯示出警告對話方塊時,按一下[確定]。按一下[瀏覽]並選取[Microsoft Smart Tags 1.0 Type Library]。選取[ISmartTagRecognizer]介面並按一下[確定]

    注意:Microsoft Smart Tags 1.0 Type Library 的預設位置為 C:\Program Files\Common Files\Microsoft Shared\Mstag.tlb。
  6. 在 ClassView 中,用滑鼠右鍵按一下[CAction]類別,並選取[Implement Interface]。於顯示出警告對話方塊時,按一下[確定]。按一下[瀏覽]並選取[Microsoft Smart Tags 1.0 Type Library]。選取[ISmartTagAction]介面並按一下[確定]
  7. 開啟 Recognizer.h 檔案,並以下列程式碼取代類別內容:
    ///////////////////////////////////////////////////////////////////////////// // CRecognizerclass ATL_NO_VTABLE CRecognizer :    public CComObjectRootEx<CComSingleThreadModel>,   public CComCoClass<CRecognizer, &CLSID_Recognizer>,   public IDispatchImpl<IRecognizer, &IID_IRecognizer, &LIBID_MESSENGERSMARTTAGLib>,   public IDispatchImpl<ISmartTagRecognizer, &IID_ISmartTagRecognizer, &LIBID_SmartTagLib>{public:    CRecognizer();    ~CRecognizer();DECLARE_REGISTRY_RESOURCEID(IDR_RECOGNIZER)DECLARE_PROTECT_FINAL_CONSTRUCT()BEGIN_COM_MAP(CRecognizer)    COM_INTERFACE_ENTRY(IRecognizer)//Removed -- COM_INTERFACE_ENTRY(IDispatch)    COM_INTERFACE_ENTRY2(IDispatch, IRecognizer)    COM_INTERFACE_ENTRY(ISmartTagRecognizer)END_COM_MAP()// IRecognizerpublic:// ISmartTagRecognizer    STDMETHOD(get_ProgId)(BSTR * ProgId);    STDMETHOD(get_Name)(INT LocaleID, BSTR * Name);    STDMETHOD(get_Desc)(INT LocaleID, BSTR * Desc);    STDMETHOD(get_SmartTagCount)(INT * Count);    STDMETHOD(get_SmartTagName)(INT SmartTagID, BSTR * Name);    STDMETHOD(get_SmartTagDownloadURL)(INT SmartTagID, BSTR * DownloadURL);    STDMETHOD(Recognize)(BSTR Text, IF_TYPE DataType, INT LocaleID,                  ISmartTagRecognizerSite * RecognizerSite);private:    long lCount;    SAFEARRAY *psa;};
  8. 開啟 Recognizer.cpp 檔案並於檔案結尾處加入下列程式碼:
    CRecognizer::CRecognizer(){    Messenger::IMsgrObject2Ptr oMsgrObj = NULL;    Messenger::IMsgrUsersPtr oUsers = NULL;    Messenger::IMsgrUserPtr oUser = NULL;    SAFEARRAYBOUND rgsaBound[1];    long rgIndices[1];		    HRESULT hr;		    // Create an instance of Instant Messenger.    oMsgrObj.CreateInstance("Messenger.MsgrObject");    // Get the list of contacts    oUsers = oMsgrObj->GetList(Messenger::MLIST_CONTACT);    // Store the number of contacts you have.    lCount = oUsers->GetCount();    rgsaBound[0].lLbound = 0;    rgsaBound[0].cElements = lCount;    // Create a SAFEARRAY to hold the list of contacts.    psa = SafeArrayCreate(VT_VARIANT, 1, rgsaBound);    // Loop through all contacts.    for (long l=0; l<lCount-1; l++)    {        rgIndices[0] = l;	        // Set the specific user.        oUser = oUsers->Item(l);        // Convert the Friendly Name to lower case        // and store it in a VARIANT.        _variant_t v = _wcslwr(oUser->GetFriendlyName());        // Put the VARIANT into the SAFEARRAY.       hr = SafeArrayPutElement(psa, rgIndices, &v);    }}CRecognizer::~CRecognizer(){    // Destroy the SAFEARRAY.    SafeArrayDestroy(psa);}HRESULT CRecognizer::get_ProgId(BSTR * ProgId){    // Set the ProgID of the Recognizer interface.    *ProgId = SysAllocString(L"MessengerSmartTag.Recognizer");    return S_OK;}HRESULT CRecognizer::get_Name(INT LocaleID, BSTR * Name){    // Set a short title about the recognizer.    *Name = SysAllocString(L"Microsoft Messenger Contacts Visual C++ Recognizer");    return S_OK;}HRESULT CRecognizer::get_Desc(INT LocaleID, BSTR * Desc){    // Set a long description of the recognizer.    *Desc = SysAllocString(L"Microsoft Messenger recognizes your Instant Messenger Contacts");    return S_OK;}HRESULT CRecognizer::get_SmartTagCount(INT * Count){    // Set the number of Smart Tags that are supported.    *Count = 1;    return S_OK;}HRESULT CRecognizer::get_SmartTagName(INT SmartTagID, BSTR * Name){    // This method is called the same number of times as you    // return in SmartTagCount. This method sets a unique name    // for the Smart Tag.    *Name = SysAllocString(L"microsoft/messenger#contacts");    return S_OK;}HRESULT CRecognizer::get_SmartTagDownloadURL(INT SmartTagID, BSTR * DownloadURL){    // Set the URL that gets embedded in documents.    *DownloadURL = NULL;    return S_OK;}HRESULT CRecognizer::Recognize(BSTR Text, IF_TYPE DataType, INT LocaleID,       ISmartTagRecognizerSite * RecognizerSite){    // The Recognize method is called and passed a text value.    // You should recognize strings in the text and set up the actions.    WCHAR *pch, *strText = _wcslwr(Text);    ISmartTagProperties  *pSmartTagProp = NULL;    long rgIndices[1];    HRESULT hr;    // Look through all contacts    for (long l = 0; l<lCount; l++).    {        rgIndices[0] = l;        // Get the contact name.        _variant_t v;        hr = SafeArrayGetElement(psa,rgIndices,&v);        // Convert the VARIANT to a BSTR.        _bstr_t bstrContact = v;        // Loop through the string looking for contacts.        for (pch = strText; (pch = wcsstr(pch, bstrContact))!=NULL; pch++)        {                // Create a new property bag.            hr = RecognizerSite->GetNewPropertyBag(&pSmartTagProp);            if (SUCCEEDED(hr)) {                // Commit the Smart Tag to the property bag.		                hr = RecognizerSite->CommitSmartTag(                      _bstr_t("microsoft/messenger#contacts"),                      pch - strText+1, wcslen(bstrContact),                      pSmartTagProp);                                if (pSmartTagProp != NULL)                    pSmartTagProp->Release();            }        }    }    return S_OK;}
  9. Open the Action.h file and replace the contents of the class with the following code:
    ///////////////////////////////////////////////////////////////////////////// // CActionclass ATL_NO_VTABLE CAction :    public CComObjectRootEx<CComSingleThreadModel>,   public CComCoClass<CAction, &CLSID_Action>,   public IDispatchImpl<IAction, &IID_IAction, &LIBID_MESSENGERSMARTTAGLib>,   public IDispatchImpl<ISmartTagAction, &IID_ISmartTagAction, &LIBID_SmartTagLib>{public:   CAction(){}DECLARE_REGISTRY_RESOURCEID(IDR_ACTION)DECLARE_PROTECT_FINAL_CONSTRUCT()BEGIN_COM_MAP(CAction)    COM_INTERFACE_ENTRY(IAction)//Removed -- COM_INTERFACE_ENTRY(IDispatch)    COM_INTERFACE_ENTRY2(IDispatch, IAction)    COM_INTERFACE_ENTRY(ISmartTagAction)END_COM_MAP()// IActionpublic:// ISmartTagAction    STDMETHOD(get_ProgId)(BSTR * ProgId);    STDMETHOD(get_Name)(INT LocaleID, BSTR * Name);    STDMETHOD(get_Desc)(INT LocaleID, BSTR * Desc);    STDMETHOD(get_SmartTagCount)(INT * Count);    STDMETHOD(get_SmartTagName)(INT SmartTagID, BSTR * Name);    STDMETHOD(get_SmartTagCaption)(INT SmartTagID, INT LocaleID,                  BSTR * Caption);    STDMETHOD(get_VerbCount)(BSTR SmartTagName, INT * Count);    STDMETHOD(get_VerbID)(BSTR SmartTagName, INT VerbIndex, INT * VerbID);    STDMETHOD(get_VerbCaptionFromID)(INT VerbID, BSTR ApplicationName,                  INT LocaleID, BSTR * Caption);    STDMETHOD(get_VerbNameFromID)(INT VerbID, BSTR * Name);    STDMETHOD(InvokeVerb)(INT VerbID, BSTR ApplicationName,                  IDispatch * Target, ISmartTagProperties * Properties,                  BSTR Text, BSTR Xml);};
  10. 開啟 Action.cpp 檔案並於檔案結尾處加入下列程式碼:
    HRESULT CAction::get_ProgId(BSTR * ProgId){   // Set the ProgID of the Action interface.   *ProgId = SysAllocString(L"MessengerSmartTag.Action");   return S_OK;}HRESULT CAction::get_Name(INT LocaleID, BSTR * Name){   // Set a short name describing the Action.   *Name = SysAllocString(L"Messenger Smart Tag");   return S_OK;}HRESULT CAction::get_Desc(INT LocaleID, BSTR * Desc){   // Set a long description describing the action.   *Desc = SysAllocString(L"Provides actions for the Messenger Smart Tag");   return S_OK;}HRESULT CAction::get_SmartTagCount(INT * Count){    // Set the number of smart tags this action supports.    *Count = 1;    return S_OK;}HRESULT CAction::get_SmartTagName(INT SmartTagID, BSTR * Name){    // This method is called the same number of times as you    // return in SmartTagCount. This method sets a unique name    // for the smart tag.    *Name = SysAllocString(L"microsoft/messenger#contacts");    return S_OK;}HRESULT CAction::get_SmartTagCaption(INT SmartTagID, INT LocaleID, BSTR * Caption){    // This caption is displayed on the menu for the smart tag.    *Caption = SysAllocString(L"Messenger Smart Tag");    return S_OK;}HRESULT CAction::get_VerbCount(BSTR SmartTagName, INT * Count){    // Return the number of verbs we support.    if (wcsstr(SmartTagName,L"microsoft/messenger#contacts") != 0) {        *Count = 2;    }    return S_OK;}HRESULT CAction::get_VerbID(BSTR SmartTagName, INT VerbIndex, INT * VerbID){    // Return a unique ID for each verb we support.    *VerbID = VerbIndex;    return S_OK;}HRESULT CAction::get_VerbCaptionFromID(INT VerbID, BSTR ApplicationName,                     INT LocaleID, BSTR * Caption){    // Set a caption for each verb. This caption is displayed    // on the Smart Tag menu.    switch (VerbID) {      case 1:        *Caption = SysAllocString(L"Send this contact an Instant Message");        break;      case 2:        *Caption = SysAllocString(L"Send email to this contact");        break;      default:        *Caption = NULL;        break;    }    return S_OK;}HRESULT CAction::get_VerbNameFromID(INT VerbID, BSTR * Name){    // Set a string name for each verb.    switch (VerbID) {      case 1:        *Name = SysAllocString(L"SendInstantMessage");        break;      case 2:        *Name = SysAllocString(L"SendEmail");        break;    }    return S_OK;}HRESULT CAction::InvokeVerb(INT VerbID, BSTR ApplicationName,      IDispatch * Target, ISmartTagProperties * Properties,      BSTR Text, BSTR Xml){    // This method is called when a user invokes a verb    // from the Smart Tag menu.    Messenger::IMessengerApp2Ptr oMessenger = NULL;    Messenger::IMsgrObject2Ptr oMsgrObj = NULL;    Messenger::IMsgrUsersPtr oUsers = NULL;    Messenger::IMsgrUserPtr oUser = NULL;    _variant_t v;		    // Create an instance of Instant Messenger.    oMessenger.CreateInstance("Messenger.MessengerApp");    oMsgrObj.CreateInstance("Messenger.MsgrObject");    // Get a list of contacts.    oUsers = oMsgrObj->GetList(Messenger::MLIST_CONTACT);    // Loop through all contacts.    for (long l=0; l<(oUsers->GetCount()-1); l++)    {        // Get a specific contact.        oUser = oUsers->Item(l);        // Check to see if the contact is the correct one.	if (wcscmp(_wcslwr(oUser->GetFriendlyName()),_wcslwr(Text)) == 0)        {            switch (VerbID) {              case 1:                // The user wants to display the Instant Message                // box to send the contact a message.                v = oUser.GetInterfacePtr();					                oMessenger->LaunchIMUI(v);                break;              case 2:                // Shell the "mailto" protocol to start the                // user's mail program and create a new message.                _bstr_t bstrTemp = "mailto:";                bstrTemp += oUser->GetEmailAddress();				                ShellExecute(0,"open",bstrTemp,NULL,NULL,1);                break;            }        }    }    return S_OK;}
  11. 開啟 Stdafx.h 檔案並於#include <atlcom.h>指令列後方加入:
    #import "C:\Program Files\Messenger\msmsgs.exe"
    注意:將 Msmsgs.exe 檔案路徑變更為 Instant Messenger 安裝點的路徑。Instant Messenger 的預設位置為 C:\Program Files\Messenger。
  12. 按下 F7 以建立 DLL。

回到頁首


登錄智慧標籤 DLL 的各個步驟



在您使用任何智慧標籤 DLL 之前,必須先在系統上進行登錄。正常 COM 登錄是在使用 DLL 名稱編譯專案或呼叫 Regsvr32.exe 時執行。您必須建立不屬於正常 COM 登錄的其他登錄項目,讓 Office 應用程式將 DLL 識別為智慧標籤 DLL。方法及步驟如下:
  1. 從命令列啟動 Regedit.exe。
  2. HKEY_CURRENT_USER\Software\Microsoft\Office\Common\Smart Tag\Actions新增子機碼,名為 MessengerSmartTag.Action。
  3. HKEY_CURRENT_USER\Software\Microsoft\Office\Common\Smart Tag\Recognize新增子機碼,名為 MessengerSmartTag.Recognize。
  4. 關閉「登錄編輯器」。

回到頁首


測試智慧標籤 DLL 的各個步驟



智慧標籤依照與巨集相同的安全性模式。如果應用程式的安全性設定為「高」,則除非 DLL 經過數位簽章 (如 VBA 巨集),否則智慧標籤 DLL 不會進行載入。如需有關數位簽章的詳細資訊,請參閱〈參考〉章節。

要在 Word 中測試自訂智慧標籤識別元 / 動作 DLL,請執行下列步驟:
  1. 啟動「Instant Messenger」並登入。

    注意:必須登入 Instant Messenger 方可使用本範例的智慧標籤。如果您尚未登入 Instant Messenger,會載入自訂 DLL 但無法識別出任何連絡人。
  2. 啟動 Word 2002。在[工具]功能表上,指向[巨集],然後按一下[安全性]。將巨集安全性設定為[中],然後按一下[確定]。如果之前曾將巨集安全性設定為[高],請重新啟動 Word。
  3. 在新文件中鍵入好記的連絡人名稱 (例如 John Smith),然後按下 ENTER。該名稱下方會出現一條細線,代表這是一個智慧標籤。將滑鼠移至名稱上方,隨即顯示出 [智慧標籤動作] 按鈕。
  4. 按一下[智慧標籤動作],並從下拉式功能表中選取其中一個自訂動作項目。您可傳送電子郵件或即時訊息給新文件中的連絡人。
您可使用相同的步驟,於 Excel 2002 中測試智慧標籤 DLL。


回到頁首


疑難排解



如果您對於自訂智慧標籤的使用上有任何問題,請先檢查是否確實載入自訂智慧標籤 DLL。在 Word 或 Excel 中,於[工具]功能表上,按一下[Auto Correct Options],按一下[智慧標籤]索引標籤,並確定[Label Text with Smart Tags]核取方塊已選取,且已列出並選擇您的智慧標籤 DLL。如果該智慧標籤 DLL 並未列示,則可能尚未正確登錄完成。

如果自訂 Recognizer 或 Action 類別的執行動作為問題來源,可以使用其他 Visual C++ DLL 的方式來為智慧標籤 DLL 進行偵錯。在 Recognizer 類別的建構工具中設定中斷點。在您按下 F5 進行應用程式偵錯時,隨即顯示出對話方塊並要求取得某可執行檔進行偵錯工作階段。選取Winword.exeExcel.exe在 Excel 或 Word 啟動及載入智慧標籤時,程式碼會在該中斷點中斷,而您可以逐步執行程式碼以進行偵錯。

回到頁首

參考


這些介面的說明文件,以及定義用的必要型別資料庫,皆包含在 Smart Tag Software Development Kit (SDK) 中。請先安裝 Smart Tag SDK (如果您尚未安裝),再繼續進行各步驟來建立智慧標籤範例。您可於 Microsoft Office XP Developer (MOD) 光碟中取得 Smart Tag SDK,或者自以下 MSDN 網站下載:


如需有關建立自訂智慧標籤識別元 / 動作 DLL 的詳細資訊,請參閱 Smart Tag SDK 中包含的 Smart Tag Development 說明檔案。

如需有關數位簽章的其他資訊,請按一下下面的文件編號,以檢視 Microsoft 知識庫中的文件:
247257 INFO: Steps for Signing a .cab File
如需有關使用 CLSIDs 而非 ProgIDs 來登錄智慧標籤 DLL 的詳細資訊,請按一下下面的文件編號,以檢視 Microsoft 知識庫中的文件:
294422 BUG: Status Flag Is Not Updated When You Enable or Disable Smart Tags


回到頁首

本文件是根據 Microsoft Knowledgebase 文件編號 Q292596 翻譯的。若要參考原始英文文件內容,請至以下網址:

smart tag sdk factoid
內容

文章識別碼:292596 - 最後檢閱時間:02/24/2014 15:31:25 - 修訂: 6.1

  • Microsoft Excel 2002 Standard Edition
  • Microsoft Word 2002 Standard Edition
  • Microsoft Visual C++ 6.0 Professional Edition
  • kbnosurvey kbarchive kbatl kbexcel kbgrpdso kbhowtomaster kbword KB292596
意見反應