Статьи Королевства Дельфи


Часть 2. Доступ к объектам пакета.


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

Для того, чтобы новичкам было все ясно, следует немного углубиться в понятие интерфейса. Я полагаю, что вы знакомы с понятием виртуальной таблицы методов (VMT). Именно она является источником и тремя составными частями ООП . Для поддержки COM в Delphi был введен новый, особый тип interface, который позволяет "поименовать" куски виртуальной таблицы методов. Способ этого именования достаточно уникален - 16-байтовое число , которое присваивается каждому такому куску. Есть мнение, что оно статистически уникально . Синтаксис данного типа следующий type IMyInitialize = interface ['{7D501741-B419-11D5-915B-ED714AED3037}'] // то самое 16-битное число в строковом // представлении. Получается // в Delphi нажатием клавиш Ctrl+g. procedure InitializeForm(const ACaption: String); // а это процедура интерфейса. end; Помимо прочего компоненты Delphi содержат метод, позволяющий получать этот кусок виртуальной таблицы. Причем этих методов два.

  • Первый имеет название QueryInterface. Для любителей COM он является привычным, так как используется в оном вдоль и поперек.
  • Второй называется GetInterface.
Разница этими методами в том, что у QueryInterface нужно проверять результат на S_OK, а у GetInterface на Boolean .

Теперь давайте прикрутим к нашей системе интерфейсы и покажем, как с ними работать. Для этого создаем новый модуль (он достаточно короткий, и я здесь привожу его полностью) unit CommonInterfaces; interface type IMyInitialize = interface ['{7D501741-B419-11D5-915B-ED714AED3037}'] procedure InitializeForm(const ACaption: String); end; IMyHello = interface ['{7D501742-B419-11D5-915B-ED714AED3037}'] function ShowHello(AText: String): String; end; implementation end. Далее, внесем изменения в наш пакет, учитывающий поддержку интерфейсов 1. для дочерней формы: type TfrmChild = class(TForm, IMyInitialize, IMyHello) // так наследуются интерфейсы Private { описание методов IMyInitialize } procedure InitializeForm(const ACaption: String); { описание методов IMyHello } function ShowHello(AText: String): String; end; Что мы тут сделали? Мы сказали, что TfrmChild является наследником TForm, но помимо методов TForm VMT класа TfrmChild содержит еще два цельных куска, один из которых идентичен VMT IMyInitialize, а второй VMT IMyHello. 2. для диалоговой формы: type TfrmDialogFrom = class(TForm, IMyInitialize) BitBtn1: TBitBtn; BitBtn2: TBitBtn; Label1: TLabel; private { описание методов IMyInitialize } procedure InitializeForm(const ACaption: String); end; Реализация этих методов проста, ее можно смотреть в архиве (Step2).




Начало  Назад  Вперед