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