Borland delphi 4 0 для начинающих элементы управления activex


Содержание

Borland delphi 4 0 для начинающих элементы управления activex

Статья опубликована на сайте www.citforum.ru

1 Что такое ActiveX

Технология ActiveX, рассматриваемая в данной статье, базируется на технологии Microsoft COM (Component Object Model — модель компонентных объектов), позволяющей создавать и использовать программные компоненты, предоставляющие различные сервисы другим приложениям, компонентам и операционной системе. COM представляет собой одну из реализаций концепции распределенных вычислений, базирующейся в общем случае на предоставлении возможности приложениям использовать для расширения своей функциональности готовые компоненты и объекты (иногда они называются сервисами). Технология COM позволяет использовать объектно-ориентированный подход не в рамках одного приложения, а в рамках операционной системы, но, в отличие от стандартных классов, определенных в исходном тексте и реализуемых как объекты в адресном пространстве одного процесса, эти компоненты могут в общем случае располагаться в адресных пространствах разных процессов и даже на разных компьютерах.

В настоящее время существуют три типа спецификаций COM, определенных Microsoft и включающих большое количество интерфейсов и функций:

  • OLE-документы — составные документы, содержащие внедренные или связанные объекты. Эта спецификация описывает правила создания контейнеров для таких документов с «активацией по месту». Отметим, что компонент OLEContainer Delphi и C++Builder создан с учетом этой спецификации (этой теме будет посвящена одна из следующих статей данного цикла).
  • OLE Automation. Эта спецификация описывает, как создать сервер и контроллер, управляющий его поведением с помощью скриптов или макросов. Эта спецификация также поддерживается Delphi и C++Builder (об этом также пойдет речь в ближайших статьях данного цикла).
  • Управляющие элементы ActiveX, использующие специальный вариант протокола Automation (о них-то и пойдет речь в данной статье).

Использование COM, и, в частности, технологии ActiveX, позволяет обеспечить создание приложений, собираемых из готовых компонентов — элементов управления ActiveX, отличающееся от привычной пользователям C++Builder или Delphi разработки приложений с помощью VCL-компонентов тем, что такая «сборка» не зависит от того, на каком языке написаны как готовые компоненты, так и использующее их приложение — лишь бы средство разработки поддерживало возможность использования таких компонентов в разрабатываемом приложении (такое приложение обычно называется контейнером).

Элементы управления ActiveX представляют собой библиотеки, содержащие исполняемый код. Как было сказано выше, эти библиотеки могут быть использованы в различных приложениях как встроенные элементы управления, поэтому они обладают свойствами, событиями и методами, доступными посредством автоматизации. Современные средства разработки, как правило, позволяют включать такие элементы в создаваемые с их помощью приложения. Помимо этого, элементы управления ActiveX нередко используются в качестве расширений web-броузеров с целью придания им дополнительной функциональности, например, для отображения документов, отличных от поддерживаемых данным броузером.

Как любой COM-сервер, элемент управления ActiveX обладает уникальным идентификатором GUID и должен быть зарегистрирован в реестре. На основании этой записи может быть осуществлен поиск местоположения файла с расширением *.ocx, содержащего его реализацию.

Таким образом, создав элемент управления ActiveX, обладающий интересующей Вас функциональностью, Вы можете в дальнейшем позволить его пользователям встраивать этот элемент в свои приложения (например, написанные на Visual Basic, PowerBuilder, Delphi, C++Builder и др.), отображать его в web-броузере в составе выгруженной с Вашего web-сервера HTML-страницы, включать его в состав документов MS Office, при этом Вы не обязаны предоставлять исходный текст этого компонента.

Когда следует создавать управляющие элементы ActiveX? Естественно, в тех случаях, когда функциональность, содержащаяся в таком элементе, уникальна. Нет смысла создавать ActiveX, реализующий функциональность кнопки или текстового редактора — таких элементов управления, в том числе выполненных в виде ActiveX, на рынке готовых компонентов более чем достаточно. Нет смысла также создавать ActiveX, если он будет использоваться только в C++Builder — в этом случае проще создать VCL-компонент, который будет работать в использующем его приложении значительно быстрее, чем аналогичный ActiveX. Но создание элемента управления, реализующего, к примеру, часть автоматизированного рабочего места какой-либо категории сотрудников Вашего предприятия может в ряде случаев оказаться весьма полезным, особенно в следующих двух случаях. Первый случай — использование на предприятии различных средств разработки, например, C++Builder и Visual Basic; в этом случае разработчик, использующий Visual Basic, может встраивать в свои приложения ActiveX, созданный другим разработчиком и реализующий какую-либо функциональность, используемую несколькими различными автоматизированными рабочими местами. Второй случай — широкое использование Internet или intranet при автоматизации предприятия. В этом случае ActiveX, реализующий подобную функциональность, может быть встроен в HTML-страницу и отображен в web-броузере. Такой подход существенно облегчает решение проблемы обновления версий автоматизированных рабочих мест, так как вместо установки новых версий на рабочих станциях достаточно заменить один экземпляр ActiveX, хранящийся на web-сервере. Наиболее ярким примером такого подхода может быть выполненный в виде ActiveX «тонкий» клиент, получающий данные от удаленного сервера приложений, являющегося, в свою очередь, клиентом серверной СУБД.

Такой набор преимуществ сделал эту технологию за последние два года весьма популярной, и именно поэтому многие современные средства разработки, такие, как Delphi или С++Builder, позволяют создавать элементы управления ActiveX. Эти средства обычно имеют встроенные механизмы поддержки спецификации ActiveX с помощью автоматической генерации соответствующего кода (хотя, конечно, не возбраняется писать подобный код вручную).

Спецификация ActiveX представляет собой набор правил (а именно описание стандартных интерфейсов), с помощью которых следует создавать такие элементы управления. Отметим, что текущая версия этой спецификации учитывает возможность использования в качестве контейнера web-броузеров и необходимость загрузки элементов ActiveX с удаленных web-серверов с их автоматической регистрацией.

2 Создание элементов управления ActiveX на основе VCL-компонентов

Как было сказано выше, C++Builder 3 позволяет создавать элементы управления ActiveX на основе VCL-компонентов. Для этой цели используется библиотека Microsoft ATL (Active Template Library), являющаяся на сегодняшний день индустриальным стандартом и позволяющая создавать элементы ActiveX, представляющие собой скомпилированный код и не требующие дополнительных run-time-библиотек для их выполнения. Процесс создания такого элемента управления весьма прост.

Для создания элемента управления ActiveX следует выбрать из репозитария объектов страницу ActiveX и далее — элемент ActiveX Control.

Далее следует заполнить появившуюся диалоговую панель:

Рис.1. Выбор имени ActiveX, имен модулей и базового VCL-класса

Следует выбрать VCL-компонент, на основе которого будет создан элемент ActiveX. В качестве примера выберем TCalendar.

Отметим, что при выборе опции Include Design-Time Licence автоматически будет сгенерирован файл с расширением *.lic, без которого данный ActiveX нельзя будет использовать ни в каких средствах разработки, но можно поставлять с готовыми приложениями. Использование такого файла бывает удобно в случае, когда ActiveX поставляется бесплатно его автором в составе готового продукта, но требует отдельного лицензирования при встраивании его другими пользователями в свои разработки.

В результате работы ActiveX Control Wizard будут созданы несколько модулей, сгенерирован уникальный идентификатор (GUID) будущего ActiveX, а также соответствующая библиотека типов.

Рис.2. Проект библиотеки ActiveX в С++Builder

Библиотека типов содержит сведения о свойствах, событиях и методах компонента ActiveX, унаследованных от исходного VCL-компонента.

Рис.3. Библиотека типов созданного элемента ActiveX

В коде, связанном с реализацией ActiveX, можно найти описание этих свойств и методов.

Далее следует сохранить и скомпилировать проект и зарегистрировать элемент ActiveX в реестре. Это делается с помощью выбора пункта меню Run/Register ActiveX Server.

После этого можно протестировать созданный ActiveX-компонент, открыв его, например, в Visual Basic. Отметим, что последние версии именно этого средства разработки широко используют элементы управления ActiveX в качестве составных частей создаваемых с их помощью приложений; фактически приложения Visual Basic собраны целиком из ActiveX-компонентов. Более того, спецификация ActiveX создана с учетом того, что в первую очередь Visual Basic и Visual C++ (и лишь затем остальные средства разработки) могут быть контейнерами для этих элементов управления. Поэтому тестирование поведения ActiveX в VisualBasic может более или менее гарантировать, что в других средствах разработки этот управляющий элемент будет вести себя точно так же.

В случае отсутствия Visual Basic можно воспользоваться и более широко распространенным Visual Basic for Applications. С этой целью можно запустить Microsoft Word 97, создать новый документ и выбрать на панели инструментов кнопку «Редактор Visual Basic». Далее следует выбрать в окне «Project» имя вновь созданного документа, щелкнуть по нему правой кнопкой мыши и из полученного контекстного меню выбрать опцию «Вставить/UserForm». На экране появится редактор форм Visual Basic и панель элементов. Далее нужно щелкнуть правой клавишей мыши по панели элементов и выбрать из контекстного меню опцию «Дополнительные элементы». Теперь следует из появившегося списка всех зарегистрированных элементов управления ActiveX выбрать нужный, и он автоматически окажется на панели элементов Visual Basic (можно поместить его на единственную имеющуюся страницу управляющих элементов или создать свою, выбрав опцию «Создать страницу» из контекстного меню ярлычков блокнота, расположенного на панели элементов).

После этого можно поместить наш ActiveX на форму и попытаться изменить какие-либо его свойства, используя для этой цели окно «Свойства».

Рис.4. Тестирование ActiveX в Visual Basic

И, наконец, можно вернуться в редактируемый документ, поместить на него кнопку, дважды щелкнуть по ней и в окне редактора кода создать процедуру, показывающую созданную форму, вписав в сгенерированный код строку UserForm1.Show :

Private Sub CommandButton1_Click()
UserForm1.Show
End Sub

Теперь можно нажать на панели инструментов «Visual Basic» кнопку «Выход из режима конструктора». После этого нажатие на созданную в теле документа кнопку приведет к появлению диалоговой панели с созданным нами элементом управления.

Можно было бы, конечно, протестировать поведение созданного ActiveX, установив его в палитру компонентов Delphi или C++Builder,, но это не самый лучший способ тестирования — ведь в основе создания нашего ActiveX лежит та же самая библиотека VCL, что и в основе создаваемого приложения для тестирования ActiveX. Использование для этой цели любого не имеющего отношения к VCL средства разработки, способного использовать элементы управления ActiveX в создаваемых приложениях, более оправдано. При этом следует заметить, что Visual Basic for Applications представляет собой наиболее часто встречающееся средство разработки такого класса, так как входит в состав самого популярного в нашей стране офисного пакета.

3 Создание страниц свойств

Так как элементы управления ActiveX могут быть использованы в средствах разработки, нередко они обладают набором страниц свойств, позволяющим пользователям менять те или иные свойства этого элемента управления.

Для создания страницы свойств выберем из репозитария объектов страницу ActiveX и элемент Property Page. В результате получим форму, на которой можно размещать интерфейсные элементы.

Создадим страницу для редактирования свойств CalendarDate и GridLineWidth. Для этого разместим на вновь созданной форме два компонента TStaticText и два компонента TEdit.

Рис.5. Страница свойств на этапе проектирования

В созданной форме имеются сгенерированные прототипы обработчиков событий UpdatePropertyPage и UpdateObject. Добавим в них соответствующий код:

Далее следует создать ссылку на странице свойств в модуле, описывающем реализацию элемента ActiveX. С этой целью следует модифицировать h-файл .Модификация кода заключается во вставке строки, указывающей на необходимость регистрации страницы свойств:

Следует также включить ссылку на h-файл страницы свойств в h-файл реализации ActiveX.

Далее следует заново скомпилировать библиотеку ActiveX и зарегистрировать ее.

Если теперь в среде разработки Visual Basic поместить на пользовательскую форму наш ActiveX и выбрать страницу свойств «Специальные», получим созданную нами страницу:

Рис.6. Страница свойств на этапе тестирования ActiveX

При изменении значений в компонентах TEdit можно убедиться, что изменяются и соответствующие свойства элемента ActiveX.

Рис.7. Результат использования страницы свойств

4 Создание активных форм

Активная форма — это элемент управления ActiveX, содержащий несколько VCL-компонентов. Возможность создания таких элементов управления позволяет существенно расширить круг доступных для элементов ActiveX функциональных возможностей. Создание такого ActiveX происходит примерно так же, как и создание обычного приложения.

Попробуем создать простейший пример такого элемента управления. Для его создания следует выбрать со страницы ActiveX репозитария объект ActiveForm, ответить на вопросы об имени компонента, после чего в дизайнере форм получим пустую форму — заготовку будущего ActiveX. Добавим на эту форму компоненты TCheckBox, TButton, TImage и TOpenPictureDialog.

Рис.8. Активная форма на этапе проектирования

Создадим обработчики событий, связанных с TCheckBox и TButton:

Теперь можно скомпилировать приложение, зарегистрировать созданный ActiveX и протестировать его указанным выше способом.

Рис.9. Тестирование активной формы в Visual Basic

Можно также протестировать созданный ActiveX c помощью отображения его в Internet Explorer. Для этой цели можно выбрать пункт меню Project/Web Deployment Options и на странице Project в полях Target dir, Target URL, HTML dir этого диалога указать имя какого-нибудь локального каталога.

Затем можно выбрать опцию Project/Web Deploy и по окончании работы Web Deployment Wizard открыть в Internet Explorer автоматически сгенерированную С++Builder html-страницу c именем, совпадающим с именем созданного проекта:

Рис.10. Тестирование активной формы в Internet Explorer

Отметим, что для успешного отображения ActiveX в броузере требуется Microsoft Internet Explorer версии 3.0 и выше, при этом настройки уровня безопасности должны позволять запуск активного содержимого, расположенного в Intranet-зоне. Если в качестве броузера используется Netscape Navigator, он должен быть оснащен модулем расширения (plug-in), позволяющим интерпретировать тег языка HTML как элемент управления ActiveX (естественно, такая возможность существует только для версий Navigator, выполняющихся под управлением 32-разрядных версий Windows). Отметим также, что сгенерированную автоматически страницу можно в дальнейшем отредактировать с помощью любого html-редактора (или даже любого текстового редактора).

При поставке ActiveX через Web процедура аналогична описанной, но вместо локальных каталогов в строке URL следует указать Internet-адрес Web-сервера:

Рис.11. Настройка опций поставки ActiveX через Internet

Помимо этого, следует обратить внимание на дополнительные «пакеты» или другие файлы, которые следует включить в поставку, если опции проекта таковы, что требуют использования каких-либо дополнительных библиотек.. Разделение ActiveX на несколько файлов и выделение отдельных пакетов может быть использовано для того, чтобы уменьшить в целом время загрузки ActiveX через Internet, например, в случае предстоящей необходимости обновления версии ActiveX или при поставке нескольких разных ActiveX — в этом случае часть «пакетов» может быть установлена один раз, а далее производится поставка лишь небольшой содержательной части элемента ActiveX. Впрочем, не возбраняется создавать ActiveX и в виде одного файла. Отметим также, что при выборе опции Include CAB File compression можно собрать используемые файлы в один файл с расширением *.cab, фактически представляющий собой архив, что также уменьшает примерно в два раза время загрузки файлов через Internet.

Следует отметить, что в активных формах можно использовать практически все компоненты C++Builder, кроме TMainMenu. Возможна также динамическая генерация дополнительных форм на этапе выполнения, при этом дополнительные формы уже не будут содержаться в контейнере, а будут представлять собой обычные формы Windows (и, естественно, могут содержать в том числе и TMainMenu).

В заключение отметим, что, редактируя библиотеку типов, можно к созданным ActiveX добавлять свойства и методы и затем описывать их реализацию в соответствующем модуле. Более подробно о библиотеках типов, их назначении, создании, редактировании будет рассказано в последующих статьях данного цикла.

Дополнительную информацию Вы можете получить в компании Interface Ltd.

Программирование Delphi

Все о программировании.

Главное меню

Как импортировать управление ActiveX в Delphi

Давайте разберемся как добавить управление ActiveX в Ваши проекты Delphi.

  1. Запустите Delphi и выберите Component->Import ActiveX Control.
  2. Найдите управление ActiveX, которое Вы хотите импортировать (диалоговое окно отображает все ActiveX управления, зарегистрированные в Вашей системе). Назовем его SomeActiveX
  3. Выберите положение на Палитре Компонентов, куда Вы хотите поместить выбранную библиотеку
  4. Возможно лучше оставить выбранную опцию ActiveX
  5. Нажмите Install
  6. Выберите пакет, куда новый компонент должен быть установлен или
  7. Создайте новый пакет для нового управления TSomeActiveX
  8. Нажмите OK
  9. Delphi спросит Вас, хотите ли Вы перестроить измененный/новый пакет или нет
  10. Нажмите Да
  11. После того, как пакет откомпилируется, Delphi выведет сообщение, что новый компонент TSomeActiveX был зарегистрирован и уже доступен как часть VCL
  12. Закройте окно, позволяя Delphi сохранить изменения
  13. Теперь компонент доступен на вкладке ActiveX (если Вы не меняли эту настройку в шаге 3)
  14. Теперь просто поместите компонент на форму и используйте его

Примечание: эта оболочка будет интегрирована в исполняемый файл (или пакет во время выполнения), но .OCX файл для этого компонента должен быть зарегистрирован на Вашем компьютере в системе перед использованием.

Инсталляционные программы, типа InstallShield Express автоматизируют этот процесс регистрации.

Borland delphi 4 0 для начинающих элементы управления activex

procedure TFormI.mnuEditCopyClick(Sender: TObject);

Все, что происходит в мире Windows, базируется на сообщениях. Для выполнения какой-либо функции управляющие элементы часто отсылают сообщения самим себе. Так и в этом примере управление происходит путем передачи сообщения WMCOPY.

Это свойство возвращает объект TForm, имеющий фокус ввода. Если приложение неактивно, свойство указывает, какая именно форма будет иметь фокус ввода при активизации приложения. В качестве примера используем свойство для создания мигающего заголовка формы, чтобы привлечь внимание пользователя. Функция Windows API, предназначенная для этой цели, должна получить дескриптор окна:

Это свойство определяет форму указателя мыши для всего приложения. Обычно оно используется для отображения песочных часов, чтобы в то время, пока пользователь думает о сложной работе, выполняемой приложением, немного передохнуть.

for iCount:=1 to 1000000000 do;

Форму указателя можно изменить для каждого потомка TControl (включая ТForm) отдельно.

Forms и FormCount

Эти свойства возвращают список форм и их количество. Работа с ними ничем не отличается от работы со списком дочерних окон, описанных в разделе „MDIChildren и MDIChildCount“.

Это наиболее полезные свойства, возвращающие высоту и ширину экрана в пикселях. Они могут применяться во многих ситуациях, например при определении местоположения формы. Вот как поместить форму в центре экрана.

Left:= (Screen.Width — Width) div 2;

Top:= (Screen.Height — Height) div 2;

tscreen предоставляет два основных события, извещающие программу об изменении фокуса ввода. Подобно возможностям класса TApplication, возможности класса TScreen доступны лишь при выполнении.

Это событие возникает при передаче фокуса ввода от одного управляющего элемента к другому. Свойство

ActiveControl обновляется непосредственно перед вызовом события. Вы можете использовать событие, например, для вывода текста подсказки в строке состояния.

procedure TFormI.ActiveControlChangeHandler(Sender: TObject);

if (not Application.Terminated) then

Проверка связана с тем, что событие генерируется и при закрытии приложения, а при этом обращение к уже уничтоженному объекту вызовет исключительную ситуацию.

Событие генерируется при создании новой формы или передаче фокуса ввода от одной формы к другой. Обычно это событие используется в MDI-приложениях для обновления доступных функций меню и кнопок-ускорителей. Ниже приведен пример из шаблона MDI-приложения.

procedure TMainForm.UpdateMenuItems(Sender: TObject);

FileCloseItem.Enabled:= MDIChildCount 0;

FileSaveItem.Enabled:= MDIChildCount 0;

FileSaveAsItem.Enabled:= MDIChildCount 0;

Процедура UpdateMenuItems назначена в качестве обработчика событию OnActiveFormChange в обработчике

procedure TMainForm.FormCreate(Sender: TObject);

Разделяемые обработчики событий

Как вы уже знаете, каждый класс способен генерировать свои собственные события. Каждое из них имеет определенный тип, как, например, TNotifyEvent у OnClick и TCloseEvent у OnClose. Delphi позволяет написать один обработчик события и назначить его нескольким событиям одновременно.

Представьте себе объект TEdit, генерирующий события OnKeyDown и OnKeyUp. Поскольку оба события — одного типа, можете написать одну процедуру и назначить ее обоим событиям. Процедура будет вызываться дважды при каждом нажатии клавиши (при нажатии и отпускании). Или, например, вы можете создать один обработчик для событий OnCreate и OnClick.

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

Вот как создать разделяемый между классами TButton и TEdit обработчик OnClick.

Выберите из меню File/New Application для создания приложения.

Поместите TButton в форму и введите в обработчик OnClick следующий код. procedure TFormI.ButtonlClick (Sender: TObject);

Поместите TEdit в форму. В Object Inspector выберите в списке для события OnClick обработчик ButtonClick. Теперь после щелчка на кнопке и на объекте TEdit будут выполняться одни и те же действия, фокус ввода будет передаваться управляющему элементу TEdit, и весь текст в нем будет выделяться.

Поскольку множество объектов может разделять один обработчик событий, необходимо уметь выяснять, какой именно обработчик его сгенерировал. Для этого предназначен параметр Sender, передаваемый в каждый обработчик, который указывает на объект, сгенерировавший событие. Часто этот параметр используется для различных действий обработчика в зависимости от того, кто именно породил событие.

Создание одноэкземплярного приложения

Если в Windows несколько раз щелкнуть на пиктограмме приложения, по умолчанию запустится сразу несколько его копий. Чтобы избежать этого, т. е. не дать запуститься второй копии приложения, необходимо выполнить поиск по заголовкам окон.

Поиск по заголовкам окон

При создании экземпляра окна Windows требует зарегистрировать имя класса окна (window class name). Delphi использует класс формы в качестве имени класса окна, например, когда Delphi создает экземпляр Form1 класса TForm1, TForm1 используется в качестве имени для регистрации окна Form1. Каждая форма имеет свойство Caption, известное как заголовок окна (window title). Эти два параметра позволяют искать окно с помощью функции Windows API FindWindow, возвращающей дескриптор найденного окна.

Эту функцию нельзя вызывать из класса TForm1, так как к тому времени окно уже будет создано, и вы окажетесь в глупом положении, найдя сами себя. Вот код, который должен находиться в файле проекта.

if FindWindow(‘TFormi’,’Formi’) о 0 then Application.Terminate;

Поскольку вы используете функцию Windows API, проследите, чтобы был подключен модуль Windows.

Если вы запускаете это приложение из Delphi, учтите, что Form Designer уже создал такое окно, и вы всегда сможете его найти. Это приложение следует запускать отдельно, закрыв Delphi.

Изменив свойство Caption или Name, вы рискуете не найти своего окна и придется повозиться с кодом программы, чтобы отследить эти изменения. Может возникнуть ситуация, когда простое совпадение приведет к тому, что окно будет найдено в совсем другом приложении, которое будет опознано как свое.

Активизирование существующей копии

Все-таки, сказать пользователю „Ты уже запустил одну копию, теперь иди и ищи ее!“ — как-то негуманно… Более профессиональным решением будет активизировать существующую копию с помощью другой функции Windows API — SetForegroundWindow. Измените проект следующим образом.

Образовательный блог — всё для учебы

Расширение возможностей СОМ технологии привело к идее компонентного построения программ, что позволяет использовать только те части программы, которые нужны в настоящий момент для выполнения поставленной задачи.

С течением времени возможность создания элементов управления ActiveX была включена и в другие системы быстрой разработки приложений, включая и Delphi.

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

Работа элементов ActiveX основана на реализации двух основных интерфейсов: lOleControl и lOleControlSite.

Технология создания ActiveX в Delphi (DAX) включает следующие возможности:
• создание элементов управление ActiveX;
• создание активных форм ActiveForm;
• инсталляцию готового элемента управления ActiveX в среду Delphi.

Основы работы управляющих элементов

Элементы управления ActiveX представляют собой динамические библиотеки-серверы, содержащие исполняемый код и исполняемые в адресном пространстве клиентского приложения (контейнера). Они включают уникальный идентификатор GUID и должны обладать возможностью саморегистрации в реестре Windows, которая фактически является основным отличием элементов управления ActiveX от СОМ-объектов.

Естественно, что взаимодействие между СОМ-субъектами: управляющим элементом и его контейнером определяется интерфейсами.

Спецификация управляющих элементов включает следующие аспекты их функционирования, для реализации которых предназначены свои группы интерфейсов:
• обеспечивающие пользовательский интерфейс;
• вызывающие методы управляющих элементов контейнером;
• посылающие события контейнеру;
• получающие данные о свойствах среды контейнера и обеспечивающие
доступ к свойствам управляющего элемента и их модификации
а) Для обеспечения пользовательского интерфейса предназначены такие интерфейсы, как: IOlelnPlaceActiveObject, IOlelnPlaceObject, IOleObject, IDa-
taObject, IViewObject2, IOleCache2, IRunnableObject, IPersistStorage.
б) Для обеспечения возможности вызова методов достаточно включить интерфейс IDispatch, с помощью метода Invoke которого можно вызывать необходимые методы. Фактически методы можно вызывать через виртуальную таблицу (раннее связывание) или через Dispatch интерфейс (позднее связывание).
в) Для обеспечения возможности посылки событий контейнеру следует
включить поддержку таких интерфейсов, как: IProvideClasslnfo2, IConnection-PointContainer, IConnectionPoint.
г) В элементы управления ActiveX добавлена возможность работы со свойствами, которых нет в OLE Automation.

Основы работы контейнеров

Контейнеры предназначены для включения управляющих элементов в приложения
Для решения проблемы взаимодействия компонентов и контейнеров введены понятия категорий компонентов (component categories), позволяющие управляющему элементу информировать компоненты о своих возможностях, помещая в реестр идентификаторы категорий — GUID (category identifier — CATID), гарантирующих способность выполнять некоторые функции. Анализируя CATID без создания экземпляров компонентов, контейнеры могут получать сведения о возможностях управляющих компонентов.

Контейнер должен иметь клиентский узел (client site), с помощью которого происходит связывание элемента ActiveX с контейнером.

Создание управляющих элементов ActiveX

Для создания управляющего элемента в Delphi можно воспользоваться соответствующим конструктором, позволяющим создавать элементы ActiveX из компонентов Delphi, являющихся наследниками класса TWinControl. Фактически конструктор позволяет создать необходимую «оболочку» вокруг компонента для превращения его в управляющий элемент.

Процесс создания элемента ActiveX состоит из следующих этапов:
• Создать с помощью конструктора «каркас» библиотеки, выполнив команды:
File\New\ ActiveX Library
• Запустить конструктор, создающий элемент ActiveX из VCL компонента:
File\New\ ActiveX Control.
• Выбрать компонент и заполнить сведения об элементе Для этого в открывшемся окне ActiveX Control Wizard из раскрывающегося списка VCL
Class Name следует выбрать зарегистрированный в Delphi компонент, который предполагается использовать для создания элемента управления ActiveX
• Скомпилировать и зарегистрировать элемент управления ActiveX, ко
мандами:
RunVRegister ActiveX Server
Созданный в результате компиляции файл получит расширение * Осх.

Создание активных форм

Delphi предоставляет также возможность создавать Active-формы, позволяющие помещать в нее несколько компонентов и все целиком использовать как элемент управления ActiveX.

Процесс создания элемента ActiveX состоит из следующих этапов:
• Создать экранную форму, выполнив команды: File\New\ ActiveForm
• Далее следует расположить на экранной форме нужные компоненты, написать соответствующий программный код и сохранить заготовку экран
ной формы.

Созданный файл получит расширение *.Осх.

Инсталляция управляющих элементов ActiveX
ComponetUmport ActiveX Control…
Откроется окно Import ActiveX, в верхней части которого будет представлен список библиотек элементов управления ActiveX, зарегистрированных в Windows. После выбора нужной из библиотек, Delphi прочитает ее библиотеку типов и составит список элементов управления.

Новые книги

Книга адресована собственникам и первым лицам малого и владельцам среднего бизнеса, самозанятым людям, а также всем, кто, «не вникая в технические детали», хочет максимально обезопасить себя, свой бизнес и свой ближний круг.

Практическое пособие представляет собой простые и эффективные советы от квалифицированных профессионалов в области ИТ-безопасности с многолетним опытом работы в бизнесе.

Книга для вас, если вы хотите знать, как исключить такие точки уязвимости, как:

– телефон, айфон, планшет,

– партнеры, коллеги, персонал,

– а также узнать, как повлияет на ваш бизнес «Пакет Яровой», кибер-казаки и «русские хакеры».

Информация преподнесена в легкой доступной форме, отрецензирована и дополнена мнениями квалифицированных специалистов, такими как: руководитель сектора «Информационная безопасность» AT Consulting, глава представительства Avast в России и СНГ, консультант по безопасности Check Point Software Technologies, исполнительный директора Robokassa и IT-консультант ФБК.

Бонусы книги: ссылки на специализированные и художественные источники информации по ИТ-безопасности, советы по медиа-стратегии и поведению в публичном поле после того, как вас уже «взломали», а также ссылки на интимные фото звезд исключительно для привлечения внимания к содержанию книги.

Глава 13. Создание элементов управления ActiveX

Примечание
Несмотря на то, что мастер ActiveX Control не дает возможности автоматически создавать элементы управления ActiveX из компонентов, не являющихся потомками TWinControl, разработчик может создать такой элемент управления самостоятельно при помощи системы разработки Delphi ActiveX (DAX).

Вызовем мастера ActiveX Control. Появится окно мастера создания элемента ActiveX из оконного компонента Delphi (рис. 3.26).
В процессе использования данного мастера вам нужно выполнить следующее:
1. Выбрать компонент VCL из выпадающего списка VCL Class Name (Имя класса VCL).

Примечание
Как вы, вероятно, заметили, в выпадающем списке находятся далеко не все компоненты VCL. В данный список внесены только те компоненты, которые удовлетворяют следующим требованиям: находятся в текущем пакете, который используется в процессе разработки (следовательно, находятся в палитре компонентов); являются потомками компонента TWinControl; не исключаются из данного списка при помощи процедуры RegisterNonActiveX.

Многие из компонентов исключены из списка из-за того, что они либо не могут быть элементами управления ActiveX (например, компонент TDBGrid, т. к. для его работы нужен другой VCL-класс TDataSource), либо необходимо самостоятельно скорректировать их перед запуском мастера, чтобы они могли функционировать как элементы ActiveX (например, TTreeView, т. к. узлы компонента очень сложно представлять в ActiveX).
2. Выбрать новое имя ActiveX в поле для ввода New ActiveX Name (Новое имя ActiveX), если вас не устраивает имя, предлагаемое Delphi автоматически.
3. Выбрать имя модуля реализации создаваемого элемента ActiveX в поле для ввода Implementation Unit (Модуль реализации).
4. Выбрать имя проекта в поле для ввода Project Name (Имя проекта).
5. Выбрать потоковую модель в выпадающем списке Threading Model (Модель потока).
6. После этого вы можете установить три дополнительные опции:
Include About Box (Включить окно «О программе») — включить в проект диалоговое окно, которое будет содержать информацию о разработчике. Данное диалоговое окно представляет собой обычную форму Delphi;
Include Version Information (Включить информацию о версии) — включить в проект информацию о версии элемента управления ActiveX (данный пункт требуется для некоторых контейнеров, например, созданных в Visual Basic 4.0);
Make Control Licensed (Включить лицензионную информацию) — включить в проект лицензионную информацию (в случае коммерческого распространения элемента управления). В результате использовать данный элемент управления смогут только те разработчики, которые имеют лицензионный ключ, причем данное ограничение будет работать во всех средах разработки (Delphi, Visual Basic и др.). При установке данного флажка вместе с проектом элемента управления должен быть сгенерирован файл лицензии, имеющий расширение LIC. Чтобы дать возможность другим разработчикам использовать этот ActiveX, вам придется передавать лицензионным пользователям файл лицензии вместе с элементом управления ActiveX (имеющим расширение OCX).

Рис. 3.26. Мастер преобразования компонентов VCL Delphi в ActiveX
После внесения необходимых значений в поля, мастер автоматически создаст все файлы, которые нужны для поддержания данного элемента управления. В число таких файлов входят: сам проект, библиотека типов и файл реализации. Обратите внимание на то, что все элементы ActiveX являются либо библиотеками DLL, либо файлами OCX (что, в принципе, одно и то же).
Рассмотрим действия, которые выполняет мастер в процессе создания элемента управления ActiveX из компонента:
— мастер определяет, в каком модуле содержится элемент управления VCL. Данный модуль передается компилятору, который создает специальную символьную информацию для описания свойств, событий и методов элемента управления VCL;
— генерируется библиотека типов для проекта;
— мастер анализирует всю символьную информацию об элементе управления VCL и добавляет подходящие свойства и методы к интерфейсу и в библиотеку типов;

Илон Маск рекомендует:  Что такое код localsize

Примечание
Для определения, подходит ли данное свойство, метод или событие для включения в библиотеку типов, мастер проверяет, совместим ли с автоматизацией тип свойства, его параметры, а также возвращаемые значения событий и методов. С автоматизацией совместимы следующие типы: Byte, Smallint, Integer, Single, Double, Currency, TDateTime, WideString, WordBool, PSafeArray, TDecimal, OleVariant, lUnknown, IDispatch. Кроме перечисленных, разрешены параметры типов TStrings, TPicture и TFont. Для данных типов мастер создаст промежуточные объекты, которые позволят им быть инкапсулированными в IDispatch или Dispinterface.

— редактор библиотеки типов генерирует файл преобразованной библиотеки типов в соответствии с добавленными свойствами, событиями и методами;
— мастер создает файл реализации элемента управления ActiveX. Данный файл содержит элемент управления TActivexcontroi. Кроме того, мастер автоматически создает так называемые пересылки (forwarders) свойств и методов интерфейса. Пересылки направляют вызовы метода из элемента управления ActiveX в элемент управления VCL, а события — из элемента управления VCL в элемент ActiveX.
Листинг 3.7 содержит код файла проекта элемента управления ActiveX, созданного на основе компонента TRichEdit.

Листинг 3.7
library RichEditXControll;
uses
ComServ,
RichEditXControllJTLB in ‘RichEditXControllJTLB.pas’,
RichEditlmpll in ‘RichEditlmpll.pas’ ;
<$E ocx>
exports
DllGetClassObject, DllCanUnloadNow, DllRegisterServer, DllUnregisterServer;
<$R *.TLB>
<$R *.RES>
begin
end.

Описывать данный листинг не имеет особого смысла, т. к. его содержание достаточно очевидно.
Листинг 3.8 содержит код реализации элемента ActiveX.

Листинг 3.8
unit RichEditlmpll;
interface
uses
Windows, ActiveX, Classes, Controls, Graphics, Menus, Forms, StdCtrls, ComServ, StdVCL, AXCtrls, RichEditXControllJTLB, ComCtrls;
type
TRichEditX = class(TActiveXControl, IRichEditX)
private
< Private declarations >
FDelphiControl: TRichEdit;
FEvents: IRicnEditXEvents;
procedure ChangeEvent(Sender: TObject);
procedure KeyPressEvent(Sender: TObject; var Key: Char);
procedure ProtectChangeEvent(Sender: TObject; StartPos, EndPos:
Integer;
var AllowChange: Boolean);
procedure SaveClipboardEvent(Sender: TObject; NumObjects, NumChars: Integer; var SaveClipboard: Boolean);
procedure SelectionChangeEvent(Sender: TObject);
protected
< Protected declarations >
procedure DefinePropertyPages(DefinePropertyPage: TDefinePropertyPage); override;
procedure EventSinkChanged(const EventSink: lUnknown); override;
procedure InitializeControl; override;
function Get_Alignment: TxAlignment; safecall;
function Get_BorderStyle: TxBorderStyle; safecall;
function Get_CanUndo: WordBool; safecall;
function Get_Color: OLE_COLOR; safecall;
function Get_Ctl3D: WordBool; safecall;
function Get_Cursor: Smallint; safecall;
function Get_DoubleBuffered: WordBool; safecall;
function Get_DragCursor: Smallint; safecall;
function Get_DragMode: TxDragMode; safecall;
function Get_Enabled: WordBool; safecall;
function Get_Font: IFontDisp; safecall;
function Get_HideScrollBars: WordBool; safecall;
function Get_HideSelection: WordBool; safecall;
function Get_ImeMode: TxImeMode; safecall;
function Get_ImeName: WideString; safecall;
function Get_Lines: IStrings; safecall;
function Get_MaxLength: Integer; safecall;
function Get_Modified: WordBool; safecall;
function Get_ParentColor: WordBool; safecall;
function Get_ParentCtl3D: WordBool; safecall;
function Get_PlainText: WordBool; safecall;
function Get_ReadOnly: WordBool; safecall;
function Get_ScrollBars: TxScrollStyle; safecall;
function Get_SelLength: Integer; safecall;
function Get_SelStart: Integer; safecall;
function Get_SelText: WideString; safecall;
function Get_Text: WideString; safecall;
function Get_Visible: WordBool; safecall;
function Get_VisibleDockClientCount: Integer; safecall;
function Get_WantReturns: WordBool; safecall;
function Get_WantTabs: WordBool; safecall;
function Get_WordWrap: WordBool; safecall;
procedure _Set_Font(const Value: IFontDisp); safecall;
procedure Set_Alignment(Value: TxAlignment); safecall;
procedure Set_BorderStyle(Value: TxBorderStyle); safecall;
procedure Set_Color(Value: OLE_COLOR); safecall;
procedure Set_Ctl3D(Value: WordBool); safecall;
procedure Set_Cursor(Value: Smallint); safecall;
procedure Set_DoubleBuffered(Value: WordBool); safecall;
procedure Set_DragCursor(Value: Smallint); safecall;
procedure Set_DragMode(Value: TxDragMode); safecall;
procedure Set_Enabled(Value: WordBool); safecall;
procedure Set_Font(var Value: IFontDisp); safecall;
procedure Set_HideScrollBars(Value: WordBool); safecall;
procedure Set_HideSelection(Value: WordBool); safecall;
procedure Set_ImeMode(Value: TxImeMode); safecall;
procedure Set_ImeName(const Value: WideString); safecall;
procedure Set_Lines(const Value: IStrings); safecall;
procedure Set_MaxLength(Value: Integer); safecall;
procedure Set_Modified (Value: WordBool); safecall;
procedure Set_ParentColor(Value: WordBool); safecall;
procedure Set_ParentCtl3D(Value: WordBool); safecall;
procedure Set_PlainText(Value: WordBool); safecall;
procedure Set_ReadOnly(Value: WordBool); safecall;
procedure Set_ScrollBars(Value: TxScrollStyle); safecall;
procedure Set_SelLength(Value: Integer); safecall;
procedure Set_SelStart(Value: Integer); safecall;
procedure Set_SelText(const Value: WideString); safecall;
procedure Set_Text(const Value: WideString); safecall;
procedure Set_Visible(Value: WordBool); safecall;
procedure Set_WantReturns(Value: WordBool); safecall;
procedure Set_WantTabs(Value: WordBool); safecall;
procedure Set_WordWrap(Value: WordBool); safecall;
end;
implementation
uses ComObj;
< TRichEditX >
procedure TRichEditX.DefinePropertyPages(DefinePropertyPage: TDefinePropertyPage);
begin
Например, DefinePropertyPage(Class_RichEditXPage); >
end;
procedure TRichEditX.EventSinkChanged(const EventSink: lUnknown);
begin
FEvents := EventSink as IRichEditXEvents;
end;
procedure TRichEditX.InitialiZeControl;
begin
FDelphiControl :=* Control as TRichEdit;
FDelphiControl.OnChange := ChangeEvent;
FDelphiControl.OnKeyPress := KeyPressEvent;
FDelphiControl.OnProtectChange := ProtectChangeEvent;
FDelphiControl.OnSaveClipboard := SaveClipboardEvent;
FDelphiControl.OnSelectionChange := SelectionChangeEvent;
end;
function TRichEditX.Get_Alignment: TxAlignment;
begin
Result := Ord(FDelphiControl.Alignment);
end;
function TRichEditX.Get_BorderStyle: TxBorderStyle;
begin
Result := Ord(FDelphiControl.BorderStyle);
end;
function TRichEditX.Get_CanUndo: WordBool;
begin
Result := FDelphiControl.CanUndo;
end;
function TRichEditX.Get_Color: OLE_COLOR;
begin
Result := OLE_COLOR(FDelphiControl.Color);
end;
function TRichEditX.Get_Ctl3D: WordBool;
begin
Result := FDelphiControl.Ctl3D;
end;
function TRichEditX.Get_Cursor: Smallint;
begin
Result := Smallint(FDelphiControl.Cursor);
end;
function TRichEditX.Get_DoubleBuffered: WordBool;
begin
Result := FDelphiControl.DoubleBuffered;
end;
function TRichEditX.Get_DragCursor: Smallint;
begin
Result := Smallint(FDelphiControl.DragCursor);
end;
function TRichEditX.Get_DragMode: TxDragMode;
begin
Result := Ord(FDelphiControl.DragMode);
end;
function TRichEditX.Get_Enabled: WordBool;
begin
Result := FDelphiControl.Enabled;
end;
function TRichEditX.Get_Font: IFontDisp;
begin
GetOleFont(FDelphiControl.Font, Result) ;
end;
function TRichEditX.Get_HideScrollBars: WordBool;
begin
Result := FDelphiControl.HideScrollBars;
end;
function TRichEditX.Get_HideSelection: WordBool;
begin
Result := FDelphiControl.HideSelection;
end;
function TRichEditX.Get_ImeMode: TxImeMode;
begin
Result := Ord(FDelphiControl.ImeMode);
end;
function TRichEditX.Get_ImeName: WideString;
begin
Result := WideString(FDelphiControl.ImeName);
end;
function TRichEditX.Get_Lines: IStrings;
begin
GetOleStrings(FDelphiControl.Lines, Result);
end;
function TRichEditX.Get_MaxLength: Integer;
begin
Result := FDelphiControl.MaxLength;
end;
function TRichEditX.Get_Modified: WordBool;
begin
Result := FDelphiControl.Modified;
end;
function TRichEditX.Get_ParentColor: WordBool;
begin
Result := FDelphiControl.ParentColor;
end;
function TRichEditX.Get_ParentCtl3D: WordBool;
begin
Result := FDelphiControl.ParentCtlSD;
end;
function TRichEditX.Get_PlainText: WordBool;
begin
Result := FDelphiControl.Plaintext;
end;
function TRichEditX.Get_ReadOnly: WordBool;
begin
Result := FDelphiControl.Readonly;
end;
function TRichEditX.Get_ScrollBars: TxScrollStyle;
begin
Result := Ord(FDelphiControl.ScrollBars);
end;
function TRichEditX.Get_SelLength: Integer;
begin
Result := FDelphiControl.SelLength;
end;
function TRichEditX,Get_SelStart: Integer;
begin
Result := FDelphiControl.SelStart;
end;
function TRichEditX.Get_SelText: WideString;
begin
Result := WideString(FDelphiControl.SelText);
end;
function TRichEditX.Get_Text: WideString;
begin
Result := WideString(FDelphiControl.Text);
end;
function TRichEditX.Get_Visible: WordBool;
begin
Result := FDelphiControl.Visible;
end;
function TRichEditX.Get_VisibleDockClientCount: Integer;
begin
Result := FDelphiControl.VisibleDockClientCount;
end;
function TRichEditX.Get_WantReturns: WordBool;
begin
Result := FDelphiControl.WantReturns;
end;
function TRichEditX.Get_WantTabs: WordBool;
begin
Result := FDelphiControl.WantTabs;
end;
function TRichEditX.Get_WordWrap: WordBool;
begin
Result := FDelphiControl.Wordwrap;
end;
procedure TRichEditX._Set_Font(const Value: IFontDisp);
begin
SetOleFont(FDelphiControl.Font, Value);
end;
procedure TRichEditX.ChangeEvent(Sender: TObject);
begin
if FEvents <> nil then FEvents.OnChange;
end;
procedure TRichEditX.KeyPressEvent(Sender: TObject; var Key: Char);
var
TempKey: Smallint;
begin
TempKey := Smallint(Key);
if FEvents <> nil then FEvents.OnKeyPress(TempKey);
Key := Char(TempKey);
end;
procedure TRichEditX.ProtectChangeEvent(Sender: TObject; StartPos, EndPos: Integer; var AllowChange: Boolean);
var
TempAllowChange: WordBool;
begin
TempAllowChange := WordBool(AllowChange);
if FEvents <> nil then FEvents.OnProtectChange(StartPos, EndPos, TempAllowChange);
AllowChange := Boolean(TempAllowChange);
end;
procedure TRichEditX.SaveClipboardEvent(Sender: TObject; NumObjects, NumChars: Integer; var SaveClipboard: Boolean);
var
TempSaveClipboard: WordBool;
begin
TempSaveClipboard := WordBool(SaveClipboard);
if FEvents <> nil then FEvents.OnSaveClipboard(NumObjects, NumChars, TempSaveClipboard); SaveClipboard := Boolean(TempSaveClipboard);
end;
procedure TRichEditX.SelectionChangeEvent(Sender: TObject);
begin
if FEvents <> nil then FEvents.OnSelectionChange;
end;
procedure TRichEditX.Set_Alignment(Value: TxAlignment);
begin
FDelphiControl.Alignment := TAlignment(Value) ;
end;
procedure TRichEditX.Set_BorderStyle(Value: TxBorderStyle);
begin
FDelphiControl.BorderStyle := TBorderStyle(Value);
end;
procedure TRichEditX.Set_Color(Value: OLE_COLOR);
begin
FDelphiControl.Color := TColor(Value);
end;
procedure TRichEditX.Set_Ctl3D(Value: WordBool);
begin
FDelphiControl.Ctl3D := Value;
end;
procedure TRichEditX.Set_Cursor(Value: Smallint);
begin
FDelphiControl.Cursor := TCursor(Value);
end;
procedure TRichEditX.Set_DoubleBuffered(Value: WordBool);
begin
FDelphiControl.DoubleBuffered := Value;
end;
procedure TRichEditX.Set_DragCursor(Value: Smallint);
begin
FDelphiControl.DragCursor := TCursor(Value);
end;
procedure TRichEditX.Set_DragMode(Value: TxDragMode);
begin
FDelphiControl.DragMode := TDragMode(Value);
end;
procedure TRichEditX.Set_Enabled(Value: WordBool);
begin
FDelphiControl.Enabled := Value;
end;
procedure TRichEditX.Set_Font(var Value: IFontDisp);
begin
SetOleFont(FDelphiControl.Font, Value);
end;
procedure TRichEditX.SetJHideScrollBars(Value: WordBool);
begin
FDelphiControl.H >end;
procedure TRichEditX.Set_HideSelection(Value: WordBool);
begin
FDelphiControl.H >end;
procedure TRichEditX.Set_ImeMode(Value: TxImeMode);
begin
FDelphiControl.ImeMode := TImeMode(Value);
end;
procedure TRichEditX.Set_ImeName(const Value: WideString);
begin
FDelphiControl.ImeName := TImeName(Value);
end;
procedure TRichEditX.Set_Lines(const Value: IStrings);
begin
SetOleStrings(FDelphiControl.Lines, Value);
end;
procedure TRichEditX.Set_MaxLength(Value: Integer);
begin
FDelphiControl.MaxLength := Value;
end;
procedure TRichEditX.Set_Modified(Value: WordBool);
begin
FDelphiControl.Modified := Value;
end;
procedure TRichEditX.Set_ParentColor(Value: WordBool);
begin
FDelphiControl.ParentColor := Value;
end;
procedure TRichEditX.Set_ParentCtl3D(Value: WordBool);
begin
FDelphiControl.ParentCtl3D := Value;
end;
procedure TRichEditX.Set_PlainText(Value: WordBool);
begin
FDelphiControl.PlainText := Value;
end;
procedure TRichEditX.Set_ReadOnly(Value: WordBool);
begin
FDelphiControl.Readonly := Value;
end;
procedure TRichEditX.Set_ScrollBars(Value: TxScrollStyle);
begin
FDelphiControl.ScrollBars := TScrollStyle(Value);
end;
procedure TRichEditX.Set_SelLength(Value: Integer);
begin
FDelphiControl.SelLength := Value;
end;
procedure TRichEditX.Set_SelStart(Value: Integer);
begin
FDelphiControl.SelStart := Value;
end;
procedure TRichEditX.Set_SelText(const Value: WideString);
begin
FDelphiControl.SelText := String(Value);
end;
procedure TRichEditX.Set_Text(const Value: WideString>;
begin
FDelphiControl.Text := TCaption(Value);
end;
procedure TRichEditX.Set_Visible(Value: WordBool);
begin
FDelphiControl.Visible := Value;
end;
procedure TRichEditX.Set_WantReturns(Value: WordBool);
begin
FDelphiControl.WantReturns := Value;
end;
procedure TRichEditX.Set_WantTabs(Value: WordBool);
begin
FDelphiControl.WantTabs := Value;
end;
procedure TRichEditX.Set_WordWrap(Value: WordBool);
begin
FDelphiControl.Wordwrap := Value;
end;
initialization
TActiveXControlFactory.Create (ComServer, TRichEditX,TRichEdit,Class_RichEditX,
1,
»
0,
tmApartment);
end.

Описанный в данном файле класс TRichEditx является потомком TActivexcontrol. Этот класс применяется для установки соответствия между бывшим компонентом Delphi TRichEdit и контейнерами, в которых будет размещаться созданный элемент управления.
На рис. 3.27 показано окно редактора библиотеки типов для данного элемента управления ActiveX. Листинг 3.9 содержит код файла библиотеки типов.

Рис. 3.27. Элемент управления RichEdit в редакторе библиотеки типов

Листинг 3.9
unit RichEditXControllJTLB;
// Внимание
// Типы, объявленные в этом файле, были сгенерированы из данных
// библиотеки типов. Если библиотека типов явно или неявно (ссылается
// на эту библиотеку через другую) реимпортирована или с помощью команды
// ‘Refresh’ в окне Type Library Editor активизирована во время
// редактирования библиотеки типов, содержимое данного файла должно быть
// регенерировано, а все внесенные вручную изменения могут быть утеряны.
*****************************************************
// PASTLWTR : $Revision: 1.88 $
// Файл создан 15.02.2001 18:30:46 из библиотеки типов, описанной ниже.
*****************************************************
// Type Lib: C:\Program
Files\Borland\Delphi5\Projects\. \RichEditXControll.tlb (1)
// IIDXLCID: \0
// Helpfile:
// DepndLst:
// (1) v2.0 stdole, (C:\WINDOWS\SYSTEM\stdole2.tlb)
// (2) v4.0 StdVCL, (C:\WINDOWS\SYSTEM\STDVCL40.DLL)
*****************************************************
<$TYPEDADDRESS OFF>// Модуль должен быть откомпилирован без проверки
// типов указателей,
interface
uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL;
//***********************************************
// GUIDS объявлены в TypeLibrary. Используются следующие префиксы:
// Type Libraries : LIBID_xxxx
// CoClasses : CLASS_xxxx
// DISPInterfaces : DIID_xxxx
// Non-DISP interfaces: IID_xxxx
//***********************************************
const
RichEditXControllMajorVersion = 1; RichEditXControllMinorVersion =0; ‘
LIB ;
I ;
DI ;
;
//***********************************************
// Объявление перечислений, определенных в библиотеке типов
//***********************************************
// Константы для TxAlignment
type
TxAlignment = TOleEnum;
const
taLeftJustify = $00000000;
taRightJustify = $00000001;
taCenter = $00000002;
// Константы для TxBorderStyle
type
TxBorderStyle = TOleEnum;
const
bsNone = $00000000;
bsSingle = $00000001;
// Константы для TxDragMode
type
TxDragMode = TOleEnum;
const
dmManual = $00000000;
dmAutomatic = $00000001;
// Константы для TxImeMode
type
TxImeMode = TOleEnum;
const
imDisable = $00000000;
imClose = $00000001;
imOpen = $00000002;
imDontCare = $00000003;
imSAlpha = $00000004;
imAlpha = $00000005;
imHira = $00000006;
imSKata = $00000007;
imKata = $00000008;
imChinese = $00000009;
imSHanguel = $OOOOOOOA;
imHanguel = $OOOOOOOB;
// Константы для TxScrollStyle
type
TxScrollStyle = TOleEnum;
const
ssNone = $00000000;
ssHorizontal = $00000001;
ssVertical = $00000002;
ssBoth = $00000003;
// Константы для TxMouseButton
type
TxMouseButton = TOleEnum;
const
mbLeft = $00000000;
mbRight = $00000001;
mbM > type
// Предварительное объявление типов, определенных в библиотеке типов
//***********************************************
IRichEditX = interface;
IRichEditXDisp = dispinterface;
IRichEditXEvents = dispinterface;
//***********************************************
// Объявление CoClasses, определенных в библиотеке типов
//***********************************************
RichEditX = IRichEditX;
//***********************************************
// Объявление структур, союзов и альянсов.
//***********************************************
PPUserTypel = A IFontDisp; <*>
//***********************************************
// Interface: IRichEditX
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: <86f5c46c-cda6-4279-8bf4-f69f1a051ed7>
//***********************************************
IRichEditX = interface(IDispatch)
[‘<86f5c46c-cda6-4279-8bf4-f69f1a051ed7>‘]
function Get_Alignment: TxAlignment; safecall;
procedure Set_Alignment(Value: TxAlignment); safecall;
function Get_BorderStyle: TxBorderStyle; safecall;
procedure Set_BorderStyle(Value: TxBorderStyle); safecall;
function Get_Color: OLE_COLOR; safecall;
procedure Set_Color(Value: OLE_COLOR); safecall;
function Get_Ctl3D: WordBool; safecall;
procedure Set_Ctl3D(Value: WordBool); safecall;
function Get_DragCursor: Smallint; safecall;
procedure Set__DragCursor'(Value: Smallint); safecall;
function Get_DragMode: TxDragMode; safecall;
procedure Set_DragMode(Value: TxDragMode); safecall;
function Get_Enabled: WordBool; safecall;
procedure Set_Enabled(Value: WordBool); safecall;
function Get_Font: .IFontDisp; safecall;
procedure _Set_Font(const Value: IFontDisp); safecall;
procedure Set_Font(var Value: IFontDisp); safecall;
function Get_HideSelection: WordBool; safecall;
procedure Set_HideSelection(Value: WordBool); safecall;
function Get_HideScrollBars: WordBool; safecall;
procedure Set_HideScrollBars(Value: WordBool); safecall;
function Get_ImeMode: TxImeMode; safecall;
procedure Set_ImeMode(Value: TxImeMode); safecall;
function Get_ImeName: WideString; safecall;
procedure Set_ImeName(const Value: WideString>; safecall;
function Get_Lines: IStririgs; safecall;
procedure Set_Lines(const Value: IStrings); safecall;
function Get_MaxLength: Integer; safecall;
procedure Set_MaxLength(Value: Integer); safecall;
function Get_ParentColor: WordBool; safecall;
procedure Set_ParentColor(Value: WordBool); safecall;
function Get_ParentCtl3D: WordBool; safecall;
procedure Set_ParentCtl3D(Value: WordBool); safecall;
function Get_PlainText: WordBool; safecall;
procedure Set_PlainText(Value: WordBool); safecall;
function Get_ReadOnly: WordBool; safecall;
procedure Set_ReadOnly(Value: WordBool); safecall;
function Get_ScrollBars: TxScrollStyle; safecall;
procedure Set_ScrollBars(Value: TxScrollStyle); safecall;
function Get_Visible: WordBool; safecall;
procedure Set_Visible(Value: WordBool); safecall;
function Get_WantTabs: WordBool; safecall;
procedure Set_WantTabs(Value: WordBool); safecall;
function Get_WantReturns: WordBool; safecall;
procedure Set_WantReturns(Value: WordBool); safecall;
function Get_WordWrap: WordBool; safecall;
procedure Set_WordWrap(Value: WordBool); safecall;
function Get_CanUndo: WordBool; safecall;
function Get_Modified: WordBool; safecall;
procedure Set_Modifled(Value: WordBool); safecall;
function Get_SelLength: Integer; safecall;
procedure Set_SelLength(Value: Integer); safecall;
function Get_SelStart: Integer; safecall;
procedure Set_SelStart(Value: Integer); safecall;
function Get_SelText: WideString; safecall;
procedure Set_SelText(const Value: WideString); safecall;
function GetJText: WideString; safecall;
procedure Set_Text(const Value:.WideString); safecall;
function Get_DoubleBuffered: WordBool; safecall;
procedure Set_DoubleBuffered(Value: WordBool); safecall;
function Get_VisibleDockClientCount: Integer; safecall;
function Get_Cursor: Smallint; safecall;
procedure Set_Cursor(Value: Smallint); safecall;
property Alignment: TxAlignment read Get_Alignment write Set_Alignment ;
property BorderStyle: TxBorderStyle read Get_BorderStyle write Set_BorderStyle;
property Color: OLE_COLOR read Get_Color write Set_Color,;
property CtlSD: WordBool read Get_Ctl3D write Set_Ctl3D;
property DragCursor: Smallint read Get_DragCursor write Set_DragCursor;
property DragMode: TxDragMode read Get_DragMode write Set_DragMode;
property Enabled: WordBool read Get_Enabled write Set_Enabled;
property Font: IFontDisp read Get_Font write _Set_Font;
property HideSelection: WordBool read Get_HideSelection write Set_HideSelection;
property HideScrollBars: WordBool read Get_HideScrollBars write Set_HideScrollBars;
property ImeMode: TxImeMode read Get_ImeMode write Set_ImeMode;
property ImeName: WideString read Get_ImeName write Set_ImeName;
property Lines: IStrings read Get_Lines write Set_Lines;
property MaxLength: Integer read Get_MaxLength write Set_MaxLength;
property ParentColor: WordBool read Get_ParentColor write Set_ParentColor;
property ParentCtlSD: WordBool read Get_ParentCtl3D write Set_ParentCtl3D;
property PlainText: WordBool read Get_PlainText write Set_PlainText;
property Readonly: WordBool read Get_ReadOnly write Set_ReadOnly;
property ScrollBars: TxScrollStyle read Get_ScrollBars write Set_ScrollBars;
property Visible: WordBool read Get_Visible write Set_Visible;
property WantTabs: WordBool read Get_WantTabs write Set_WantTabs;
property WantReturns: WordBool read Get_WantReturns write SetJWantReturns;
property Wordwrap: WordBool read Get_WordWrap write Set_WordWrap;
property CanUndo: WordBool read Get_CanUndo;
property Modified: WordBool read Get__Modified write Set_Modified;
property SelLength: Integer read Get_SelLength write Set_SelLength;
property SelStart: Integer read Get_SelStart write Set_SelStart;
property SelText: WideString read Get_SelText write Set_SelText;
property Text: WideString read Get_Text write Set_Text;
property DoubleBuffered: WordBool read Get_DoubleBuffered write Set_DoubleBuffered;
property VisibleDockClientCount: Integer read Get_VisibleDockClientCoxint;
property Cursor: Smallint read Get_Cursor write Set_Cursor;
end;
//***********************************************
// Displntf: IRichEditXDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: <86f5c46c-cda6-4279-8bf4-f69f1a051ed7>
//***********************************************
IRichEditXDisp = dispinterface
[‘<86f5c46c-cda6-4279-8bf4-f69f1a051ed7>‘]
property Alignment: TxAlignment dispid 1;
property BorderStyle: TxBorderStyle dispid 2;
property Color: OLE_COLOR dispid -501;
property Ctl3D: WordBool dispid 3;
property DragCursor: Smallint dispid 4;
property DragMode: TxDragMode dispid 5;
property Enabled: WordBool dispid -514;
property Font: IFontDisp dispid -512;
property HideSelection: WordBool dispid 6;
property HideScrollBars: WordBool dispid 7;
property ImeMode: TxImeMode dispid 8;
property ImeName: WideString dispid 9;
property Lines: IStrings dispid 10;
property MaxLength: Integer dispid 11;
property ParentColor: WordBool dispid 12;
property ParentCtl3D: WordBool dispid 13;
property PlainText: WordBool dispid 14;
property Readonly: WordBool dispid 15;
property ScrollBars: TxScrollStyle dispid 16;
property Visible: WordBool dispid 17;
property WantTabs: WordBool dispid 18;
property WantReturns: WordBool dispid 19;
property Wordwrap: WordBool dispid 20;
property CanUndo: WordBool readonly dispid 34;
property Modified: WordBool dispid 35;
property SelLength: Integer dispid 36;
property SelStart: Integer dispid 37;
property SelText: WideString dispid 38;
property Text: WideString dispid -517;
property DoubleBuffered: WordBool dispid 39;
property VisibleDockClientCount: Integer readonly dispid 40;
property Cursor: Smallint dispid 49;
end;
//***********************************************
// Displntf: IRichEditXEvents
// Flags: (0)
// QUID: <21ab5f94-7d87-4fco-ab5a-9bce1d05af8b>
//***********************************************
IRichEditXEvents = dispinterface
[‘<21ab5f94-7d87-4fco-ab5a-9bce1d05af8b>‘]
procedure OnChange; dispid 1;
procedure OnKeyPress(var Key: Smallint); dispid 8;
procedure OnProtectChange(StartPos: Integer; EndPos: Integer; var AllowChange: WordBool); dispid 16;
procedure OnSaveClipboardfNumObjects: Integer; NumChars: Integer; var SaveClipboard: WordBool); dispid 18;
procedure OnSelectionChange; dispid 19;
end;

// Объявление класса OLE Control Proxy
// Control Name TRichEditX
// Help String RichEditX Control
// Default Interface IRichEditX
// Def. Intf. DISP? No
// Event Interface IRichEditXEvents
// TypeFlags (34) CanCreate Control
//***********************************************
TRichEditXOnKeyPress = procedure(Sender: TObject; var Key: Smallint) of object;
TRichEditXOnProtectChange = procedure(Sender: TObject; StartPos: Integer; EndPos: Integer;
var AllowChange: WordBool) of object;
TRichEditXOnSaveClipboard = procedure(Sender: TObject; NumObjects: Integer; NumChars-: Integer;
var SaveClipboard: WordBool) of object;
TRichEditX = class(Telecontrol)
private
FOnChange: TNotifyEvent;
FOnKeyPress: TRichEditXOnKeyPress;
FOnProtectChange: TRichEditXOnProtectChange;
FOnSaveClipboard: TRichEditXOnSaveClipboard;
FOnSelectionChange: TNotifyEvent;
FIntf: IRichEditX;
function GetControlInterface: IRichEditX;
protected
procedure CreateControl;
procedure InitControlData; override/function Get_Lines: IStrings;
procedure Set_Lines(const Value: IStrings);
public
property Controllnterface: IRichEditX read GetControlInterface;
property Defaultlnterface: IRichEditX read GetControlInterface;
property CanUndo: WordBool index 34 read GetWordBoolProp;
property Modified: WordBool index 35 read GetWordBoolProp write SetWordBoolProp;
property SelLength: Integer index 36 read GetlntegerProp write SetlntegerProp;
property SelStart: Integer index 37 read GetlntegerProp write SetlntegerProp;
property SelText: WideString index 38 read GetWideStringProp write SetWideStringProp;
property Text: WideString index -517 read GetWideStringProp write SetWideStringProp;
property DoubleBuffered: WordBool index 39 read GetWordBoolProp write SetWordBoolProp;
property VisibleDockClientCount: Integer index 40 read GetlntegerProp;
published
property Alignment: TOleEnum index 1 read GetTOleEnumProp write SetTOleEnumProp stored False;
property BorderStyle: TOleEnum index 2 read GetTOleEnumProp write SetTOleEnumProp stored False;
property Color: TColor index -501 read GetTColorProp write SetTColorProp stored False;
property Ctl3D: WordBool index 3 read GetWordBoolProp write SetWordBoolProp stored False;
property DragCursor: Smallint index 4 read GetSmallintProp write SetSmallintProp stored False property DragMode: TOleEnum index 5 read GetTOleEnumProp write SetTOleEnumProp stored False;
property Enabled: WordBool index -514 read GetWordBoolProp write SetWordBoolProp stored False;
property Font: TFont index -512 read GetTFontProp write SetTFontProp stored False;
property HideSelection; WordBool index 6 read GetWordBoolProp write SetWordBoolProp stored False;
property HideScrollBars: WordBool index 7 read GetWordBoolProp write SetWordBoolProp stored False;
property ImeMode: TOleEnum index 8 read GetTOleEnumProp write SetTOleEnumProp stored False;
property ImeName: WideString index 9 read GetWideStringProp write SetWideStringProp stored False;
property Lines: IStrings read Get_Lines write Set_Lines stored False property MaxLength: Integer index 11 read GetlntegerProp write SetlntegerProp stored False
property ParentColor: WordBool index 12 read GetWordBoolProp write SetWordBoolProp stored False;
property ParentCtlSD: WordBool index 13 read GetWordBoolProp write SetWordBoolProp stored False;
property PlainText: WordBool index 14 read GetWordBoolProp write SetWordBoolProp stored False;
property Readonly: WordBool index 15 read GetWordBoolProp write SetWordBoolProp stored False;
property ScrollBars: TOleEnum index 16 read GetTOleEnumProp write SetTOleEnumProp stored False;
property Visible: WordBool index 17 read GetWordBoolProp write SetWordBoolProp stored False;
property WantTabs: WordBool index 18 read GetWordBoolProp write SetWordBoolProp stored False;
property WantReturns: WordBool index 19 read GetWordBoolProp write SetWordBoolProp stored False;
property Wordwrap: WordBool index 20 read GetWordBoolProp write SetWordBoolProp stored False;
property Cursor: Smallint index 49 read GetSmallintProp write SetSmallintProp stored False;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnKeyPress: TRichEditXOnKeyPress read FOnKeyPress write FOnKeyPress;
property OnProtectChange: TRichEditXOnProtectChange read FOnProtectChange write FOnProtectChange;
property OnSaveClipboard: TRichEditXOnSaveClipboard read FOnSaveClipboard write FOnSaveClipboard;
property OnSelectionChange: TNotifyEvent read FOnSelectionChange write FOnSelectionChange;
end;
procedure Register; implementation uses ComObj;
procedure TRichEditX.InitControlData; const
CEventDisp > $00000001, $00000008, $00000010, $00000012, $00000013); CTFontlDs: array [0..0] of DWORD = (
$FFFFFEOO); CControlData: TControlData2 = (
ClassID: ‘<7c731eeo-d98d-4040-8fe1-eocb9e54c58b>‘;
EventHD: ‘<21ab5f94-7d87-4fco-ab5a-9bce1d05af8b>‘;
EventCount: 5;
EventDispIDs: @CEventDispIDs;
LicenseKey: nil (*HR:$80040154*);
Flags: $00000020;
Version: 401;
FontCount: 1;
FontlDs: @CTFontIDs);
begin
ControlData := @CControlData;
TControlData2(CControlData).FirstEventOfs := Cardinal(SSFOnChange) — Cardinal(Self);
end;
procedure TRichEditX.CreateControl;
procedure DoCreate;
begin
FIntf := lUnknown(OleObject) as IRichEditX;
end;
begin
if FIntf = nil then DoCreate;
end;
function TRichEditX.GetControlInterface: IRichEditX;
begin
CreateControl;
Result := FIntf;
end;
function TRichEditX.Get_Lines: IStrings;
begin
Result := DefaultInterface.Get_Lines;
end;
procedure TRichEditX.Set_Lines(const Value: IStrings);
begin
Defaultlnterface.Set_Lines(Value);
end;
procedure Register;
begin
RegisterComponents(‘ActiveX’,[TRichEditX]);
end;
end.

Как вы можете видеть, приведенные выше листинги имеют достаточно большой размер. Но тот факт, что Delphi берет на себя такую большую работу, позволяет даже непрофессионалу в разработке элементов управления ActiveX создавать свои ActiveX при помощи мастера. Мастер в данном случае генерирует полностью функциональный элемент управления ActiveX с интерфейсами, библиотекой типов и событиями, при этом разработчику не нужно вводить собственный код!
Для установки данного элемента управления в палитру компонентов Delphi нужно сделать следующее:
1. Откомпилировать проект с помощью пункта главного меню Project/Compile (Проект/Компилировать ), при этом будет создана библиотека OCX.
2. С помощью пункта главного меню Component/Import ActiveX Control (Компонент/Импорт элемента управления ActiveX) открыть окно импорта нового элемента ActiveX.
3. В диалоговом окне импорта ActiveX нажать кнопку Add (Добавить), перейти в каталог, содержащий созданный файл OCX, и выбрать его двойным щелчком, элемент управления появится в списке диалогового окна импорта ActiveX.
4. Выбрать данный элемент управления в списке и нажать кнопку Install (Установить).
5. Выбрать файл пакета и нажать кнопку ОК.
После выполнения данной последовательности шагов в палитре компонентов Delphi появится ваш элемент управления ActiveX.
Следует заметить, что создание элементов управления ActiveX из стандартных компонентов Delphi применяется очень редко. Вы можете использовать данную процедуру преобразования компонента в ActiveX к самостоятельно созданному компоненту, что значительно расширит его функциональность и позволит использовать ваш компонент разработчиками в других средах программирования.
Создание ActiveX из форм
Данный способ создания элементов управления позволяет на базе собственной формы приложения создать элемент ActiveX. Этот способ носит название ActiveForms.
Попробуем создать элемент управления ActiveX из формы. Выполним следующие шаги:
1. Вызовем мастер ActiveForm. Для этого выберем пункт главного меню File/New (Файл/Новый), и перейдя на вкладку ActiveX выберем пиктограмму ActiveForm. Появится окно мастера (рис. 3.28).
Как можно видеть, данный мастер очень похож на мастера преобразования компонента VCL Delphi в элемент управления ActiveX. Но отличие сразу бросается в глаза. В поле имени класса VCL Class Name (Имя класса VCL) мастер автоматически устанавливает значение TActiveForm.

Рис. 3.28. Диалоговое окно мастера ActiveForm
2. В поле New ActiveX Name (Новое имя ActiveX) нам нужно ввести имя создаваемого элемента управления ActiveX. Введем имя MyForm, при этом автоматически произойдут изменения в других полях (они описаны выше для мастера ActiveX Control).
3. После нажатия кнопки ОК мастер создает все необходимые заготовки для элемента управления ActiveX (практически так же, как и в предыдущем случае). Поверхность формы MyForm становится рабочей поверхностью. Вы можете размещать на ней произвольные компоненты, описывать методы и события компонентов и формы, устанавливать их свойства.
Разместим на форме MyForm два компонента CоmВох, как показано на рис. 3.29.

Рис. 3.29. Форма MyForm
Внесем в свойство items для первого компонента СотЬоВох значения, соответствующие названиям месяцев с января по декабрь. В свойство items второго компонента СотЬоВох внесем значения, которые соответствуют названиям дней недели с понедельника по воскресенье. Итак, при нажатии на первый список в нем должны отображаться названия месяцев, а при нажатии кнопки второго списка — названия дней недели.
В принципе, мы уже создали элемент управления ActiveX. Но данный элемент управления будет бесполезным, т. к. нам необходимо, чтобы выбранные в списках значения передавались пользователю. Для этого нужно создать интерфейс с пользователем элемента управления.
Для решения данной задачи нам необходимо добавить в библиотеку типов элемента управления в интерфейс IMyForm два новых свойства. Назовем их, например, Month и Day. Откроем редактор библиотеки типов при помощи пункта главного меню View/Type Library (Просмотр/Библиотека типов). Работать с ней нам уже приходилось, поэтому не будет сложным добавить к интерфейсу IMyForm свойства Month и Day (рис. 3.30).
Теперь нужно обновить модуль реализации MyFormImpl1. Для чего необходимо нажать кнопку Refresh Implementation (Обновить реализацию) в верхней панели инструментов редактора библиотеки типов. При этом в обоих файлах проекта появляются описания новых свойств, а в файле реализации — заготовки кода (листинг 3.10).

Листинг З.10
function TMyForm.Get_Day: Integer;
begin
end;
function TMyForm.Get_Month: Integer;
begin
end;
procedure TMyForm.Set_Day(Value: Integer);
begin
end;
procedure TMyForm.Set_Month(Value: Integer);
begin
end;

Рис. 3.30. Редактор библиотеки типов с добавленными в интерфейс IMyForm свойствами Month и Day
Как мы видим, были добавлены две заготовки для функций Get и две заготовки для процедур set. Функции Get предназначены для передачи значения свойства в программу, вызвавшую данную функцию. Процедуры Set служат для передачи и установки необходимых параметров.
Заполним эти заготовки следующим образом (листинг 3.11):

Листинг 3.11
function TMyForm.Get_Day: Integer;
begin
Result:=ComboBox2.Itemlndex;
end;
function TMyForm.Get_Month: Integer;
begin
Result: =ComboBoxl. Itemlndex;
end;
procedure TMyForm.Set_Day(Value: Integer);
begin
ComboBox2.Itemlndex:=value;
end;
procedure TMyForm.Set_Month(Value: Integer);
begin
ComboBoxl.Itemlndex:=value;
end;

Передаваемые и принимаемые значения свойств Day и Month в нашем случае имеют тип integer, хотя вы могли присвоить данным свойствам другой тип в редакторе библиотеки типов в процессе создания этих свойств.
Вот и все. Мы создали элемент управления ActiveX на основе формы. Теперь осталось лишь откомпилировать проект и установить элемент управления в палитру компонентов (как это сделать, описано в конце предыдущего раздела).
Попробуем использовать данный элемент управления ActiveX в своем приложении. Создадим новый проект. Разместим на нем элемент управления ActiveX MyForm. Кроме того, расположим на форме четыре кнопки и два компонента Edit (рис. 3.31).

Рис. 3.31. Внешний вид приложения, использующего элемент управления ActiveX MyForm
На листинге 3.12 приведен код для приложения, внешний вид которого представлен на рис. 3.31.

Листинг 3.12
unit Unitl;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, OleCtrls, MyFormProjlJTLB;
type
TForml = class(TForm)
MyForml: TMyForm;
GetMonth: TButton;
Editl: TEdit;
GetDay: TButton;
Edit2: TEdit;
SetMonth: TButton;
SetDay: TButton;
Label1: TLabel;
Label2: TLabel;
procedure GetMonthClick(Sender: TObject);
procedure GetDayClick(Sender: TObject);
procedure SetMonthClick(Sender: TObject)’;
procedure SetDayClick(Sender: TObject);
private
< Private declarations >
public
< Public declarations >
end;
var
Forml: TForml;
implementation <$R *.DFM>
procedure TForml.GetMonthClick(Sender: TObject);
begin
Editl.Text:=IntToStr(MyForml.Month+1);
end;
procedure TForml.GetDayClick(Sender: TObject);
begin
Edit2.Text:=IntToStr(MyForml.Day+1);
end;
procedure TForml.SetMonthClick(Sender: TObject);
begin
MyForml.Month:=StrToInt(Edit1.Text)-1;
end;
procedure TForml.SetDayClick(Sender: TObject);
begin
MyForml.Day:=StrToInt(Edit2.Text)-1;
end;
end.

При нажатии на любую из двух кнопок, размещенных на форме слева (GetMonth и GetDay), вы получите порядковый номер значения из нужного списка компонента MyForm (т. к. нумерация элементов списка CоmВох на чинается с нуля, то мы прибавляем к получаемому значению единицу) в соответствующее поле редактирования Edit. Нажатие любой из кнопок справа на форме (setMonth и setDay) приведет к передаче значения из необходимого поля редактирования Edit в элемент управления ActiveX. При этом произойдет установка соответствующего свойства элемента MyForm.
Работу данного приложения иллюстрирует рис. 3.32.

Рис. 3.32. Приложение, использующее ActiveX в процессе исполнения

Borland delphi 4 0 для начинающих элементы управления activex

Почему именно Delphi? В Delphi сделать первый шаг очень просто, она интуитивно понятна. Конечно, небольшому числу разработчиков по долгу службы нужны глубокие специфические знания, которые приходят со временем. А начинающим Delphi позволяет начать создавать программы сразу, не углубляясь в изучение внутренностей операционной системы, и даже собственной среды разработки. Поэтому программист может сразу сосредоточиться на логике работы будущей программы.

Delphi — прекрасная система визуального объектно-ориентированного проектирования, одинаково радующая и новичков в программировании, и профессионалов. Начинающим Delphi позволяет сразу, с небольшими затратами времени и сил создавать прикладные программы, которые внешне неотличимы от программ, созданных профессионалами. А для опытного программиста Delphi открывает неограниченные возможности для создания сколь угодно сложных программ любого типа, в том числе, распределённых приложений, работающих с любыми базами данных.

Более подробно о том, что такое Delphi и почему её стоит изучать, можно прочесть на специальной страничке и этом переводе статьи «Why Delphi? (Delphi For Beginners)» :

Эта статья о Delphi имеет цель объяснить, что такое Delphi и что он может сделать для вас.

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

Borland Delphi представляет собой средство разработки приложений для Microsoft Windows. Delphi является мощным и простым в использовании инструментом для создания автономных программ, обладающих графическим интерфейсом (GUI) , или 32-битных консольных приложений (программ, которые не имеют графического интерфейса).

В сочетании с Borland Kylix, программисты Delphi могут создавать из одного исходного текста приложения и для Windows и для Linux, и это открывает новые возможности и увеличивает потенциальную отдачу от усилий, вложенных в изучение Delphi. В Delphi используется кросс-платформенная библиотека компонентов CLX и визуальные дизайнеры для создания высокопроизводительных приложений для Windows, которые повторной компиляцей можно легко превратить в приложения для Linux.

Delphi является первым языком программирования, обладающим простой в использовании средой для быстрой разработки приложений, разрушающей барьеры между языками высокого уровня, и языками, на низком уровне разговаривающими с системой на языке битов и байтов.

При создании графического интерфейса приложений Delphi, у вас все возможности языка программирования Object Pascal, «завернутого» в среду RAD . Такие компоненты окна графического пользовательского интерфейса, как формы, кнопки и списки объектов, включены в состав Delphi. Это означает, что вам не нужно писать никакого кода при добавлении их в ваше приложение. Вы просто «кладёте» их на вашу Форму, как в графическом редакторе. Вы можете также добавить на Форму элементы управления ActiveX, для создания в считанные минуты специализированных программ таких, например, как веб-браузеры. Delphi позволяет разработчикам дизайна внедрять в интерфейс новые элементы и кодировать их события одним щелчком мыши.

Delphi поставляется в различных конфигурациях, настроенных на потребности различных предприятий. В Delphi вы можете писать программы для Windows быстрее и легче, чем это было возможно раньше.

Паскаль

Лучшим способом представить что такое Delphi является Object Pascal на основе визуальной среды разработки. Delphi основан на Object Pascal, языке, аналогичном объектно-ориентированному C++, а в некоторых случаях даже лучше. Для разработчиков не имеющих опыта работы в Паскале, Delphi имеет шаблоны своих структур на Паскале, что ускоряет процесс изучения языка.

Компилятор Delphi упаковывает приложения в компактные исполняемые файлы, причем нет необходимости в громоздких библиотеках DLL — большое удобство, я должен сказать.

Библиотека Visual Component Library (автономные бинарные части программного обеспечения, которые выполняют некоторые конкретные предопределенные функции), или VCL, Delphi является объектно-ориентированной базой. В этой богатой библиотеке вы найдете классы для таких визуальных объектов Windows как окна, кнопки и т.д., а также классы для пользовательских элементов управления таких как таймер и мультимедийный плеер, наряду с невизуальными объектами, такими как список строк, таблицы базы данных, потоки и т.д.

Базы данных

Delphi может получать доступ ко многим типам баз данных. Используя BDE (Borland Database Engine — механизм доступа к базам данных), формы и отчеты, которые вы создаете, получают доступ к локальным базам данных, таким как Paradox и DBase, сетевых баз данных SQL Server, InterBase, также как и SysBase, и любые источники данных, доступные даже через ODBC (открытая связь с базами данных).

Итак, Delphi — прекрасная среда разработки Windows- и Linux-программ любого типа. Поэтому единственное, что вас должно уже сейчас интересовать —

Итак, запустим Delphi. Перед нами четыре окошка. Вверху во вcю ширину экрана окно управления проектом и средой разработки — главное окно Delphi. При его сворачивании сворачиваются и все остальные. Слева — инспектор объектов. В нём задаются свойства составляющих нашу программу компонентов. И наконец, в центре одно над другим два окна, окно формы будущей программы и окно программной начинки.

В пустой форме смысла нет. Наполнить её содержанием помогут компоненты Delphi. Они располагаются на главном окне, на нескольких вкладках. Все основные компоненты находятся на первых четырёх вкладках: Standard, Additional, Win32 и System. Их названия всплывают в виде подсказок при наведении мышки на пиктограммы.

Илон Маск рекомендует:  Что такое код openssl_x509_check_private_key

Структура программы для Windows представляет собой набор подпрограмм, каждая из которых ответственна за обработку конкретного события и вызывается только при его получении. Удобство Delphi состоит в том, что мы избавлены от необходимости получать сообщения от Windows сами, Delphi это делает за нас. Каждый компонент имеет впечатляющий набор событий, на которые он может реагировать. Программист сам определяет, какие события в программе требуется обрабатывать.

Данные в компьютере можно рассматривать как ячейки памяти, имеющие свои имена (идентификаторы). Все данные в программе на языке Delphi должны быть описаны до их первого использования. И компилятор следит, чтобы в программе они использовались в соответствии с этим описанием, что позволяет избежать ошибок.

При создании любой серьёзной программы не обойтись без дополнительных, более сложных, чем числа и строки, типов данных. В Delphi программист может для своих целей конструировать собственные типы данных. Чтобы ввести в программу (описать) новый тип данных, применяется оператор с ключевым словом type.

Для создания приложений, реализующих сложную алгоритмическую логику, нужны средства управления ходом работы программы: Математически доказано, что любой алгоритм можно закодировать с помощью оператора присваивания, условного оператора и оператора цикла.
В качестве примера рассматривается программа сортировки одномерного массива методом пузырька. Приводится скриншот программы и подробные комментарии. Также можно скачать проект целиком в виде архива.

Начало. Работа с файлами важная вещь в любом языке программирования. Для начала нужно упомянуть компоненты, которые умеют работать с файлами, считывать и сохранять своё содержимое, строки типа String, в файл текстового формата. Это компоненты ListBox, ComboBox и Memo, расположенные на первой же вкладке палитры компонентов.
Продолжение. В Delphi реализовано несколько способов прямой работы с файлами. Познакомимся с классическим способом, связанным с использованием файловых переменных. Прежде всего файл должен быть открыт.
Окончание. То, что мы узнали в предыдущей части урока, позволяет работать с файлами по адресу, жёстко записанному в тексте программы. Мы же хотим просматривать любые файлы по нашему выбору. В Delphi есть компоненты, позволяющие в работающей программе осуществлять выбор файлов.
Поиск файлов в Delphi производится в три этапа. На первом этапе функция FindFirst находит первый файл, удовлетворяющий критериям отбора. На втором этапе функция FindNext в цикле поочерёдно находит остальные файлы. На третьем этапе функция FindClose освобождает память, выделенную для осуществления поиска.
Задачка. Теперь, пользуясь всем вышеизложенным материалом, можно ответить, например, на вопрос: «как средствами Delphi определить размер файла». Есть несколько альтернативных способов, как подсчитать размер файла с помощью Delphi.
Список подпрограмм используемых при работе с файлами в Delphi. Содержит функции и процедуры создания, поиска, преобразования и удаления папок и файлов.

Редкая программа обходится одной формой. Delphi позволяет с лёгкостью создавать дополнительные формы, предоставляющие возможность, например, вести диалог с пользователем, принимать и выводить любую необходимую информацию.

Всё богатство стандартных процедур и функций Delphi не исчерпывает встающих перед программистом задач. Для выполнения повторяющихся операций с меняющимися данными Delphi программист может создавать собственные подпрограммы — процедуры и функции Delphi.
Пример. Вычисление факториала. Выполняя повторяющиеся участки кода, подпрограммы эффективно заменяют циклы. Классический пример — вычисление факториала числа, демонстрирующий также использование рекурсии. Этот проект также можно скачать.

Исключительные ситуации в Delphi встречаются постоянно. Исключительная ситуация это такая ситуация, в результате которой генерируется ошибка, и выполнение программы прерывается. Например, деление на ноль — классический пример исключительной ситуации. Для контроля исключительных ситуаций ввода-вывода также могут применяться директивы компилятора <$I>.

Применение компонентов Delphi позволяет избежать рутинного ручного кодирования. Компоненты Delphi охватывают практически все аспекты применения современных информационных технологий. Конечно, для работы в Delphi прежде всего требуется изучить базовые компоненты Delphi, которые требуются при подготовке практически любого приложения.
Страница Standart
Изучение Delphi естественным образом начинается со страницы палитры компонентов Standart. На этой странице расположены стандартные для Windows интерфейсные элементы, такие как главное и всплывающее меню, кнопка, однострочный и многострочный редакторы, переключатели, метки, списки, и некоторые другие компоненты, которые применяются наиболее часто. Рассматривается пример на переопределение символов , вводимых в компонент Edit, что может использоваться в формах для ввода пароля.
Страница Additional
На страницу палитры компонентов Additional помещены дополнительные компоненты, без некоторых из которых сегодня трудно представить программу для Windows: кнопки с дополнительными свойствами, таблицы , компоненты для размещения изображений и многие другие.
Страница Win32
Страница палитры компонентов Win32 содержит компоненты, представляющие собой интерфейсные элементы для 32-разрядных операционных систем Windows 95/98/NT (В версии системы Delphi 2 эта страница называлась Win95). Использующие эти компоненты программы выглядят в стилистике последних версий операционных систем Windows.
Страница System
На странице палитры компонентов System представлены компоненты, которые имеют различное функциональное назначение (например, Timer — очень важный в любой программе компонент), в том числе компоненты, поддерживающие стандартные для Windows технологии межпрограммного обмена данными OLE и DDE.

Работа со строками Delphi позволяет извлечь из строки необходимую информацию и представить её в нужном виде. Delphi предоставляет весь спектр необходимых функций для работы со строками и преобразования строк Delphi в необходимые форматы.
Продолжение. Использование списка строк. Список строк Delphi TStringList — это структура данных, напоминающая компонент ListBox, но не визуальная, а просто хранящая в памяти и имеющая свойства и методы для работы со строками типа TString.

Создание интерфейса пользователя сводится к выбору из палитры компонентов необходимых для работы программы компонентов Delphi, служащих интерфейсом управления, а также интерфейсом отображения информации, и перенесению их на Форму с последующей компоновкой.

Работа с графикой в Delphi это не только линии и рисунки, но также и и печать текстовых документов. Поэтому в Delphi работе с графикой нужно уделить немного времени. Работа с графикой в Delphi предполагает знакомство с канвой (Canvas) компонентов. Канва это тот холст, который умеет управлять состоянием каждого своего пиксела, и это свойство позволяет программисту отобразить то, что требуется.

Потоки в Delphi выполняют функцию имитации псевдопараллельной работы приложения. Как известно, для организации многозадачности операционная система выделяет каждому приложению, выполняющемуся в настоящий момент, определённые кванты времени, длина и количество которых определяется его приоритетом. Поэтому объём работы, который приложение может выполнить, определяется тем, сколько таких квантов оно сможет получить в единицу времени.

Динамически создаваемые компоненты — это компоненты, место в памяти под которые выделяется по мере необходимости в процессе работы приложения. Этим они и отличаются от компонентов, которые помещаются на Форму при проектировании приложения. Возможность создавать компоненты динамически это очень большое удобство для программиста.

Новые Уроки Delphi будут появляться с течением времени. Кроме того, будут корректироваться уже готовые уроки с целью избавиться от всегда возможных неточностей и ошибок. Как говорится:

Borland delphi 4 0 для начинающих элементы управления activex

procedure TFormI.mnuEditCopyClick(Sender: TObject);

Все, что происходит в мире Windows, базируется на сообщениях. Для выполнения какой-либо функции управляющие элементы часто отсылают сообщения самим себе. Так и в этом примере управление происходит путем передачи сообщения WMCOPY.

Это свойство возвращает объект TForm, имеющий фокус ввода. Если приложение неактивно, свойство указывает, какая именно форма будет иметь фокус ввода при активизации приложения. В качестве примера используем свойство для создания мигающего заголовка формы, чтобы привлечь внимание пользователя. Функция Windows API, предназначенная для этой цели, должна получить дескриптор окна:

Это свойство определяет форму указателя мыши для всего приложения. Обычно оно используется для отображения песочных часов, чтобы в то время, пока пользователь думает о сложной работе, выполняемой приложением, немного передохнуть.

for iCount:=1 to 1000000000 do;

Форму указателя можно изменить для каждого потомка TControl (включая ТForm) отдельно.

Forms и FormCount

Эти свойства возвращают список форм и их количество. Работа с ними ничем не отличается от работы со списком дочерних окон, описанных в разделе „MDIChildren и MDIChildCount“.


Это наиболее полезные свойства, возвращающие высоту и ширину экрана в пикселях. Они могут применяться во многих ситуациях, например при определении местоположения формы. Вот как поместить форму в центре экрана.

Left:= (Screen.Width — Width) div 2;

Top:= (Screen.Height — Height) div 2;

tscreen предоставляет два основных события, извещающие программу об изменении фокуса ввода. Подобно возможностям класса TApplication, возможности класса TScreen доступны лишь при выполнении.

Это событие возникает при передаче фокуса ввода от одного управляющего элемента к другому. Свойство

ActiveControl обновляется непосредственно перед вызовом события. Вы можете использовать событие, например, для вывода текста подсказки в строке состояния.

procedure TFormI.ActiveControlChangeHandler(Sender: TObject);

if (not Application.Terminated) then

Проверка связана с тем, что событие генерируется и при закрытии приложения, а при этом обращение к уже уничтоженному объекту вызовет исключительную ситуацию.

Событие генерируется при создании новой формы или передаче фокуса ввода от одной формы к другой. Обычно это событие используется в MDI-приложениях для обновления доступных функций меню и кнопок-ускорителей. Ниже приведен пример из шаблона MDI-приложения.

procedure TMainForm.UpdateMenuItems(Sender: TObject);

FileCloseItem.Enabled:= MDIChildCount 0;

FileSaveItem.Enabled:= MDIChildCount 0;

FileSaveAsItem.Enabled:= MDIChildCount 0;

Процедура UpdateMenuItems назначена в качестве обработчика событию OnActiveFormChange в обработчике

procedure TMainForm.FormCreate(Sender: TObject);

Разделяемые обработчики событий

Как вы уже знаете, каждый класс способен генерировать свои собственные события. Каждое из них имеет определенный тип, как, например, TNotifyEvent у OnClick и TCloseEvent у OnClose. Delphi позволяет написать один обработчик события и назначить его нескольким событиям одновременно.

Представьте себе объект TEdit, генерирующий события OnKeyDown и OnKeyUp. Поскольку оба события — одного типа, можете написать одну процедуру и назначить ее обоим событиям. Процедура будет вызываться дважды при каждом нажатии клавиши (при нажатии и отпускании). Или, например, вы можете создать один обработчик для событий OnCreate и OnClick.

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

Вот как создать разделяемый между классами TButton и TEdit обработчик OnClick.

Выберите из меню File/New Application для создания приложения.

Поместите TButton в форму и введите в обработчик OnClick следующий код. procedure TFormI.ButtonlClick (Sender: TObject);

Поместите TEdit в форму. В Object Inspector выберите в списке для события OnClick обработчик ButtonClick. Теперь после щелчка на кнопке и на объекте TEdit будут выполняться одни и те же действия, фокус ввода будет передаваться управляющему элементу TEdit, и весь текст в нем будет выделяться.

Поскольку множество объектов может разделять один обработчик событий, необходимо уметь выяснять, какой именно обработчик его сгенерировал. Для этого предназначен параметр Sender, передаваемый в каждый обработчик, который указывает на объект, сгенерировавший событие. Часто этот параметр используется для различных действий обработчика в зависимости от того, кто именно породил событие.

Создание одноэкземплярного приложения

Если в Windows несколько раз щелкнуть на пиктограмме приложения, по умолчанию запустится сразу несколько его копий. Чтобы избежать этого, т. е. не дать запуститься второй копии приложения, необходимо выполнить поиск по заголовкам окон.

Поиск по заголовкам окон

При создании экземпляра окна Windows требует зарегистрировать имя класса окна (window class name). Delphi использует класс формы в качестве имени класса окна, например, когда Delphi создает экземпляр Form1 класса TForm1, TForm1 используется в качестве имени для регистрации окна Form1. Каждая форма имеет свойство Caption, известное как заголовок окна (window title). Эти два параметра позволяют искать окно с помощью функции Windows API FindWindow, возвращающей дескриптор найденного окна.

Эту функцию нельзя вызывать из класса TForm1, так как к тому времени окно уже будет создано, и вы окажетесь в глупом положении, найдя сами себя. Вот код, который должен находиться в файле проекта.

if FindWindow(‘TFormi’,’Formi’) о 0 then Application.Terminate;

Поскольку вы используете функцию Windows API, проследите, чтобы был подключен модуль Windows.

Если вы запускаете это приложение из Delphi, учтите, что Form Designer уже создал такое окно, и вы всегда сможете его найти. Это приложение следует запускать отдельно, закрыв Delphi.

Изменив свойство Caption или Name, вы рискуете не найти своего окна и придется повозиться с кодом программы, чтобы отследить эти изменения. Может возникнуть ситуация, когда простое совпадение приведет к тому, что окно будет найдено в совсем другом приложении, которое будет опознано как свое.

Активизирование существующей копии

Все-таки, сказать пользователю „Ты уже запустил одну копию, теперь иди и ищи ее!“ — как-то негуманно… Более профессиональным решением будет активизировать существующую копию с помощью другой функции Windows API — SetForegroundWindow. Измените проект следующим образом.

Borland delphi 4 0 для начинающих элементы управления activex

Теперь займемся увлекательным делом — создадим элементы управления ActiveX. Рассмотрим, что собой представляв ActiveX и чем элементы управления ActiveX лучше или хуже стандартных компонентов Delphi на базе библиотек VCL.
Технология AcliveX компании Microsoft представляет собой технологию ОСХ, переделанную для обеспечения пepедачи элементов управления через службы Internet, в основном через World Wide Web. Я уверен, что читатель спросит «Это все хорошо, но как технология ActiveX может помочь мне?». Но неужели вам не хочется создать элементы управления, которые можно использовать не только в Delphi, но и в таких средах программирования, как Borland C++ Builde Visual C++ и Visual Basic? Технология ActiveX предоставляет вам такую возможность.
Чтобы использовать эту возможность, Delphi предлагает с помощью среды DAX заключить потомка класса TWin Control в элемент управления ActiveX. Ниже перечислены платформы, на которых сертифицированы для выполнены элементы управления ActiveX, поставляемые с Delphi.

  • Borland Delphi версии 2 и 3.
  • Borland C++ Builder.
  • Borland Paradox 8.
  • Borland IntraBuilder.
  • Microsoft Visual C++.
  • Microsoft Visual Basic версии 4 и 5.
  • Microsoft Internet Explorer 3.01.
  • Microsoft ActiveX Control Pad.
  • Microsoft Frontpage.

Создание элемента управления ActiveX предусматривает выполнение следующих этапов.

  1. Элемент управления VCL должен быть вставлен в палитру компонентов Delphi и должен быть потомком класса TWinControl. Чтобы создать элемент управления ActiveX, являющийся потомком TGraphicControl. в большинстве случаев достаточно изменить базовый класс на TCustomControl. Этот способ использован в примере, который будет приведен немного позже.
  2. Запустите мастера ActiveX Control, выбрав команду File/New и дважды щелкнув на пиктограмме ActiveX Control во вкладке ActiveX. В окне мастера выберите компонент VCL, который нужно преобразовать в элемент ActiveX, укажите имя элемента ActiveX, включите или отключите информацию о лицензировании, версии и т.п. После щелчка на кнопке OK Delphi создаст библиотеку типов со всеми свойствами, объявленными как public и published, методами и событиями. Дополнительно создаются два файла исходного кода: в одном из них содержатся определения из библиотеки типов (интерфейсы, диспинтерфейсы и т.д.), а во втором — реализации методов интерфейса, определенных в первом файле.
  3. В процессе создания библиотеки типов Delphi может преобразовать не все конструкции языка то ли потому, что нет смысла преобразовывать отдельные конструкции, то ли потому, что она не знает, как преобразовать некоторые конструкции языка Object Pascal. Независимо от причины, по которой преобразование не выполнилось, в определение элемента ActiveX можно легко добавить любые свойства, методы и события. Для этого откройте библиотеку типов (с помощью команды View/Type Library), внесите необходимые изменения и щелкните на кнопке Refresh панели инструментов редактора библиотек типов, что позволит Delphi обновить код.
  4. Создайте код всех методов Get и Set, в которых не реализована необходимая функциональность или которые оставлены пустыми, как добавления к библиотеке типов. Это относится и к обработчикам событий.
  5. Теперь вы, возможно, пожелаете создать одну или несколько страниц свойств. В средах, не поддерживающих инспекторов свойств, это даст возможность пользователю, щелкнув правой кнопкой мыши, вызвать некоторое подобие инспектора свойств для изменения значений свойств элемента управления. Для этого, как минимум, нужно создать основную страницу свойств. Delphi обладает несколькими стандартными страницами свойств для управления цветом, шрифтами, изображением и списком строк Delphi.
  6. Откомпилируйте и зарегистрируйте элемент управления.
  7. ОСХ-файл можно импортировать в любую среду разработки, поддерживающую элементы управления ActiveX, которые созданы в Delphi.


Оглавление

1С:Предприятие 7.5, 7.7, 8.0 Технология создания внешних компонент

Введение

Система программ 1С:Предприятие предназначена для решения самых разнообразных задач автоматизации деятельности организаций. Она обладает мощными средствами конфигурирования, которые позволяют штатными средствами настроить систему на особенности обработки информации в конкретной организации. В тоже время, 1С:Предприятие является открытой системой. Для связи с другими программами могут использоваться встроенные средства загрузки-выгрузки информации в текстовом формате, в форматах DBF и XML, система поддерживает стандарт интеграции программ OLE Automation. Однако для специальных задач интеграции может потребоваться более тесное взаимодействие между 1С:Предприятием и другими программами.

Для решения таких задач разработана «Технология создания внешних компонент». Данная технология позволяет создавать программы, которые будут динамически подключаться и тесно взаимодействовать с системой 1С:Предприятие, расширяя ее возможности. Внешние компоненты позволяют решать широкий спектр специальных задач, в частности, задачи, связанные с использованием различного торгового оборудования совместно с 1С:Предприятием.

В комплект поставки входит данное руководство и набор примеров реализации внешних компонент с помощью различных программных средств.

В данном руководстве описана технология создания внешних компонент версии 1.0 и 2.0.

Версии компонент

Технология создания внешних компонент версии 2.0 является развитием версии 1.0 и предназначена для использования с 1С:Предприятием 7.7 и 8. Все возможности, описанные в данной книге, относятся к версиям 1.0 и 2.0, если нет явного указания, что данная возможность относится исключительно к версии 2.0. Ниже приводится информация о совместимости различных версий внешних компонент и 1С:Предприятия между собой.

Версия компоненты определяется по возвращаемому методом GetInfo значению.

Компоненты версии 1.0 полностью совместимы с 1С:Предприятием 7.5, 7.7 и 8. При работе компоненты с 1С:Предприятием 7.7 и 8 создание нескольких однотипных объектов невозможно.

Компоненты версии 2.0 полностью совместимы с 1С:Предприятием 7.7 и 8. Эти компоненты могут работать с 1С:Предприятием 7.5 при условии, что они используют только возможности версии 1.0. При работе компоненты с 1С:Предприятием 7.5 создание нескольких однотипных объектов невозможно.

1С:Предприятие 7.5 может использовать внешние компоненты версии 1.0. Компоненты версии 2.0 могут быть использованы при условии, что они не задействуют возможностей версии 2.0.

1С:Предприятие 7.7 и 8 может использовать внешние компоненты версий 1.0 и 2.0. При использовании компоненты версии 1.0 создание нескольких однотипных объектов невозможно.

В 1С:Предприятии 8 возможности версии 2.0 по созданию окон сохранены в сокращенном виде для совместимости с существующими компонентами. Для отображения нестандартной информации в окнах 1С:Предприятия 8 рекомендуется использовать формы с элементами управления ActiveX или же Активные документы.

Что Вы должны знать

Настоящая методика предназначена для специалистов, выполняющих конфигурирование 1С:Предприятия и решающих задачи, выходящие за возможности встроенных в 1С:Предприятие механизмов.

Для работы с методикой необходимо знание основ COM (ActiveX). Желательно также знакомство с используемыми средами программирования.

Замечание: Для работы внешних компонент, поставляемых в этом комплекте, необходимы дополнительные библиотеки, входящие в поставку используемых сред разработки.

Структура руководства

В первой части настоящей методики описывается стандарт, которому должна следовать внешняя компонента при работе с 1С:Предприятием. В этой части также приводится описание интерфейсов, предоставляемых 1С:Предприятием внешней компоненте.

Во второй части разбираются примеры построения внешних компонент в различных средах разработки. Используются следующие программные продукты: Visual C++ 5.0 — 7.0, Visual Basic 5.0 и 6.0 (Enterprise Edition), Visual Basic .NET, Borland Delphi 3.0 –5.0. Для каждой среды разобраны структура и код примера и сложные детали реализации.

Третья часть описывает основы COM и может быть использована как краткая справка по COM.

Глава 1. Внешние компоненты

Возможности внешней компоненты:

  • расширение встроенного языка 1С:Предприятия (добавление новых агрегатных объектов);
  • добавление страницы свойств в параметры 1С:Предприятия;
  • сохранение параметров внешней компоненты через механизмы сохранения параметров 1С:Предприятия;
  • создание дополнительных окон в окне 1С:Предприятия (версия 2.0, только для 1С:Предприятия 7.7);
  • доступ к функциям 1С:Предприятия через OLE Automation (версия 2.0);
  • вызов процедуры обработки событий, контролируемых внешней компонентой;
  • доступ к строке состояния 1С:Предприятия.

Внешние компоненты используются в 1С:Предприятии для расширения его возможностей при выполнении различных задач. В частности, в число таких задач входит вызов функции из библиотеки (DLL), использование различного торгового оборудования, нестандартное отображение данных и т.д. Все внешние компоненты следуют единому стандарту, поэтому при работе можно использовать как уже существующие компоненты, так и разрабатывать новые. В данную поставку входят шаблоны и примеры для различных сред разработки, которые позволяют упростить разработку новых компонент.

Средства встроенного языка 1С:Предприятия, предназначенные для работы с внешними компонентами

Загружает внешнюю компоненту, создает соответствующие COM-объекты и подключает их к 1С:Предприятию.

Тип: строка. Имя файла внешней компоненты. должно иметь вид «Имя.Расширение» и не должно содержать путь. Файл компоненты должен находиться в каталоге исполняемых файлов 1С:Предприятия.

Тип: число. 0 — при загрузке компоненты произошла ошибка. 1 — компонента успешно загружена. При возникновении ошибок при загрузке 1С:Предприятие выдает информацию об ошибке в окно сообщений.

отсутствует. В случае ошибки возникает исключительная ситуация.

Внешние компоненты загружаются функцией встроенного языка ЗагрузитьВнешнююКомпоненту. Файл внешней компоненты должен быть динамически загружаемой библиотекой (например, DLL или OCX), то есть работать как InProc сервер. При загрузке внешней компоненты 1С:Предприятие вызывает функцию DllRegisterServer, если она экспортирована из внешней компоненты. Это позволяет просто переносить компоненты между компьютерами без дополнительной регистрации их как COM-серверов. О создании COM-объекта внешней компоненты при загрузке — см. Разработка внешней компоненты.

Создает COM-объекты внешней компоненты и подключает их к 1С:Предприятию.

ProgID (Programmatic Identifier) объекта внешней компоненты. должно соответствовать информации, находящейся в регистрационной базе данных системы (Registry).

Тип: число. 0 — при загрузке компоненты произошла ошибка. 1 — компонента успешно загружена. При возникновении ошибок при подключении 1С:Предприятие выдает информацию об ошибке в окно сообщений.

Отсутствует. В случае ошибки возникает исключительная ситуация.

Внешние компоненты подключаются функцией встроенного языка ПодключитьВнешнююКомпоненту. Внешняя компонента может быть как динамически загружаемой библиотекой (например, DLL или OCX), так и приложением.

Предопределенная процедура встроенного языка. Вызывается при возникновении сообщения от внешней компоненты.

Тип:строка. Наименование источника сообщения.

Тип:строка. Наименование сообщения.

Тип:строка. Параметры сообщения.

Процедура ОбработкаВнешнегоСобытия — предопределенная процедура обработки сообщений от внешних компонент.

1С:Предприятие 7.5, 7.7

Процедура может быть описана в любом модуле системы 1С:Предприятие. При получении сообщения будет вызвана процедура ОбработкаВнешнегоСобытия, определенная в модуле активной на этот момент формы. Если в этом модуле процедура ОбработкаВнешнегоСобытия не определена, то будет вызвана процедура ОбработкаВнешнегоСобытия, определенная в глобальном модуле. Если в глобальном модуле процедура ОбработкаВнешнегоСобытия отсутствует, будет выдано сообщение об отсутствии процедуры ОбработкаВнешнегоСобытия. Процедура ОбработкаВнешнегоСобытия в глобальном модуле не вызывается, если событие обработано в модуле активной формы.

Процедура может быть описана в модуле приложения системы 1С:Предприятие. При получении сообщения будут вызваны обработчики внешнего события, определенные в модулях всех открытых на этот момент форм. После этого будет вызвана процедура ОбработкаВнешнегоСобытия, определенная в модуле приложения.

Вызов этой процедуры синхронизирован с обработкой сообщений системой 1С:Предприятие и происходит только при отсутствии других выполняемых системой операций (проведении документов, построении отчетов и т.д.).

Процедура обработки внешнего события во встроенном языке. Вызывается при возникновении сообщения от внешней компоненты. В 1С:Предприятии 7.5, 7.7 отсутствует – в качестве этого обработчика используется предопределенная процедура ОбработкаВнешнегоСобытия.

Тип:строка. Наименование источника сообщения.

Тип:строка. Наименование сообщения.

Тип:строка. Параметры сообщения.

Процедура может быть описана в модуле любой формы системы 1С:Предприятие. При получении сообщения будет вызвана процедура ВнешнееСобытие, определенная в модулях открытых на этот момент форм. После обработки внешнего события в формах будет вызвана предопределенная процедура ОбработкаВнешнегоСобытия, определенная в модуле приложения. Процедура ОбработкаВнешнегоСобытия в модуле приложения всегда вызывается последней. Для отличия активной в данный момент формы можно использовать функцию ВводДоступен.

Вызов этой процедуры синхронизирован с обработкой сообщений системой 1С:Предприятие и происходит только при отсутствии других выполняемых системой операций (проведении документов, построении отчетов и т.д.).

Разработка внешней компоненты


Создание COM—объекта внешней компоненты

При загрузке внешней компоненты функцией ЗагрузитьВнешнююКомпоненту 1С:Предприятие определяет ProgID COM—объекта компоненты следующим образом:

  • ProgID имеет вид . ;
  • в качестве первой части ( ) используется строка «AddIn»;
  • в качестве второй части ( ) используется строка с ID 100 из таблицы строк компоненты. Строка может иметь вид «Name1|Name2|. |NameN», и в этом случае будут созданы все объекты с ProgID вида «AddIn.NameX». Если такая строка отсутствует, то используется имя файла внешней компоненты без расширения.

При использовании функции ПодключитьВнешнююКомпоненту ProgID COM-объекта компоненты передается в качестве параметра функции и также может представляться строкой вида ProgID1| ProgID2|. |ProgIDX.

Инициализация и выгрузка компоненты

Для инициализации и выгрузки компоненты используется интерфейс IInitDone. Этот интерфейс наследован от IUnknown и предназначен для инициализации объекта и завершения работы с объектом.

HRESULT Init(IDispatch *pBackConnection)

Тип: IDispatch. Указатель на интерфейс 1С:Предприятия.

  • E_FAIL — при инициализации произошла ошибка
  • S_OK — инициализация прошла успешно

При загрузке 1С:Предприятие инициализирует объект компоненты, вызывая метод Init и передавая указатель на IDispatch. Объект может сохранить этот указатель для дальнейшего использования. Все остальные интерфейсы 1С:Предприятия объект может получить, вызвав метод QueryInterface переданного ему интерфейса IDispatch. Объект должен возвратить S_OK, если инициализация прошла успешно, и E_FAIL при возникновении ошибки. Данный метод может использовать интерфейс IErrorLog для вывода информации об ошибках. При этом инициализация считается неудачной, если одна из переданных структур EXCEPINFO имеет поле scode, не равное S_OK. Все переданные в IErrorLog данные обрабатываются при возврате из данного метода. В момент вызова этого метода свойство AppDispatch не определено.

  • S_OK — объект завершил работу

1С:Предприятие вызывает этот метод при завершении работы с объектом компоненты. Объект должен возвратить S_OK. Этот метод вызывается независимо от результата инициализации объекта (метод Init).

HRESULT GetInfo(SAFEARRAY **pInfo)

Тип: SAFEARRAY**. Двойной указатель на массив структур VARIANT. Память для массива выделяется 1С:Предприятием.

  • S_OK — информация о компоненте возвращена

1С:Предприятие вызывает этот метод для получения информации о компоненте. В текущей версии 2.0 компонентной технологии в элемент с индексом 0 необходимо записать версию поддерживаемой компонентной технологии в формате V_I4 — целого числа, при этом старший номер версии записывается в тысячные разряды, младший номер версии — в единицы. Например: версия 3.56 — число 3560. В настоящее время все объекты внешних компонент могут поддерживать версию 1.0 (соответствует числу 1000) или 2.0 (соответствует 2000). Память для pInfo выделяется 1С:Предприятием. Метод должен возвращать S_OK.

Объект внешней компоненты обязан реализовать этот интерфейс. При его отсутствии компонента не будет загружена.

Страница свойств

Для добавления страницы свойств объекта компоненты в диалог настройки параметров 1С:Предприятия используются интерфейсы IPropertyPage или ISpecifyPropertyPages (объект может реализовать любой из этих интерфейсов). Каждый объект может добавить одну страницу свойств. Странице свойств при инициализации передается указатель на интерфейс IUnknown соответствующего объекта внешней компоненты. Интерфейсы IPropertyPage, ISpecifyPropertyPages являются стандартными для COM, поэтому их описание Вы сможете найти в документации на COM.

Расширение встроенного языка

Для расширения встроенного языка компонента должна реализовать интерфейс ILanguageExtender. Этот интерфейс унаследован от IUnknown и предназначен для расширения встроенного языка 1С:Предприятия. Для использования этого расширения необходимо вызвать функцию СоздатьОбъект (Новый в 1С:Предприятии 8), передав ей строку вида «AddIn. «, где возвращается методом этого интерфейса Затем можно использовать созданный объект, вызывая его методы и свойства.

Версия 2.0 позволяет создавать несколько объектов одного типа «AddIn. «, однако компонента должна явно указать поддержку версии 2.0 в методе GetInfo. В противном случае допускается создание только одного объекта.

HRESULT RegisterExtensionAs(BSTR *pExtensionName)

Тип: BSTR*. Наименование расширения встроенного языка 1С:Предприятия.

В переменную pExtensionName помещается наименование расширения. Память для строки выделяется объектом компоненты стандартными системными функциями для работы с COM—строками (например, SysAllocString. 1С:Предприятие освобождает эту память вызовом SysFreeString).

Первое свойство имеет порядковый номер 0.

HRESULT GetNProps(long *plProps)

Тип: long*. Указатель на переменную, содержащую при возврате количество свойств расширения.

Возвращает количество свойств данного расширения, 0 – при отсутствии свойств. Память для переменной plProps выделяется 1С:Предприятием.

HRESULT FindProp(BSTR pszPropName,long*plPropNum)

Тип: BSTR. Наименование свойства.

Тип: long*. Указатель на переменную, содержащую при возврате порядковый номер свойства.

  • S_OK — операция завершена успешно
  • S_FALSE — свойство с именем pszPropName в данном расширении отсутствует

Возвращает порядковый номер свойства с именем pszPropName; -1, если свойство не найдено. Память для переменной plPropNum выделяется 1С:Предприятием.

HRESULT GetPropName(long lPropNum,long lAliasNum,BSTR *pPropName)

Тип: long. Порядковый номер свойства.

Тип: long. Язык наименования:


    • 0 — английское наименование;
    • 1 — локальное наименование.

Тип: BSTR*. Указатель на строку, содержащую при возврате наименование свойства.

  • S_OK — операция завершена успешно
  • S_FALSE — свойство с номером lPropNum в данном расширении отсутствует

В переменную pPropName помещается имя свойства с порядковым номером lPropNum; если свойство с таким номером отсутствует, в pPropName помещается пустая строка. Память для строки выделяется объектом компоненты стандартными системными функциями для работы с COM—строками (например, SysAllocString. 1С:Предприятие освобождает эту память вызовом SysFreeString).

HRESULT GetPropVal(long lPropNum,VARIANT *pvPropVal)

Тип: long. Порядковый номер свойства.

Тип: VARIANT*. Указатель на структуру VARIANT, содержащую при возврате значение свойства.

  • S_OK — операция завершена успешно
  • S_FALSE — свойство с номером lPropNum в данном расширении отсутствует или недоступно для чтения.

В переменную pvPropVal помещается значение свойства с порядковым номером lPropNum; если свойство с таким номером отсутствует или недоступно для чтения, должен иметь тип VT_EMPTY.

HRESULT SetPropVal(long lPropNum, VARIANT *pvPropVal)

Тип: long. Порядковый номер свойства.

Тип: VARIANT*. Структура VARIANT, содержащая новое значение свойства.

  • S_OK — операция завершена успешно
  • S_FALSE — свойство с номером lPropNum в данном расширении отсутствует или недоступно для записи.

Переменная pvPropVal содержит значение свойства с порядковым номером lPropNum; если свойство с таким номером отсутствует, недоступно для чтения или тип переданного pvPropVal не приводится к необходимому, метод должен возвратить S_FALSE.

HRESULT IsPropReadable(long lPropNum, BOOL *pboolPropReadable)

lPropNum Тип: long. Порядковый номер свойства.

pboolPropReadable Тип: BOOL*. Указатель на переменную, содержащую при возврате флаг возможности чтения свойства.

  • S_OK — операция завершена успешно.
  • S_FALSE — свойство с номером lPropNum в данном расширении отсутствует.

В переменную pboolPropReadable помещается флаг возможности чтения свойства с порядковым номером lPropNum: FALSE(0) — свойство недоступно для чтения, TRUE(1) — свойство допускает чтение. Если свойство с таким номером отсутствует, метод должен возвращать S_FALSE.

HRESULT IsPropWritable(long lPropNum, BOOL *pboolPropWritable)

Тип: long. Порядковый номер свойства.

Тип: BOOL*. Указатель на переменную, содержащую при возврате флаг возможности записи свойства.

  • S_OK — операция завершена успешно.
  • S_FALSE — свойство с номером в данном расширении отсутствует.

В переменную pboolPropWritable помещается флаг возможности записи свойства с порядковым номером lPropNum: FALSE(0) — свойство недоступно для записи, TRUE(1) — свойство допускает запись. Если свойство с таким номером отсутствует, метод должен возвращать S_FALSE.

Первый метод имеет порядковый номер 0. Первый параметр метода имеет порядковый номер 0.

HRESULT GetNMethods(long *plMethods)

Тип: long*. Указатель на переменную, содержащую при возврате количество методов расширения языка.

В переменную plMethods помещается количество методов данного расширения, 0 — при отсутствии методов.

HRESULT FindMethod(BSTR bstrMethodName,long *plMethNum)

Тип: long*. Указатель на переменную, содержащую при возврате порядковый номер метода с именем methodName.

В переменную plMethNum помещается порядковый номер метода с именем bstrMethodName; -1 — при отсутствии метода.

HRESULT GetMethodName(long lMethodNum, long lAliasNum, BSTR *pbstrMethName)

Тип: long. Порядковый номер метода.

Тип: long. Язык имени метода:


    • 0 — английское наименование;
    • 1 — локальное наименование.

Тип: BSTR*. Указатель на строку, содержащую при возврате имя метода.

  • S_OK — операция завершена успешно
  • S_FALSE — метод с номером в данном расширении отсутствует

В переменную помещается имя свойства с порядковым номером; если свойство с таким номером отсутствует, в помещается пустая строка. Память для строки выделяется объектом компоненты стандартными системными функциями для работы с COM—строками (например, SysAllocString. 1С:Предприятие освобождает эту память вызовом SysFreeString).

HRESULT GetNParams(long lMethodNum, long *plMethParams)

Тип: long. Порядковый номер метода.

Тип: long*. Указатель на переменную, содержащую при возврате количество параметров метода.

  • S_OK — операция завершена успешно
  • S_FALSE — метод с номером в данном расширении отсутствует

В переменную plMethParams помещается количество параметров метода с порядковым номером lMethodNum; если свойство с таким номером отсутствует или не имеет параметров, в помещается 0. Память для переменной выделяется 1С:Предприятием.

HRESULT GetParamDefValue(long lMethodNum, long lParamNum, VARIANT *pvParamDefVal)

Тип: long. Порядковый номер метода.

Тип: long. Порядковый номер параметра.

Тип: VARIANT*. Указатель на структуру VARIANT, содержащую при возврате значение параметра по умолчанию.

  • S_OK — операция завершена успешно (вне зависимости от наличия у параметра значения по умолчанию)
  • S_FALSE — метод или параметр метода отсутствует

В переменную pvParamDefVal помещается значение по умолчанию параметра lParamNum метода с порядковым номером lMethodNum. В pvParamDefVal помещается тип VT_EMPTY, если метод с таким номером отсутствует, не имеет параметра с номером или параметр не имеет значения по умолчанию. Память для переменной выделяется 1С:Предприятием.

HRESULT HasRetVal(long lMethodNum,BOOL *pboolHasRetVal)

Тип: long. Порядковый номер метода.

Тип: BOOL*. Указатель на переменную, содержащую при возврате флаг наличия возвращаемого значения.

  • S_OK — операция завершена успешно
  • S_FALSE — метод отсутствует

В переменную pboolHasRetVal помещается флаг наличия возвращаемого значения у метода с порядковым номером lMethodNum: TRUE для методов с возвращаемым значением и FALSE в противном случае. Память для переменной выделяется 1С:Предприятием.

HRESULT CallAsProc(long lMethodNum, SAFEARRAY **pVars)

Тип: long. Порядковый номер метода.

Тип: SAFEARRAY**. Двойной указатель на массив структур VARIANT, содержащий значения параметров метода. Если метод не имеет параметров, то содержит NULL.

  • S_OK — соответствующий метод вызван, ошибок не произошло.
  • E_FAIL — соответствующий метод вызван, произошла ошибка времени исполнения (runtime error). Исполнение модуля прекращается.
  • S_FALSE – отсутствует метод, соответствующий переданному lMethodNum.

Выполняется метод с порядковым номером lMethodNum. Если метод возвращает E_FAIL, возникает ошибка времени выполнения и выполнение модуля 1С:Предприятия прекращается. Память для массива параметров выделяется 1С:Предприятием.

HRESULT CallAsFunc(long lMethodNum, VARIANT *pRetValue, SAFEARRAY **pVars)

Тип: long. Порядковый номер метода.

После создания объекта можно использовать его свойства и методы в отчете ПримерРаботыСКомпонентой.

Этот отчет использует свойство объекта Включен при инициализации и обработке внешнего события, порождаемого компонентой при изменении этого свойства:


Форма отчета ПримерРаботыСКомпонентой:

Для создания внешнего события откройте отчет и затем страницу параметров компоненты. Включите компоненту и нажмите кнопку «Применить» — элементы формы отчета должны стать доступными. При выключении компоненты элементы формы становятся недоступными.

Кнопки «Старт» и «Стоп» соответственно запускают и останавливают таймер. При этом в форме отображается текущее время. Это обрабатывается следующей частью процедурой ОбработкаВнешнегоСобытия:

Конфигурация для 1С:Предприятия 7.7

В конфигурации используются только глобальный модуль и обработка ПримерРаботыСКомпонентой. В глобальном модуле загружается внешняя компонента и создается объект «AddIn.AddInVideo»:

После создания объекта можно использовать его свойства и методы в обработке ПримерРаботыСКомпонентой.

Обработка ПримерРаботыСКомпонентой позволяет открыть окно с видеоклипом формата AVI, выбирая файл клипа из файлов на диске или же используя справочник клипов конфигурации (видеоклипы не входят в комплект поставки).

Примеры для Visual Basic и Visual C++ используют элемент управления ActiveX Microsoft Multimedia Control, входящий в поставку Visual Basic и Visual C++. Пример для Borland Delphi использует встроенный элемент управления TMediaControl, обеспечивающий те же функции, что и Multimedia Control.

Конфигурация для 1С:Предприятия 8

В конфигурации используется только модуль приложения и обработка ПримерРаботыСКомпонентой. В модуле основной формы обработки загружается внешняя компонента и создается объект «AddIn.AddInExtension»:

После создания объекта можно использовать его свойства и методы.

Эта обработка использует свойство объекта Включен при инициализации и обработке внешнего события, порождаемого компонентой при изменении этого свойства:

Для создания внешнего события откройте обработку и затем страницу параметров компоненты. Включите компоненту и нажмите кнопку «Применить» — элементы формы обработки должны стать доступными. При выключении компоненты элементы формы становятся недоступными.

Кнопки «Старт» и «Стоп» соответственно запускают и останавливают таймер. При этом в форме отображается текущее время. Это обрабатывается следующей частью процедурой ОбработкаВнешнегоСобытия:

Ссылка «Открыть новый экземпляр формы» используется для демонстрации использования свойства AppDispatch – в данном примере, используя это свойство, внешняя компонента может открывает новый экземпляр формы обработки ПримерРаботыСКомпонентой.

Описание компонент


Компонента SAMPLE

Компонента реализует следующие свойства и методы:

Свойства

Использование: Чтение и запись.

Описание: Тип: Булево. Содержит состояние компоненты.

Описание: Тип: Булево. Определяет наличие у компоненты таймера.

Методы

Описание: Включает объект компоненты.

Описание: Выключает объект компоненты.

Параметры: Текст. Текст, выводимый в строке статуса.

Описание: На 5 секунд выводит в строку статуса полученный текст.

Описание: Включает таймер компоненты. Каждую секунду компонента посылает сообщение 1С:Предприятию с параметрами «Компонента», «Таймер» и строкой времени.

Описание: Выключает таймер компоненты.

Описание: Открывает новый экземпляр формы обработки ПримерРаботыСКомпонентой. Этот метод присутствует только в компоненте для 1С:Предприятия 8.

Для управления компонентой используется страница свойств с опцией включения компоненты. При нажатии кнопки «Применить» компонента посылает сообщение 1С:Предприятию с параметрами «Компонента», «Включение» и строкой «0» или «1» в зависимости от включения компоненты. При подключении и отключении компонента загружает и сохраняет состояние включения.

Страница свойств компоненты

В VB.NET отсутствует поддержка страниц свойств для элементов управления, поэтому в компоненте, разработанной на VB.NET, страница свойств компоненты не реализована.

Компонента SAMPLE2

Компонента позволяет проигрывать видеоклипы формата AVI в окне 1С:Предприятия 7.7.

Компонента реализует следующие свойства и методы:

Свойства

Чтение и запись.

Тип: Строка. Содержит полное имя файла с видеоклипом.

Методы

Открывает окно с клипом, переданным в свойство ФайлКлипа.

Открывает окно с клипом, выбранным из файлов на диске.

Открывает окно с клипом, выбранным из справочника конфигурации.

ОткрытьКлипИзФайла и ОткрытьКлипИзСправочника открытия окна используют внешнее событие, передавая в качестве одного из параметров имя выбранного файла. Метод ОткрытьКлипИзСправочника использует OLE Automation 1C:Предприятия для доступа к справочнику клипов «Клипы».

Microsoft Visual C++


Компонента SAMPLE

Пример в Visual C++ написан с использованием библиотеки ATL (Active Template Library), входящей в состав поставки VC++.

Определение интерфейсов 1С:Предприятия

Все интерфейсы 1С:Предприятия определены в файле AddIn.idl. Этот файл содержит определения интерфейсов на IDL — Interface Definition Language. При компиляции проекта этот файл обрабатывается утилитой MIDL, порождающей файлы с определениями интерфейсов для C++ (AddInTlb.h, AddIn_i.c) и библиотекой типов AddIn.tlb.

Определение объекта внешней компоненты

Заголовочный файл AddIn.h содержит определение объекта CAddIn, унаследованного от различных интерфейсов и базовых COM-объектов:

Классы CComObjectRoot и CComCoClass являются базовыми для COM-объектов в ATL. IInitDone и ILanguageExtender — интерфейсы объекта внешней компоненты. IPropertyPageImpl и CDialogImpl реализуют страницу свойств объекта.

Следут обратить внимание на то, что класс CAddIn реализует одновременно как объект внешней компоненты, так и объект страницы свойств. Но поскольку объект и страница свойств являются различными экземплярами класса CAddIn, для их связи используется интерфейс IPropertyLink, определенный именно для этой компоненты.

Реализация объекта внешней компоненты

Реализация класса CAddIn находится в файле AddIn.cpp. В реализации используются функции LoadProperties и SaveProperties, в которые выносится загрузка и сохранение параметров объекта компоненты; функция TermString, упрощающая реализацию расширения встроенного языка; и функции GetNParam и PutNParam, использующиеся в реализации методов CallAsProc и CallAsFunc.

Интерфейсы IInitDone и ILanguageExtender определены в соответствии с настоящим описанием. Реализации методов расширения находятся в методе ILanguageExtender::CallAsProc, так как ни один из методов не возвращает значения. Методы Включить и Выключить достаточно просты и не нуждаются в разборе. Методы работы с таймером используют системные функции SetTimer и KillTimer, реализация функции таймера находится в конце файла. Метод ПоказатьВСтрокеСтатуса более сложен: он использует в своей работе интерфейс IErrorLog:

Если у объекта почему-либо отсутствует указатель на интерфейс IStatusLine, объект посылает информацию через интерфейс IErrorLog. Поля wCode и scode заполняются соответствующими кодами ошибок. Поля bstrSource и bstrDescription заполняются строками, описывающими соответственно источник ошибки и саму ошибку. Для работы с строками COM в VC++ удобно использовать CString и функцию AllocSysString, возвращающую BSTR.

Создание собственной компоненты

При разработке собственной компоненты можно использовать шаблон из данной методики или начать разработку компоненты «с нуля». В последнем случае необходимо:

  1. Выбрать из меню File | New.
  2. В закладке Projects выбрать ATL COM AppWizard (ATL Project для VC++ 7.0), задать имя проекта и его расположение.
  3. Нажать OK.
  4. Выбрать создание DLL и завершить создание объекта.

По расположению в файлах созданный проект будет практически аналогичен (с точностью до имен файлов) шаблону из данной методики. Необходимо лишь внести в IDL—файл определения интерфейсов 1С:Предприятия, отредактировать определение объекта внешней компоненты, внести строку с индексом 100 для автоматического создания объекта 1С:Предприятием при загрузке и запрограммировать функциональность компоненты.

Компонента SAMPLE2

Пример написан в Visual C++ с использованием библиотеки MFC, входящей в состав поставки VC++.

Структура проекта

Проект разбит на две части — часть ActDoc реализует Активный документ, часть AddIn реализует внешнюю компоненту для взаимодействия с 1С:Предприятием 7.7 и создания окна Активного документа. Внешняя компонента создана на основе шаблона, поэтому ее описание здесь не приводится.

Активный документ

Реализация Активного документа в Visual C++ с использованием MFC достаточно сложна, поэтому ниже описаны только некоторые детали, необходимые для понимания работы документа. Для детального разбора реализации Вам необходимо обратиться к соответствующей справочной литературе.

Для определения Активного документа используется несколько различных классов, основные из которых – класс CAddDocDoc, реализующий документ, и класс CAddDocView, реализующий визуальную часть документа. Эти классы определены в файлах AddDoc.h и AddDoc.cpp. Документ использует элемент Cmci, полученный импортированием ActiveX (см. пункт меню Project|Add To Project|Components and Controls…) и представляющий интерфейс к Microsoft Multimedia Control. Cmci создается и отображается в окне в методе OnInitialUpdate класса CAddDocView. При изменении размеров окна CAddDocView соответственно изменяет размеры Cmci. Для управления извне документ реализует два метода, доступных через OLE Automation: SetFileName и Play.

Создание собственной компоненты

При разработке собственной компоненты можно использовать шаблон из данной методики или начать разработку компоненты «с нуля». При разработке «с нуля» есть несколько вариантов построения проекта, один из них (соответствующий примеру) приведен ниже:

  1. Выбрать из меню File | New.
  2. В закладке Projects выбрать MFC AppWizard (EXE), задать имя проекта и его расположение.
  3. Нажать OK.
  4. Выбрать необходимые параметры сервера, поддержку OLE Automation и ActiveX Controls (в данном примере miniserver с поддержкой OLE Automation и ActiveX Controls) и завершить создание объекта.

Далее можно добавить проект, содержащий реализацию внешней компоненты и при создании окна передавать в качестве ProgID идентификатор созданного MFC AppWizard Активного документа. В качестве добавляемого проекта можно использовать входящий в комплект поставки шаблон.

Microsoft Visual Basic 5.0 и 6.0 (Enterprise Edition)


Общая часть компонент


Определение интерфейсов 1С:Предприятия

В комплект поставки включена библиотека типов AddIn.tlb, на который должна быть установлена ссылка из проекта. Для установки ссылки нужно сделать следующее:

  1. Открыть проект в Visual Basic.
  2. Выбрать пункт Project | References.
  3. Нажать кнопку Browse.
  4. Выбрать файл AddIn.tlb и нажать кнопку Open.
  5. Нажать ОК.

Возможно, что библиотека типов уже зарегистрирована на Вашем компьютере. Тогда в п.3 вместо нажатия Browse. выберите библиотеку V7 AddIn 1.0 Type Library в списке библиотек и включите опцию выбора.

Установление ссылки на библиотеку типов позволяет использовать наименования COM-интерфейсов в операторе Implements при реализации COM-объекта.

Определение и реализация объекта внешней компоненты

В реализации используются функции LoadProperties и SaveProperties, в которые выносится загрузка и сохранение параметров объекта компоненты; функция TermString, упрощающая реализацию расширения встроенного языка; функции GetNParam и PutNParam, используемые в Visual C++ и Borland Delphi, отсутствуют, так как в Visual Basic встроена работа с структурой SAFEARRAY.

В Visual Basic отсутствует доступ к ресурсам проекта, поэтому строка с номером 100 добавляется в виде скомпилированного файла ресурсов AddInStr.res. Этот файл можно получить, скомпилировав файл AddInStr.rc утилитой RC.EXE (эта утилита входит в поставку Visual Basic 5.0). Командная строка проста: RC AddInStr.rc. Файл AddInStr.rc — это обычный текстовый файл, который можно править любым текстовым редактором.

Компонента SAMPLE

Пример в Visual Basic (Enterprise Edition) использует новые возможности, появившиеся в версии 5.0, а именно: возможность создания ActiveX элементов и использование нестандартных интерфейсов. В реализации компоненты на Visual Basic 5.0 отсутствуют функции таймера.

Определение и реализация объекта внешней компоненты

Определение и реализация объекта компоненты находятся в файле AddInObj.ctl. В реализации на Visual Basic объект компоненты является ActiveX элементом, поэтому все необходимые интерфейсы невидимы для пользователя и все действия выполняются визуально. Например, для связи ActiveX элемента и страницы свойств используется свойство элемента PropertyPages, интерфейс ISpecifyPropertyPages объект реализует автоматически. Необходимо только добавить строки:

для реализации объектом соответствующих интерфейсов. Определения интерфейсов будут автоматически взяты из библиотеки типов.

Следует обратить внимание на свойства InvisibleAtRuntime: True — это позволяет реализовать невидимый элемент, и Name: AddInObj — это вторая часть ProgID объекта компоненты. Первая часть ProgID — это свойство Name проекта, поэтому проект называется AddIn для автоматического создания объекта при использовании функции ЗагрузитьВнешнююКомпоненту.

Определение и реализация страницы свойств внешней компоненты

Определение и реализация страницы свойств находятся в файле PropPage.pag. Они достаточно просты и понятны без дополнительных объяснений. Можно лишь отметить, что в отличие от компонент, написанных на Visual C++ и Borland Delphi, обмен данными происходит не через дополнительный интерфейс, а через глобальные переменные, определенные в файле AddInMod.bas.

Создание собственной компоненты

При разработке собственной компоненты можно использовать шаблон из данной методики или начать разработку компоненты «с нуля». В последнем случае необходимо:

  1. Выбрать из меню File | NewProject.
  2. Выбрать ActiveX Control.
  3. Внести оператор Implements в текст файла ActiveX элемента.

После этого названия интерфейсов будут доступны в списке объектов файла, а названия методов интерфейсов можно выбрать из списка функций.

При необходимости добавить страницу свойств в проект:

  1. Выбрать из меню Project| Add Property Page.
  2. Установить свойство ActiveX элемента PropertyPages на созданную страницу.

Компонента SAMPLE2

Этот пример в Visual Basic (Enterprise Edition) использует возможности создания Active Document и использования нестандартных интерфейсов.

Определение и реализация объекта внешней компоненты

Определение и реализация объекта компоненты находятся в файле AddInDoc.dob. В реализации на Visual Basic внешняя компонента и Активный документ реализованы одним объектом, поэтому в этот файл добавлены строки:

для реализации объектом соответствующих интерфейсов. Определения интерфейсов будут автоматически взяты из библиотеки типов. Страница свойств в этом примере не используется.

ProgID COM-объекта в этом примере складывается из двух частей: названия проекта и названия Активного документа, поэтому при создании окна 1С:Предприятия передается «AddIn.AddInDoc».

Создание собственной компоненты

При разработке собственной компоненты можно использовать шаблон из данной методики или начать разработку компоненты «с нуля». В последнем случае необходимо:

  1. Выбрать из меню File | NewProject.
  2. Выбрать ActiveX Document Dll.
  3. Внести оператор Implements в текст файла ActiveX Document.

Visual Basic .NET

Пример в Visual Basic .NET использует возможности взаимодействия технологии .NET с COM (так называемый COM Interop). В реализации компоненты на Visual Basic .NET отсутствуют функции таймера.

Определение и реализация объекта внешней компоненты

Определение и реализация объекта компоненты находятся в файле AddInObj.vb. В реализации на Visual Basic .NET объект компоненты является COM-классом, реализующим интерфейсы внешней компоненты IInitDone и ILanguageExtender. Для определения этих интерфейсов в проекте присутствует ссылка на библиотеку типов (type library) AddInLib – по этой ссылке строится соответствующая Interop.AddInLib.dll, необходимая для взаимодействия с COM. В целом код объекта по сравнению с реализацией в Visual Basic 6.0 практически не изменен, за исключением следующих моментов:

  • некоторые типы VB 6.0 заменены на соответствующие типы .NET (например Integer заменен на Long и Variant на Object);
  • методы интерфейсов объявлены как Overridable Overloads, соответствие методам интерфейсов задается конструкцией Implements;
  • после обнуления ссылок на объекты 1С:Предприятия выполняется процедура сборки «мусора» GC.Collect() и ожидание завершения этой процедуры GC.WaitForPendingFinalizers().

В среде Visual Basic .NET отсутствует поддержка создания страницы свойств, поэтому реализация страницы свойств отсутствует. Для включения/выключения объекта используется флажок КомпонентаВключена формы обработки ПримерРаботыСКомпонентой.

Включение стандартных Win32-ресурсов в проект Visual Basic .NET может выполняться только при компиляции проекта в командной строке (ключ /win32res), поэтому в поставку настоящего продукта включена готовая внешняя компонента с уже добавленной строкой с ID 100.

Создание собственной компоненты

При разработке собственной компоненты можно использовать шаблон из данной методики или начать разработку компоненты «с нуля». В последнем случае необходимо:

  1. Зарегистрировать входящую в поставку библиотеку типов AddIn.tlb с помощью утилиты regtlib: regtlib addin.tlb. Утилита regtlib входит в состав Internet Explorer и различных сред разработки.
  2. В Visual Basic .NET выбрать из меню пункт File | New | Project.
  3. Из раздела Visual Basic Projects выбрать Empty Project. после создания изменить тип проекта (output type) на Class Library и пространство имен (root namespace) на AddIn.
  4. В раздел проекта References добавить ссылку на библиотеку типов V7 AddIn 1.0 Type Library (эта библиотека находится в списке библиотек на закладке COM).
  5. Из контекстного меню проекта выбрать Add | Add New Item… и в появившемся диалоге выбрать COM Class. Название файла соответствует названию класса и, таким образом, вместе с пространством имен формирует ProgId.
  6. Внести в код созданного класса операторы Implements для необходимых интерфейсов и соответствующие этим интерфейсам определения и реализации методов.

Borland Delphi


Общая часть компонент


Определение интерфейсов 1С:Предприятия

Все интерфейсы 1С:Предприятия определены в модуле AddInLib.pas. Этот модуль импортируется директивой uses в модулях, использующих эти определения.

Определение и реализация объекта внешней компоненты

В реализации используются функции LoadProperties и SaveProperties, в которые вынесены загрузка и сохранение параметров объекта компоненты; функция TermString, упрощающая реализацию расширения встроенного языка; и функции GetNParam и PutNParam, использующиеся в реализации методов CallAsProc и CallAsFunc.

Компонента SAMPLE

Пример в Borland Delphi написан на стандартном Object Pascal и не использует никаких специальных свойств и библиотек.

Определение и реализация объекта внешней компоненты

И определение, и реализация объекта находятся в модуле AddInObj. Для привязки к странице свойств используется интерфейс ISpecifyPropertyPages и метод этого интерфейса GetPages. Для связи со страницей свойств и обмена данными используется интерфейс IPropertyLink. Главная деталь, на которую необходимо обратить внимание — создание «фабрики» объектов TComObjectFactory:

ComServer.SetServerName(‘AddIn’); TComObjectFactory.Create(ComServer,TAddInObject, CLSID_AddInObject, ‘AddIn’,’V7 AddIn 1.0′,ciSingleInstance);

Наименование сервера ComServer образует первую часть ProgID объекта. Так как 1С:Предприятие при создании объекта функцией ЗагрузитьВнешнююКомпоненту использует ProgID вида «AddIn. «, то имени сервера должна быть присвоена строка «AddIn». Далее, в Delphi отсутствует доступ к таблице строк в ресурсах создаваемого COM-сервера, поэтому необходимо использовать имя создаваемой библиотеки в качестве второй части ProgID. Поскольку компонента компилируется в библиотеку с именем AddIn.dll, то в параметр ClassID передается строка «AddIn». Все вышеперечисленное относится лишь к использованию функции ЗагрузитьВнешнююКомпоненту, так как функция ПодключитьВнешнююКомпоненту получает ProgID как параметр.

Определение и реализация страницы свойств внешней компоненты

Определение и реализация страницы свойств располагаются в модуле PropPage.pas и форме PropPage.dfm. Класс TAddInPropPage унаследован от стандартного класса TPropertyPage и использует переопределение стандартных функций UpdatePropertyPage (вызывается при открытии страницы свойств) и UpdateObject (вызывается при нажатии кнопки «Применить» или «ОК»).

Создание собственной компоненты

При разработке собственной компоненты можно использовать шаблон из данной методики или начать разработку компоненты «с нуля». В последнем случае необходимо:

  1. Выбрать из меню File | New.
  2. В закладке ActiveX выбрать ActiveX Library.
  3. В свойствах проекта на закладке Linker выбрать опцию Generate Object files.

Специфическая для Borland Delphi деталь, относящаяся к проекту: при разработке компоненты в свойствах проекта на закладке Linker необходимо выбирать опцию Generate Object files. Это свойство требуется для правильной работы страницы свойств (если это свойство не установлено, 1С:Предприятие после завершения работы может остаться работать в фоновом режиме).

При необходимости добавить в проект страницу свойств:

  1. Выбрать из меню File | New.
  2. В закладке ActiveX выбрать Property Page.

Файл, аналогичный AddInObj, Delphi не создает, поэтому определение и реализацию объекта разработчику нужно написать самому.

Отличие в реализации для Delphi 4.0

При работе с объектами, унаследованными от TAutoObject, необходимо использовать TAutoObjectFactory, что в свою очередь требует использования в проекте библиотеки типов (Type Library). Однако ее подключение усложнило бы проект, поэтому TAddInObject унаследован от TComObject.

Для корректной работы страницы свойств в Delphi 4.0 требуется, чтобы объекты, чьи свойства отображаются на странице, имели интерфейс IDispatch (при наследовании от TAutoObject это требование выполнялось автоматически). Поэтому TAddInObject реализует также IDispatch, но методы IDispatch не реализованы.

Компонента SAMPLE2

Этот пример в Borland Delphi также написан на стандартном Object Pascal и не использует никаких специальных свойств и библиотек.

Определение и реализация объекта внешней компоненты

И определение, и реализация объекта находятся в модуле AddInVid. Страница свойств в этом примере не используется. Главная деталь, на которую необходимо обратить внимание — создание «фабрики» объектов TComObjectFactory:

При этом в регистрационную базу данных системы(Registry) заносится ProgID «AddIn.AddInVideo». Для создания объекта при загрузке внешней компоненты необходимо, чтобы строка с ID 100 содержала вторую часть ProgID созадваемого объекта. Для этого в проект директивой <$R AddInStr.RES>включен ресурсный файл AddInStr, содержащий строку AddInVideo и скомпилированный из AddInStr.rc компилятором ресурсов rc.exe.

При создании дополнительного окна в качестве Активного документа передается документ, реализованный в файле AddInDoc.pas. При успешном создании окна в параметре cntr находится указатель на интерфейс IDispatch, что позволяет управлять созданным документом.

Определение и реализация Активного документа

Определение и реализация Активного документа находятся в модуле AddInDoc. Этот модуль и соответствующая ему форма создаются средой при создании документа. Одновременно создается библиотека типов, содержащая описание интерфейсов документа. Для редактирования свойств документа рекомендуется пользоваться именно библиотекой типов, так как в этом случае все необходимые определения и реализации методов генерируются средой автоматически. В форму документа включен элемент TMediaControl, доступный в закладке System панели элементов управления.

Использование библиотеки типов (Type Library)

Библиотека типов создается средой при создании Активного документа. Состав библиотеки можно редактировать, выбрав пункт меню View|Type Library. В примере к библиотеке добавлены два метода Play и SetFileName.

Создание собственной компоненты

При разработке собственной компоненты можно использовать шаблон из данной методики или начать разработку компоненты «с нуля». В последнем случае необходимо:

  1. Выбрать из меню File | New.
  2. В закладке ActiveX выбрать ActiveX Library.
  3. В свойствах проекта на закладке Linker выбрать опцию Generate Object files.

Специфическая для Borland Delphi деталь, относящаяся к проекту: при разработке компоненты в свойствах проекта на закладке Linker необходимо выбирать опцию Generate Object files. Это свойство требуется для правильной работы страницы свойств (если это свойство не установлено, 1С:Предприятие после завершения работы может остаться работать в фоновом режиме).

При необходимости добавить в проект Активный документ:

  1. Выбрать из меню File | New.
  2. В закладке ActiveX выбрать ActiveForm.

Файл AddInVid создан с использованием входящего в поставку шаблона.

Шаблоны

Шаблоны практически аналогичны примерам SAMPLE за исключением функциональности: оставлен только скелетный код и все необходимые детали реализаций компонент для удобства использования при разработке других компонент. Шаблоны работают согласно настоящему описанию и могут быть использованы при разработке компонент «с нуля». Расположение файлов шаблонов на дискете см. Структура каталогов.

Рекомендации по построению компоненты

При построении компоненты желательно следовать следующим рекомендациям:

  • компонента должна быть InProc COM—сервером (DLL, OCX) для ускорения работы. Построение EXE — сервера проще в стадии отладки, но скорость и устойчивость работы ниже, чем у InProc сервера;
  • если в разработке используется шаблон компоненты, то необходимо:
  • изменять имена, использованные в шаблоне (например, «AddInExtension»);
  • не наследовать классы от классов шаблона, а переписывать их;
  • если в компоненте используется флаг включения компоненты, то по умолчанию компоненту следует выключать. Тогда компоненту легко отключить — достаточно стереть соответствующие записи в регистрационной базе данных системы (Registry);
  • использовать только латиницу в названиях ProgID объектов.
  • некоторые комбинации стилей окна могут быть несовместимы со средой 1С:Предприятие в силу ограничений Windows, поэтому при создании нестандартных окон необходимо тщательно тестировать их работу.

Глава 3. Введение в COM

Эта часть описывает основы COM и не является полным руководством по COM (ActiveX) и OLE технологиям. Для более глубокого изучения COM Вам следует обратиться к документации по COM и OLE.

Интерфейсы в COM

Центральным понятием в COM является понятие «интерфейс». Под интерфейсом понимается некоторое множество функций, организованное по определенному стандарту. Стандарт COM определяет таблицу функций интерфейса, называемую vtable. Эта таблица имеет фиксированную структуру и включает в себя указатели на функции данного интерфейса, что позволяет вызывать функции интерфейса по ссылке на интерфейс.

В стандарте COM определен один интерфейс, называемый IUnknown, от которого наследуются все остальные COM-интерфейсы (т.е. все интерфейсы содержат функции IUnknown). В IUnknown входят три функции:

  • AddRef — увеличивает счетчик ссылок объекта на 1;
  • Release — уменьшает счетчик ссылок объекта на 1;
  • QueryInterface — запрашивает интерфейс у COM-объекта.

В COM используется большое количество различных интерфейсов, построенных по единому стандарту COM, с различными наборами функций. Каждому интерфейсу присвоен уникальный номер: GUID.

GUID (Globally Unique Identifier) — 16-байтное число, создаваемое по специальному алгоритму. Этот алгоритм гарантирует уникальность числа «в пространстве Вселенной за время ее существования». Обычно это число записывается в виде
<89abcdef-1234-5678-9abc-def012345678>.

Уникальный номер интерфейса называют IID (Interface Identifier) для отличия от других идентификаторов.

Объекты COM

Каждый COM—объект реализует один или несколько интерфейсов для выполнения различных задач и обязательный интерфейс IUnknown. Для создания объекта и получения указателя на один из интерфейсов используются функции Win32: CoCreateInstanceEx, CoCreateInstanceFromFile, CoGetClassObject и т.д. Одним из параметров функций является CLSID (Class Identifier) — это GUID, используемый при создании объекта. При создании объекта система использует информацию, хранящуюся в регистрационной базе данных системы (Registry).

Эта информация организована следующим образом:

  • под ключом HKEY_CLASSES_ROOT лежит ключ, описывающий ProgID (Programmatic Identifier) объекта. ProgID — это текстовая строка, например: Excel.Application. Под ключом ProgID находится ключ CLSID, значением которого является GUID объекта. Таким образом, ProgID — это строка, представляющая удобную для восприятия ссылку на CLSID. Преобразование ProgID в CLSID выполняется Win32 функцией CLSIDFromProgID;
  • под ключом HKEY_CLASSES_ROOT\CLSID находится ключ с именем CLSID для объекта. Под этим ключом находятся ключи, описывающие создание объекта: InProcServer32 — объект создается из DLL, LocalServer32 — объект создается из приложения, ProgID— обратная ссылка на ProgID и т.д.

Другим параметром функций при создании объекта передается
IID — идентификатор необходимого интерфейса. Функции, создающие объект, возвращают указатель на запрошенный интерфейс. Указатель на этот интерфейс может быть использован для получения другого интерфейса вызовом QueryInterface.

Каждый объект поддерживает счетчик ссылок других объектов на себя. Этот счетчик изменяется вызовами AddRef и Release интерфейсов объекта. Если после очередного вызова Release счетчик ссылок достигает нуля, это означает, что ссылки на данный объект отсутствуют и он уничтожается. QueryInterface увеличивает счетчик ссылок автоматически.

OLE Automation

Технология OLE Automation основывается на одном из наиболее известных и часто используемых в OLE интерфейсов — интерфейсе IDispatch. Этот интерфейс позволяет читать и писать свойства OLE Automation объекта и вызывать его функции с произвольным списком параметров. OLE Automation объектом можно назвать любой OLE объект, реализующий IDispatch. Для вызова функции объекта необходимо определить ее номер, затем вызывать метод Invoke интерфейса IDispatch и ей в качестве параметров передать номер вызываемой функции и массив ее параметров. Следует отличать функции OLE Automation объекта от функций интерфейсов (в частности, IDispatch) — интерфейс имеет жесткий неизменяемый список функций, а OLE Automation объект — произвольных список свойств и функций. Наиболее широко этот интерфейс используется в языке Visual Basic, где определен тип Object — в действительности это указатель на IDispatch.

В IDispatch входят следующие функции:

  • GetTypeInfo, GetTypeInfoCount — функции для работы с информацией о типах (за дополнительной информацией об этих функциях и работе с типами обращайтесь к рекомендованной литературе);
  • GetIDsOfNames — позволяет получить номер функции объекта по ее имени;
  • Invoke — вызов необходимой функции по номеру.

При передаче параметров функции используется структура VARIANT. Эта структура представляет собой объединение различных типов данных и может содержать практически любое значение, используемое на практике.

Элементы ActiveX со старыми версиями Delphi

Я тестирую не визуальный элемент управления ActiveX на основе зарегистрированного .ocx который я импортирую в Delphi с помощью предоставленного мастера.

Затем я просто помещаю сгенерированный компонент в основную форму нового приложения VCL.

В старых версиях Delphi (D5 и D2007), когда я запускаю приложение, это поднимает AV во время инициализации компонента.

с Delphi 2009: никаких проблем, приложение запускается гладко.

Известны усовершенствования управления ActiveX в последних версиях Delphi, которые может объяснить эту разницу?

Могу ли я заподозрить ошибку в элементе управления ActiveX, или я могу рассмотреть происхождение проблема из старых версий Delphi?

Мне нужно использовать этот компонент (если тесты ОК) в D2007. Считаете ли вы возможным устранить проблему AV в D2007, изменив файл .tlb, созданный D2007 (например, попытавшись использовать созданный D2009).

PS: элемент управления ActiveX не назван, потому что мой вопрос — это общий вопрос о Delphi и ActiveX, а не о конкретном элементе управления ActiveX.

Изменить:
С D2007 ошибка (нарушение доступа) появляется во время Application.CreateForm(TForm1, Form1);
и более конкретно, когда создается Olecontrol:

Насколько я помню, были значительные улучшения для импорта ActiveX/TLB в Delphi 2009 (связанные с поддержкой Unicode) — это может объяснить это.

В моем личном опыте Delphi 7 и Delphi 2007 неоднократно не импортировали некоторые библиотеки типов Windows 7 (различные новые интерфейсы для работы с новой панелью задач), но Delphi 2009 удалось без проблем.

Как для использования Delphi 2009 сгенерированного файла в более ранних версиях — остерегайтесь проблем Unicode. Плюс это не поможет, если дефект находится в RTL. Попробуйте сделать оболочку ActiveX в Delphi 2009 и использовать ее в Delphi 2007 — это должно работать.

Извините, что вылезаете так поздно после битвы (по прошествии 5 лет), но я потратил столько времени на этот точный вопрос, что я думал, что должен поделиться тем, что я видел, и тем, что я сделал решить его: 2 машины (win7 64/win 8.1) тот же самый delphi 7 (тот же самый вариант сборки), тот же activeX (MapX, чтобы назвать его) с идентичными .lic файлами, содержащими ключ, состоящий из 59 символов:

тот же импорт, производящий 2 немного разных TLB.

Тот, который работает: (на win 8.1), содержит это в процедуре TMap.InitControlData:

который переводится в 61 char ключ

TLB, который не работает (win 7 64), содержит это:

который преобразуется в ключ 2 char

Замена одной константы на другую и перекомпиляция компонента решила мою проблему. Я не знаю, что случилось. Я просто знаю, что Import/TLB создал плохой файл .pas, который можно скорректировать вручную.

Илон Маск рекомендует:  Описание доменных зон
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL