На этом шаге мы рассмотрим общие принципы создания контроллеров автоматизации Microsoft Office.
В общем случае контроллер автоматизации должен выполнять следующие действия.
Соответствующий код для Delphi представлен ниже:
procedure TForm1.Button1Click(Sender: TObject); var ServerIsRunning : Boolean; Unknown : IUnknown; Result : HResult; AppProgID : String; App : Variant; begin // Указать программный идентификатор приложения-сервера AppProgID := 'Word.Application'; ServerIsRunning := False; Result := GetActiveObject(ProgIDToClassID(AppProgID),nil,Unknown); if (Result = MK_E_UNAVAILABLE) then // Создать один экземпляр сервера App := CreateOleObject(AppProgID) else begin // Соединиться с уже запущенной копией сервера App := GetActiveOleObject(AppProgID); ServerIsRunning := True; end; // Показать окно приложения на экране App.Visible := True; // ------------------------------------------ // Здесь выполняются другие действия // с объектами приложения Office // ------------------------------------------ if not ServerIsRunning then App.Quit; App:= Unassigned; end;
Здесь мы воспользовались функциями GetActiveOleObject и CreateOleObject для подключения к уже запущенной копии приложения-сервера или запуска новой, если сервер не запущен, что приводит к тому, что в вариантную переменную помещается ссылка на объект Application соответствующего сервера.
В заключение сделаем одно маленькое замечание касательно числа параметров методов объектов автоматизации. В случае позднего связывания число указанных в коде параметров метода не обязано совпадать с их истинным числом, которое можно найти в описании объектной модели соответствующего приложения. В этом случае, несмотря на то что метод Quit объекта Application для некоторых приложений Microsoft Office (например, Microsoft Word) имеет параметры, вполне допустимым является следующий код:
App.Quit;
С другой стороны, при раннем связывании следует строже подходить к определению параметров - их число и типы должны соответствовать описанию методов в библиотеке типов. Например, в случае раннего связывания корректный код на Delphi для закрытия документа Word со значениями всех параметров по умолчанию будет иметь вид:
App.Quit(EmptyParam, EmptyParam, EmptyParam);
Помимо перечисленных технических принципов хотелось бы обратить внимание на некоторые соображения организационного характера. Как правило, при создании контроллеров автоматизации подобных приложений не рекомендуется предоставлять конечному пользователю доступ к пользовательскому интерфейсу сервера, по крайней мере, в те моменты, когда свои действия выполняет контроллер. В противном случае из-за возможного нежелательного и непредсказуемого вмешательства пользователя результат работы контроллера может оказаться отличным от ожидаемого. В связи с этим отметим, что манипуляция свойством Visible объекта Application может быть одним из средств решения данной проблемы - пока это свойство равно False, окна приложения не только невидимы, но и неспособны обрабатывать события, инициируемые мышью или клавиатурой, и поэтому вмешательство конечного пользователя в их работу исключено.
В связи с вышеизложенным отметим, что у объекта Application всех приложений семейства Microsoft Office имеется свойство DisplayAlerts, указывающее, выводить или нет на экран диагностические сообщения, которые предназначены пользователю, работающему с приложением интерактивно (например, вопрос о том, перезаписывать ли уже существующий файл). При создании контроллеров автоматизации приложений Microsoft Office нередко это значение устанавливают равным False, поскольку в общем случае, во-первых, контроллер и сервер могут быть запущены на разных компьютерах, а во-вторых, как было только что отмечено, сервер может функционировать в режиме, в котором его пользовательский интерфейс полностью недоступен, и в этом случае сервером не обрабатываются события, инициируемые мышью или клавиатурой.
Со следующего шага мы начнем рассматривать автоматизацию Microsoft Word.