Работа с COM-объектами в Delphi: late-binding и подключение к событиям
В процессе разработки приложений на Delphi часто возникает необходимость работы с объектами, реализованными по технологии COM (Component Object Model). Одним из способов взаимодействия с такими объектами является использование late-binding, то есть связывания в момент выполнения программы. В этом случае не требуется заранее импортировать типовые библиотеки (TLB - Type Library), что может быть полезно, например, при работе с объектами, типовая библиотека которых отсутствует или не доступна.
Проблема
Рассмотрим код, который создает COM-объект с использованием функции CreateOleObject в Delphi:
var
myObject: OleVariant;
begin
myObject := CreateOleObject('SomeNamespace.SomeClass');
end;
Допустим, что данный COM-объект имеет события, например, OnClick. Вопрос заключается в том, как подключиться к этим событиям, не импортируя типовую библиотеку.
Решение проблемы
При работе с COM-объектами через late-binding, подключение к событиям требует выполнения нескольких шагов:
Создание нового класса, наследуемого от TInterfacedObject, который реализует интерфейс IDispatch.
Реализация функции Invoke в новом классе.
Получение контейнерного соединения (IConnectionPointContainer) и запрошенного соединения.
Подключение к соединению с помощью метода IConnectionPointContainer.FindConnectionPoint.
Вызов метода IConnectionPoint.Advise для регистрации обработчика событий.
Пример реализации
Ниже приведен пример кода, который демонстрирует, как можно реализовать подключение к событиям COM-объекта:
type
TMyDispatch = class(TInterfacedObject, IDispatch)
private
FDispatch: TDispatch;
function GetIDsOfNames(const GUID: TGUID; const Names: PAnsiChar; const NumNames, LCID: Integer; var NamesUsed: Integer): HResult; stdcall;
function GetTypeInfoCount(Out Count: Integer): HResult; stdcall;
function GetTypeInfo(const Index: Integer; var LCID: Integer): Pointer; stdcall;
function Invoke(const DispatchID: DISPID; const Name: PAnsiChar; const LCID, lcid: Integer; var Locals, Formats, Args, PVarResult, PExcepInfo, PCallSvc, CalleePropPos: Pointer): HResult; stdcall;
public
constructor Create(ADispatch: TDispatch); override;
destructor Destroy; override;
end;
constructor TMyDispatch.Create(ADispatch: TDispatch);
begin
inherited Create(ADispatch);
FDispatch := ADispatch;
end;
destructor TMyDispatch.Destroy;
begin
FDispatch := nil;
inherited Destroy;
end;
function TMyDispatch.GetIDsOfNames(const GUID: TGUID; const Names: PAnsiChar; const NumNames, LCID: Integer; var NamesUsed: Integer): HResult;
begin
Result := FDispatch.GetIDsOfNames(GUID, Names, NumNames, LCID, NamesUsed);
end;
function TMyDispatch.GetTypeInfoCount(Out Count: Integer): HResult;
begin
Result := FDispatch.GetTypeInfoCount(Count);
end;
function TMyDispatch.GetTypeInfo(const Index: Integer; var LCID: Integer): Pointer;
begin
Result := FDispatch.GetTypeInfo(Index, LCID);
end;
function TMyDispatch.Invoke(const DispatchID: DISPID; const Name: PAnsiChar; const LCID, lcid: Integer; var Locals, Formats, Args, PVarResult, PExcepInfo, PCallSvc, CalleePropPos: Pointer): HResult;
begin
// Реализация функции Invoke, которая будет обрабатывать вызовы методов
// и событий COM-объекта. Здесь должен быть код для подключения к событиям.
Result := FDispatch.Invoke(DispatchID, Name, LCID, LCID, Locals, Formats, Args, PVarResult, PExcepInfo, PCallSvc, CalleePropPos);
end;
// Дополнительный код для работы с контейнером соединений и подключения к событиям
Дополнительные материалы
Для более глубокого понимания работы с COM-объектами, late-binding и событий в Delphi, рекомендуется ознакомиться с дополнительными материалами, такими как:
Описание контекста: Работа с COM-объектами в Delphi через late-binding и подключение к событиям без использования импорта типовой библиотеки.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.