智慧標籤是由 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」:
ISmartTagRecognizer
和
ISmartTagAction
。
ISmartTagRecognizer
介面可識別出以智慧標籤方式鍵入文件中的文字。
ISmartTagAction
介面則負責在使用者要求下,於特定智慧標籤上執行動作。這些介面並不需要在相同的 DLL 中實作。您可以有單一識別元 DLL 和一或多個動作 DLL,以便為不同的動作延伸單一智慧標籤類型。
在 ATL 中建立智慧標籤 DLL
下列步驟可建立出簡易的智慧標籤 DLL,以識別 Microsoft Network (MSN) Instant Messenger 連絡人,並提供使用者傳送電子郵件或即時訊息給已知連絡人的功能。您必須具備 Instant Messenger 才能使用本範例。如果您沒有 Instant Messenger,可自以下 MSN 網站取得:
-
在 Visual C++ 中,建立新的 ATL COM AppWizard 專案。將專案命名為 MessengerSmartTag。
-
按一下
[確定]
以啟動 ATL COM 精靈。在下一個對話方塊中,確實選取
[動態連結程式庫]
並按一下
[完成]
。按一下
[確定]
以建立專案。
-
要建立
Recognizer
類別,請於
[插入]
功能表上,按一下
[New ATL Object]
。選取
[Simple Object]
並按一下
[下一步]
。在短名稱部份,鍵入
「Recognizer」
並按一下
[確定]
。
-
要建立
Action
類別,依步驟 3 的指示但鍵入
「Action」
作為短名稱。
-
開啟 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。
-
在 ClassView 中,用滑鼠右鍵按一下
[CAction]
類別,並選取
[Implement Interface]
。於顯示出警告對話方塊時,按一下
[確定]
。按一下
[瀏覽]
並選取
[Microsoft Smart Tags 1.0 Type Library]
。選取
[ISmartTagAction]
介面並按一下
[確定]
。
-
開啟 Recognizer.h 檔案,並以下列程式碼取代類別內容:
/////////////////////////////////////////////////////////////////////////////
// CRecognizer
class 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()
// IRecognizer
public:
// 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;
}; -
開啟 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;
} -
Open the Action.h file and replace the contents of the class with the following code:
/////////////////////////////////////////////////////////////////////////////
// CAction
class 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()
// IAction
public:
// 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);
}; -
開啟 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;
} -
開啟 Stdafx.h 檔案並於
#include <atlcom.h>
指令列後方加入:
#import "C:\Program Files\Messenger\msmsgs.exe"
注意
:將 Msmsgs.exe 檔案路徑變更為 Instant Messenger 安裝點的路徑。Instant Messenger 的預設位置為 C:\Program Files\Messenger。
-
按下 F7 以建立 DLL。
登錄智慧標籤 DLL 的各個步驟
在您使用任何智慧標籤 DLL 之前,必須先在系統上進行登錄。正常 COM 登錄是在使用 DLL 名稱編譯專案或呼叫 Regsvr32.exe 時執行。您必須建立不屬於正常 COM 登錄的其他登錄項目,讓 Office 應用程式將 DLL 識別為智慧標籤 DLL。方法及步驟如下:
-
從命令列啟動 Regedit.exe。
-
於
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\Smart Tag\Actions
新增子機碼,名為 MessengerSmartTag.Action。
-
於
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\Smart Tag\Recognize
新增子機碼,名為 MessengerSmartTag.Recognize。
-
關閉「登錄編輯器」。
測試智慧標籤 DLL 的各個步驟
智慧標籤依照與巨集相同的安全性模式。如果應用程式的安全性設定為「高」,則除非 DLL 經過數位簽章 (如 VBA 巨集),否則智慧標籤 DLL 不會進行載入。如需有關數位簽章的詳細資訊,請參閱〈參考〉章節。
要在 Word 中測試自訂智慧標籤識別元 / 動作 DLL,請執行下列步驟:
-
啟動「Instant Messenger」並登入。
注意
:必須登入 Instant Messenger 方可使用本範例的智慧標籤。如果您尚未登入 Instant Messenger,會載入自訂 DLL 但無法識別出任何連絡人。
-
啟動 Word 2002。在
[工具]
功能表上,指向
[巨集]
,然後按一下
[安全性]
。將巨集安全性設定為
[中]
,然後按一下
[確定]
。如果之前曾將巨集安全性設定為
[高]
,請重新啟動 Word。
-
在新文件中鍵入好記的連絡人名稱 (例如 John Smith),然後按下 ENTER。該名稱下方會出現一條細線,代表這是一個智慧標籤。將滑鼠移至名稱上方,隨即顯示出 [智慧標籤動作] 按鈕。
-
按一下
[智慧標籤動作]
,並從下拉式功能表中選取其中一個自訂動作項目。您可傳送電子郵件或即時訊息給新文件中的連絡人。
您可使用相同的步驟,於 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.exe
或
Excel.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
(http://support.microsoft.com/kb/247257/EN-US/
)
INFO: Steps for Signing a .cab File
如需有關使用 CLSIDs 而非 ProgIDs 來登錄智慧標籤 DLL 的詳細資訊,請按一下下面的文件編號,以檢視 Microsoft 知識庫中的文件:
294422
(http://support.microsoft.com/kb/294422/EN-US/
)
BUG: Status Flag Is Not Updated When You Enable or Disable Smart Tags
本文件是根據 Microsoft Knowledgebase 文件編號 Q292596 翻譯的。若要參考原始英文文件內容,請至以下網址:
文章編號: 292596 - 上次校閱: 2006年9月28日 - 版次: 6.1
這篇文章中的資訊適用於:
- Microsoft Excel 2002 Standard Edition
- Microsoft Word 2002 Standard Edition
- Microsoft Visual C++ 6.0 Professional Edition
| kbatl kbexcel kbgrpdso kbhowtomaster kbword KB292596 |
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。