oldi

Delphi и смарт-теги

Наталия Елманова

Что такое смарт-теги

Требования к DLL, реализующим смарт-теги

Создание распознавателей смарт-тегов

Создание обработчиков смарт-тегов

Поставка и тестирование DLL, реализующих смарт-теги

Заключение

 

В этой статье мы снова возвращаемся к теме создания смарт-тегов для приложений Microsoft Office XP — этому вопросу были посвящены две статьи Алексея Малинина (см. КомпьютерПресс, CD-ROM № 11, 12’2001). Смарт-теги представляют собой довольно интересное новшество Office XP, и при желании им можно найти массу полезных применений. В настоящей статье мы рассмотрим, как с помощью Delphi создавать DLL, реализующие смарт-теги для Office XP, и как осуществить их поставку конечным пользователям. Но прежде напомним, что они собой представляют.

Что такое смарт-теги

Смарт-теги представляют собой элементы пользовательского интерфейса Microsoft Word 2002, Microsoft Excel 2002, Microsoft Outlook 2002 (в случае если Word 2002 используется в качестве редактора писем) и Microsoft Internet Explorer 6 (при условии, что на данном компьютере установлен Microsoft Office XP или любое из перечисленных выше приложений). C помощью смарт-тегов в документе отмечаются отдельные слова или словосочетания, и пользователю предлагается осуществить выбор из набора действий, которые он может выполнить с этим словом. Например, слово Moscow может быть распознано и отмечено как географическое название, а словосочетание John Smith — как английское имя. Если слово или словосочетание отмечено как распознанное (в случае Word 2002 оно подчеркивается фиолетовыми точками, в случае Excel — выделяется фиолетовым треугольником в правом нижнем углу ячейки), пользователь может вывести на экран список возможных действий с этим словом и выбрать одно из них. Например, пользователь может добавить в документ карту MapPoint 2002 c Москвой в центре, спланировать маршрут до Москвы, равно как и создать новый контакт Outlook для Джона Смита. Для этого достаточно поместить курсор мыши на отмеченное слово или словосочетание, немного подождать, нажать на кнопку Smart Tag Actions и выбрать одно из возможных действий в появившемся списке (рис. 1).

Иными словами, смарт-теги позволяют осуществить динамическое распознавание пользовательского ввода и выполнение действий в зависимости от результатов этого распознавания.

Набор смарт-тегов, поставляемый с Microsoft Office, можно расширять собственными смарт-тегами. Это означает, что мы можем определять собственные категории слов и словосочетаний, которые следует распознавать, и набор действий, которые можно с ними выполнить. Например, мы можем создать новую категорию смарт-тегов Borland products, описать строки с именами продуктов Borland и определить действия, которые можно сделать с этими именами (например, найти цену продукта в прайс-листе, содержащемся в рабочей книге Excel, открыть в Web-браузере страницу, посвященную этому продукту, добавить в документ изображение коробки с этим продуктом и т.д.).

Следует заметить, что, хотя смарт-теги и содержатся внутри документа, реализация кода, выполняющего распознавание строк, и осуществление действий над ними, находятся за его пределами — они содержатся в отдельной DLL, требующей регистрации на компьютере пользователя. Иными словами, в отличие от макросов VBA, при передаче документа с помощью электронной почты или при загрузке его из Интернета никакой код непосредственно в документе не передается, что представляется благоприятным с точки зрения безопасности.

Имеется несколько способов реализации смарт-тегов. Простейший из них заключается в создании XML-файла, описывающего категории словосочетаний, сами словосочетания и действия, которые с ними можно произвести. Подробнее о создании таких смарт-тегов вы можете узнать из статьи Алексея Малинина (см. КомпьютерПресс, CD-ROM № 11’2001). Подобные решения легко реализуются, но недостаточно расширяемы, а действия, производимые в них, довольно примитивны (например, открыть заранее определенную Web-страницу, если словосочетание распознано как принадлежащее к той или иной категории). Если же мы хотим от смарт-тега более сложной функциональности, нам следует реализовать COM DLL. Это можно сделать с помощью любого средства разработки, поддерживающего создание COM DLL, в частности с помощью Visual Basic, о чем мы уже писали в предыдущем номере нашего журнала (см. КомпьютерПресс, CD-ROM № 12’2001). Можно для этой цели использовать и Delphi Professional или Enterprise любой версии, начиная с версии 3.0, что мы и сделаем.

В начало В начало

Требования к DLL, реализующим смарт-теги

Каждый смарт-тег состоит из двух компонентов: распознавателя (recognizer), отвечающего за распознавание словосочетания как принадлежащего к определенной категории и за пометку его в документе, и обработчика (action), ответственного за вывод списка действий и выполнение одного из них в соответствии с выбором пользователя. Оба эти компонента должны быть COM-объектами, реализованными в DLL, которые, в свою очередь, при необходимости используются приложениями Microsoft Office XP.

Чтобы создать смарт-тег, нам следует сослаться на библиотеку типов Microsoft Smart Tags 1.0 type library (MSTAG.TLB), содержащую несколько COM-интерфейсов. В наших COM-объектах мы должны реализовать два из них: ISmartTagRecognizer и ISmartTagAction. Свойства и методы этих интерфейсов подробно описаны в статье Алексея Малинина (см. КомпьютерПресс, CD-ROM № 12’2001), а также по адресу http://msdn.microsoft.com/library/en-us/dnsmarttag/html/odc_smarttags.asp.

В начало В начало

Создание распознавателей смарт-тегов

В нашем примере мы создадим смарт-тег, который распознает названия продуктов Borland и реализует обработчик, зависящий от наименования распознанного продукта. Пусть это будет открытие Web-страницы, посвященной этому продукту. В нашем примере мы можем поместить распознаватель и обработчик в одну и ту же DLL, но в общем случае это не обязательно.

Запустим Delphi и создадим новую COM-библиотеку. Для этой цели выберем пункт File | New | Other из главного меню среды разработки Delphi, а затем — пиктограмму ActiveX Library со страницы ActiveX репозитария объектов.

После этого будет сгенерирован код «пустой» библиотеки:

library Project1;  
   
uses  
  ComServ;  
   
exports  
  DllGetClassObject,  
  DllCanUnloadNow,  
  DllRegisterServer,  
  DllUnregisterServer;  
   
{$R *.RES}  
   
begin  
end.  

Переименуем наш проект в st.dpr.

Теперь добавим к нашей библиотеке объект, реализующий интерфейс ISmartTagRecognizer. Для этого выберем пункт меню File | New | Other и щелкнем по пиктограмме COM Object на странице ActiveX репозитария объектов, что приведет к запуску COM Object Wizard (рис. 2).

В диалоговой панели COM Object Wizard мы должны указать имя COM-класса (пусть он называется STR) и описание COM-объекта, а значения параметров Instancing и Threading Model оставить равными значениям по умолчанию. Заполняя поле Implemented Interfaces, вспомним, что нам нужно реализовать уже существующий интерфейс — Word или Excel будут искать его имя в реестре и в самой DLL. Простейший способ сделать это — нажать на кнопку List и выбрать ISmartTagRecognizer из списка доступных интерфейсов (рис. 3).

Если этот интерфейс отсутствует в списке, нам следует убедиться, что Office XP, или Word 2002, или Excel 2002 установлен на компьютере, использующемся для разработки смарт-тегов. Если это так, нужно нажать кнопку Add Library и найти файл MSTAG.TLB в каталоге C:\Program Files\Common Files\Microsoft Shared\Smart Tag.

После нажатия кнопки OK в COM Object Wizard будут сгенерированы заготовки методов класса TSTR, реализующего интерфейс ISmartTagRecognizer. Теперь можно создать их реализацию. Она может выглядеть, например, так:

unit st1;  
   
{$WARN SYMBOL_PLATFORM OFF}  
   
interface  
   
uses  
  ComObj, ActiveX, st_TLB, StdVcl, SmartTagLib_TLB;  
   
type  
  TSTR = class(TAutoObject, ISmartTagRecognizer)  
  protected  
    function Get_Desc(LocaleID: SYSINT): WideString; safecall;  
    function Get_Name(LocaleID: SYSINT): WideString; safecall;  
    function Get_ProgId: WideString; safecall;  
    function Get_SmartTagCount: SYSINT; safecall;  
    function Get_SmartTagDownloadURL(SmartTagID: SYSINT): WideString; safecall;  
    function Get_SmartTagName(SmartTagID: SYSINT): WideString; safecall;  
    procedure Recognize(const Text: WideString; DataType: IF_TYPE;  
      LocaleID: SYSINT; const RecognizerSite: ISmartTagRecognizerSite);  
      safecall;  
    { Protected declarations }  
  end;  
   
 const  
 BorProdArray: array[1..5] of String = ('Delphi', 'C++Builder',  
  'JBuilder', 'Kylix', 'JDataStore');  
   
implementation  
   
uses ComServ;  
   
function TSTR.Get_Desc(LocaleID: SYSINT): WideString;  
begin  
  result:= 'The test smart tag' ;  
end;  
   
function TSTR.Get_Name(LocaleID: SYSINT): WideString;  
begin  
  result:='Borland Web Site Smart Tag'  
end;  
   
function TSTR.Get_ProgId: WideString;  
begin  
  result:='st.STR';  
end;  
   
   
function TSTR.Get_SmartTagCount: SYSINT;  
begin  
  result:=1;  
end;  
   
function TSTR.Get_SmartTagDownloadURL(SmartTagID: SYSINT): WideString;  
begin  
  result:='';  
end;  
   
function TSTR.Get_SmartTagName(SmartTagID: SYSINT): WideString;  
begin  
  result:='ComputerPress#borwebsite';  
end;  
   
procedure TSTR.Recognize(const Text: WideString; DataType: IF_TYPE;  
  LocaleID: SYSINT; const RecognizerSite: ISmartTagRecognizerSite);  
  var PropertyBag: ISmartTagProperties;  
  tx,tx1,str: string;  i,len,ix: integer;  
begin  
 for  i:=1 to 5 do begin  
 str:=BorProdArray[i];  
 len:=length(str);  
 ix:=Pos(str, text);  
 while ix>0 do begin  
  PropertyBag := RecognizerSite.GetNewPropertyBag;  
  tx:=text;  
  RecognizerSite.CommitSmartTag('ComputerPress#borwebsite',
   ix,len,PropertyBag);  
  tx1:=copy(tx,ix+len,Length(tx)-ix-len);  
  tx:=tx1;  
  ix:=Pos(str,tx);  
  end;  
 end;  
end;  
   
initialization  
  TAutoObjectFactory.Create(ComServer, TSTR, Class_STR,  
    ciMultiInstance, tmApartment);  
end.  

Поясним, что содержится в приведенном выше коде. Первые три метода соответствуют тому, что смарт-тег называется ‘Borland Web Site Smart Tag’, его описание представляет собой строку ‘The test smart tag’, а его ProgID равно ‘st.STR’. Метод Get_SmartTagCount возвращает 1  — в данном примере мы реализуем один смарт-тег. Метод Get_SmartTagDownloadURL возвращает пустую строку — в этом примере мы не планируем производить обновления этого смарт-тега через Интернет. Метод Get_SmartTagName возвращает уникальную строку (в нашем примере — ‘ComputerPress#borwebsite’) для идентификации нашего смарт-тега.

Метод Recognize реализует алгоритм сканирования текста с целью нахождения в нем строк, определенных в строковом массиве BorProdArray (этот массив содержит названия продуктов Borland). Если мы находим строку из этого массива, мы создаем новый экземпляр интерфейса ISmartTagProperties (он описан в той же библиотеке MSTAG.TLB, ссылка на которую уже есть в нашем проекте). Этот экземпляр нужен для хранения свойств смарт-тега для найденного словосочетания. Далее нам следует сохранить сам смарт-тег в документе.

После распознавания словосочетания его следует обработать. Поэтому следующим шагом будет создание обработчиков.

В начало В начало

Создание обработчиков смарт-тегов

Для создания обработчика смарт-тега добавим к нашей библиотеке COM-объект, реализующий интерфейс ISmartTagAction. Чтобы это сделать, нам следует выбрать пиктограмму COM Object со страницы ActiveX репозитария объектов, в диалоговой панели COM Object Wizard указать имя COM-класса (назовем его STA), оставить значения по умолчанию для параметров Instancing и Threading Model и ввести описание этого COM-объекта. Заполняя поле Implemented Interfaces, мы должны нажать кнопку List и выбрать интерфейс ISmartTagAction из списка доступных интерфейсов. После этого мы получим заготовки для методов класса TSTA, реализующего интерфейс ISmartTagAction. Реализация этих методов может иметь вид:

unit st2;  
   
{$WARN SYMBOL_PLATFORM OFF}  
   
interface  
   
uses  
  ComObj, ActiveX, st_TLB, SysUtils, StdVcl, SmartTagLib_TLB;  
   
type  
  TSTA = class(TAutoObject, ISmartTagAction)  
  protected  
    function Get_Desc(LocaleID: SYSINT): WideString; safecall;  
    function Get_Name(LocaleID: SYSINT): WideString; safecall;  
    function Get_ProgId: WideString; safecall;  
    function Get_SmartTagCaption(SmartTagID, LocaleID: SYSINT): WideString;  
      safecall;  
    function Get_SmartTagCount: SYSINT; safecall;  
    function Get_SmartTagName(SmartTagID: SYSINT): WideString; safecall;  
    function Get_VerbCaptionFromID(VerbID: SYSINT;  
      const ApplicationName: WideString; LocaleID: SYSINT): WideString;  
      safecall;  
    function Get_VerbCount(const SmartTagName: WideString): SYSINT; safecall;  
    function Get_VerbID(const SmartTagName: WideString;  
      VerbIndex: SYSINT): SYSINT; safecall;  
    function Get_VerbNameFromID(VerbID: SYSINT): WideString; safecall;  
    procedure InvokeVerb(VerbID: SYSINT; const ApplicationName: WideString;  
      const Target: IDispatch; const Properties: ISmartTagProperties;  
      const Text, Xml: WideString); safecall;  
    { Protected declarations }  
  end;  
   
implementation  
   
uses ComServ;  
   
function TSTA.Get_Desc(LocaleID: SYSINT): WideString;  
begin  
  result:= 'The test smart tag' ;  
end;  
   
function TSTA.Get_Name(LocaleID: SYSINT): WideString;  
begin  
  result:='Borland Web Site Smart Tag';  
end;  
   
function TSTA.Get_ProgId: WideString;  
begin  
  result:='st.STA';  
end;  
   
function TSTA.Get_SmartTagCaption(SmartTagID,  
  LocaleID: SYSINT): WideString;  
begin  
 if SmartTagId=1 then  
  result:='Borland Product';  
end;  
   
function TSTA.Get_SmartTagCount: SYSINT;  
begin  
  result:=1;  
end;  
   
function TSTA.Get_SmartTagName(SmartTagID: SYSINT): WideString;  
begin  
  if SmartTagId=1 then  
  result:='ComputerPress#borwebsite';  
end;  
   
function TSTA.Get_VerbCaptionFromID(VerbID: SYSINT;  
  const ApplicationName: WideString; LocaleID: SYSINT): WideString;  
begin  
  if VerbID=1 then result:='Get product information from Borland web site';  
end;  
   
function TSTA.Get_VerbCount(const SmartTagName: WideString): SYSINT;  
begin  
  result:=1;  
end;  
   
function TSTA.Get_VerbID(const SmartTagName: WideString;  
  VerbIndex: SYSINT): SYSINT;  
begin  
   result:=1;  
end;  
   
function TSTA.Get_VerbNameFromID(VerbID: SYSINT): WideString;  
begin  
  if VerbID=1 then result:='BorProdVerbName'  
end;  
   
procedure TSTA.InvokeVerb(VerbID: SYSINT;  
  const ApplicationName: WideString; const Target: IDispatch;  
  const Properties: ISmartTagProperties; const Text, Xml: WideString);  
var IE: Variant;  ProdDir:string;  
begin  
 ProdDir:=Text;  
 If Text='C++Builder' then ProdDir:='bcppbuilder';  
 IE := CreateOleObject('InternetExplorer.Application');  
 IE.Navigate2('www.borland.com/'+ AnsiLowerCase(ProdDir));  
 IE.Visible := True;  
end;  
   
initialization  
  TAutoObjectFactory.Create(ComServer, TSTA, Class_STA,  
    ciMultiInstance, tmApartment);  
end.  

Как и в предыдущем случае, реализация первых трех методов отражает тот факт, что смарт-тег называется ‘Borland Web Site Smart Tag’, его описание  — ‘The test smart tag’, а его ProgID — ‘st.STA’. Метод Get_SmartTagCaption возвращает строку, которая появится в верхней части всплывающего меню смарт-тега. Пусть это будет строка ‘Borland Product’.

Как и в предыдущем случае, метод Get_SmartTagCount возвращает 1, а метод Get_SmartTagName — уникальную строку ‘ComputerPress#borwebsite’ для идентификации смарт-тега.

Метод Get_VerbCount должен возвращать количество возможных действий, доступных для данного смарт-тега. В нашем примере мы реализуем одно действие, поэтому этот метод возвращает 1. Метод Get_VerbCaptionFromID должен возвратить название действия, которое появится во всплывающем меню смарт-тега. Пусть это будет ‘Get product information from Borland web site’. Метод Get_VerbID должен вернуть уникальный идентификатор действия внутри смарт-тега — пусть это будет 1. Метод Get_VerbNameFromID возвращает имя действия, используемое внутри приложения Office, — пусть это имя равно ‘BorProdVerbName’.

Реализация действия должна быть осуществлена в методе InvokeVerb. Здесь мы должны написать код, который будет выполнен, если пользователь выбрал данное действие. В отличие от обсуждавшихся выше простых смарт-тегов, основанных на XML-списках, в реализации метода InvokeVerb может содержаться алгоритм любой степени сложности. В частности, в нем мы можем выводить на экран диалоговые панели, запускать другие приложения, осуществлять поиск в базах данных или в реестре и т.д. Можно выполнить разные действия для Word и Excel — чтобы определить, какое из этих приложений инициировало вызов метода InvokeVerb, мы можем использовать его параметр ApplicationName. В нашем же примере мы просто запустим Internet Explorer и откроем страницу с информацией о продукте, имя которого было распознано. Тем не менее в данном примере адрес страницы зависит от распознанного названия продукта.

Теперь нашу DLL можно скомпилировать и зарегистрировать (например, выбрав пункт меню Delphi Run | Register ActiveX Server). Однако для успешного применения созданного смарт-тега этого недостаточно. Ниже мы обсудим, что именно нужно для успешной поставки и тестирования таких DLL.

В начало В начало

Поставка и тестирование DLL, реализующих смарт-теги

Для регистрации созданной COM DLL как DLL, реализующей смарт-тег, нам следует найти (а возможно, и создать) следующие разделы реестра:

HKEY_CURRENT_USER\Software\Microsoft\Office\_Common\Smart Tag\Recognizers\
HKEY_CURRENT_USER\Software\Microsoft\Office\_Common\Smart Tag\Action

Первый из этих разделов должен содержать подраздел, название которого равно ProgID или CLSID COM-класса, реализующего интерфейс ISmartTagRecognizer, а второй должен содержать подраздел, название которого равно ProgID или CLSID COM-класса, реализующего интерфейс ISmartTagAction. Следует обратить внимание на то, что для тестирования смарт-тега достаточно ProgID, но в большинстве случаев лучше использовать CLSID. Дело в том, что смарт-теги можно отключать из приложений Office, но это состояние для библиотек, зарегистрированных с использованием ProgID, сохраняется только внутри пользовательской сессии. Результатом может быть, например, такое поведение смарт-тега: пользователь отключил распознаватель в Word или Excel, заново запустил приложение, но распознаватель снова оказался активным.

В отличие от Visual Basic, Delphi позволяет нам получить доступ к CLSID COM-объектов на этапе их разработки  — их можно найти в редакторе библиотек типов или в тексте соответствующего модуля (в нашем случае в st_TLB.pas).

Для регистрации смарт-тега можно создать соответствующий *.reg-файл и поставлять его вместе с DLL, реализующей смарт-тег, либо позаботиться о создании ключей реестра в инсталляционном приложении; InstallShield Express, входящий в комплект поставки Delphi, позволяет это делать. Можно также переписать процедуру регистрации DLL, реализующей смарт-тег, добавив в нее создание нужных разделов и ключей.

Как протестировать смарт-тег? Во-первых, нам нужно удостовериться, что уровень безопасности при использовании модулей расширения Office средний или низкий и что приложения Office позволяют использовать все установленные модули расширения (для этого следует вызвать диалоговую панель Security из меню Word или Excel Tools | Macro | Security).

Во-вторых, нам следует закрыть все приложения Microsoft Office, а также Internet Explorer. Рекомендуется также заглянуть на страницу Processes в Task Manager и выгрузить все процессы OUTLOOK.EXE, WINWORD.EXE, EXCEL.EXE и IEXPLORE.EXE.

В-третьих, нам следует запустить Microsoft Word 2002 или Microsoft Excel 2002 и проверить, найден ли наш смарт-тег (в данном случае Borland Web Site Smart Tag). Если да, мы увидим его название на странице SmartTags диалоговой панели AutoCorrect (ее можно вывести на экран, выбрав пункт меню Tools|Autocorrect Options — рис. 4).

Если мы не можем найти наш смарт-тег в диалоговой панели AutoCorrect, следует проверить, не отключен ли он из-за сбоя при загрузке библиотеки приложением Office. Для этой цели следует заглянуть в раздел реестра, соответствующего распознавателю:

HKEY_CURRENT_USER\Software\Microsoft\Office\_Common\Smart Tag\Recognizers\st.STR

Если мы найдем в этом разделе ключ Status, это означает, что смарт-тег отключен либо пользователем из приложения Office, либо самим приложением из-за сбоя при загрузке DLL. Если первое исключается — стоит заняться отладкой созданной DLL.

Еси смарт-тег обнаружен, можно протестировать его работу. Мы видим, что при появлении в документе названий продуктов Borland они помечаются как смарт-теги и, если мы выбираем действие Get product information from Borland web site, запускается Internet Explorer, в котором открывается страница, посвященная этому продукту (рис. 5).

Мы также можем убедиться, что данный смарт-тег корректно взаимодействует с другими смарт-тегами. Например, поскольку средство разработки Delphi названо в честь известного греческого города, это слово распознается не только как продукт Borland, но и как город в Европе, а следовательно, распознается и нашим смарт-тегом, и смарт-тегом, установленным вместе с Microsoft MapPoint 2002 (рис. 6).

В начало В начало

Заключение

В этом разделе мы научились создавать смарт-теги для Office XP с помощью Delphi. Мы убедились, что эта задача не очень сложная — нужно всего лишь создать COM DLL, в которой реализованы два интерфейса, и обеспечить ее корректную регистрацию. При этом реализация собственных смарт-тегов позволяет нам создавать интересные, полезные и недорогие решения, способные повысить эффективность работы пользователей и обеспечить их дополнительными сервисами — даже если эти пользователи не работают ни с чем, кроме приложений Microsoft Office.

КомпьюАрт 2'2002