Delphi, С++Builder и COM: вопросы и ответыНаталия Елманова После публикации осенью 1998 г. цикла статей, посвященных C++Builder и COM-технологии, в адрес редакции поступило много вопросов, связанных с проблемами использования COM в приложениях Delphi и C++Builder. Данная статья посвящена ответам на некоторые наиболее часто встречающиеся из них. Уважаемая Наталия! Я только начал изучать Delphi и
не могу решить простые задачи, например, такие как инсталляция новых
компонент *.ocx ("Компьютер Пресс CD, 1999, N 3). Установка ActiveX (OCX) в палитру компонентов осуществляется
просто: из меню среды разработки нужно выбрать опцию "Component/Import
ActiveX Control". Если в полученном списке нужного элемента не окажется,
нужно перед этим его зарегистрировать из командной строки: Regsvr32
<имя *.ocx-файла><имя *.ocx-файла> Уважаемый автор, Если имеются в виду объекты, вставляемые с помощью пункта
меню Word "Вставка/Объект", то обычно таким образом вставляются OLE-объекты,
поддерживаемые так называемыми серверами документов. Элементы ActiveX
могут и не являться такими серверами. Тем не менее, их можно вставить
непосредственно в документ Word 97, используя опцию "Элементы управления"
панели инструментов Visual Basic. На диалоговой панели "Элементы управления"
следует нажать кнопку "Дополнительные элементы" и выбрать нужный элемент
ActiveX. Он должен присутствовать в списке, если он зарегистрирован.
Если же нет, его можно зарегистрировать, выбрав опцию "Зарегистрировать
элемент управления". После создания и переноса CAB-файла и Web-страницы на Web-сервер эта страница в браузере открывается, но на месте предполагаемой активной формы появляется только квадратик. Разъясните, в чем может быть проблема Причин такого поведения может быть несколько. Первая
причина связана с тем, что далеко не все браузеры поддерживают отображение
ActiveX с помощью тега<OBJECT>. Для отображения ActiveX следует
использовать MS Internet Explorer версии 3.0 и выше (отметим, что в
комплект поставки некоторых 32-разрядных версий Windows входит более
ранняя версия этого браузера) либо Netscape Communicator, оснащенный
соответствующим модулем расширения (plug-in). Дело в том, что Netscape
Communicator позиционирует себя на рынке как многоплатформенный браузер,
поэтому сам по себе он не отображает элементов управления ActiveX, так
как ActiveX есть технология, специфичная для Windows. С удовольствием прочитал вашу статью: "Создание контроллеров автоматизации....", но по ходу дела у меня возник ряд вопросов: Как заставить управляемое приложение остаться активным после завершения контроллера. Пример: некая программа генерирует отчет, управляя редактором Word. Требуется, чтобы после того как отчет создан, окно Word не закрывалось. Я добился этого методом вызова функции AddRef применительно к управляемому объекту, но подозреваю, что этот способ не корректен. В принципе можно использовать вызов функции AddRef. Но наиболее принятый способ (если используются вариантные переменные, как в примерах из статьи "Создание контроллеров автоматизации...") — поместить вариантную переменную в глобальную область видимости приложения-контроллера. В этом случае данные, содержащиеся в этой переменной, могут существовать, пока запущено приложение-контроллер, а вместе с ними остается активным и сам COM-сервер (если, конечно, из приложения-контроллера не был вызван метод, приводящий к его закрытию, и если этой вариантной переменной не было присвоено другое значение). Я не понял, как формируется имя сервера, занесенное в реестр (Project1.MyAuto3)? MyAuto3 — мы задаем явно, а откуда берется Project1??? Project1 в данном случае есть имя исполняемого файла COM-сервера. MyAuto3 — это имя COM-объекта, реализованного в данном сервере (COM-объектов в одном сервере может быть и несколько). Мой вопрос связан с автоматизацией Excel из приложений
Delphi. Например, вполне нормально выполняется код, написанный в Delphi: var v:variant; begin v := CreateOleObject('Excel.Application.8'); v.Visible:= True; v.WorkBooks.Add; v.Range('A2') := 12; v.ActiveCell.FormulaR1C1 := '=RAND()'; v.ActiveCell.Font.Bold := True; end;Почему при этом не выполняется команда: v.Range('A2').Select; При этом появляется сообщение об ошибке: Member not found. Точно так же не выполняются и многие другие команды, которые можно найти в макросах Excel. Я экспериментировал с Visual FoxPro 5.0, и все команды (макросы) из Excel можно переносить в него практически без изменений, подставляя впереди имя переменной, например v.Range('A2').Select На самом деле в Delphi подобная команда выглядит так:
Иными словами, если Вы пользуетесь справкой по Visual Basic for Applications, нужно менять в содержащихся в ней примерах не только кавычки, но и скобки. Дело в том, что получающийся код должен удовлетворять требованиям синтаксиса языка программирования того средства разработки, на котором пишется контроллер Excel. Хотя синтаксис Pascal и позволяет создавать видимость того, что мы вызываем методы вариантной переменной (не все языки программирования позволяют это делать, например, в C++ так с вариантными переменными обращаться нельзя), из этого не следует, что в него можно включать синтаксические конструкции из Visual Basic без изменений. Что касается FoxPro — синтаксис используемого в этом средстве разработки языка с этой точки зрения (я имею в виду именно употребление скобок и кавычек в описании методов переменных, содержащих ссылки на COM-объекты), видимо, более близок к Visual Basic, чем синтаксис Pascal. Чем с точки зрения синтаксиса может при автоматизации Excel помочь импорт библиотеки типов? Если рассматривать только проблемы синтаксиса, импорт
библиотеки типов полезен, скорее, в случае С++, а не Pascal. 1) Form1.Show — этот оператор использует настоящий метод класса TForm (аналог на C++ — Form1->Show()); 2) Var V:variant; V:=CreateOleObject('Excel.Application'); ..... V.Visible:=True; — Здесь используется "метод" для установки "свойства" варианта, но в действительности это инициирование вызова удаленных процедур в Excel (и его внутренних методов). В данном случае внутренний метод Excel, предназначенный для показа его окна, может называться как угодно, и "Show" есть лишь внешнее опубликованное имя этого внутреннего метода. Аналог на C++ : Variant V; V=CreateOleObject("Excel.Application"); V.OlePropertySet("Visible",true); //! Итак, мы видим, что на самом деле "Visible" с точки зрения
C++ — это просто строка. Иными словами, и Visual Basic, и Delphi, и
Visual FoxPro просто совершают некоторые манипуляции со строками, позволяя
помещать их в исходный текст без явного указания, что это строки, и
тем самым заставляя думать, что мы вызываем методы вариантной переменной.
C++ таких вещей делать не позволяет. Зато его код иллюстрирует, что
происходит на самом деле при автоматизации Excel в Visual Basic или
Delphi. Фактически "Visible" — просто строка, передаваемая в Excel из
приложения-контроллера. Импорт же библиотеки типов позволяет создать
объекты в адресном пространстве контроллера автоматизации, имеющие те
же методы, что и объекты в адресном пространстве Excel. Соответственно
можно вызывать настоящие методы этого "своего" объекта, а их реализация
на самом деле будет заключаться в вызове удаленных процедур, обращенных
к Excel (даже если это локальный Excel), которые инициируют манипуляции
уже с внутренними объектами Excel. Соответственно после этого синтаксис
на любом языке будет похож (с точностью до скобок, кавычек и указателей)
на синтаксис Visual Basic. V.Visible=true становится верным. Есть ли возможность с помощью Delphi или C++Builder создать контроллер автоматизации одновременно для Excel 7 и Excel 97? Если нужно создать приложение-контроллер, совместимое
и с текущей, и с прежней версиями Excel, лучше или не импортировать
библиотеку типов, или импортировать, но использовать позднее связывание
по изложенным выше причинам (в документации к Delphi подробно описано,
как это сделать), и не использовать вызовы методов, отсутствующих в
старой версии Excel. |