Интерфейсные формы


Когда я занялся реализацией интерфейсов из листинга 10.3, неожидан новозникли проблемы — моя система «зависала» при каждом вызове AddNotifiee(Self) из формы, реализующей IFrame. Хотя решение оказалось простым, мне пришлось в течение многих часов изобретать и проверять различные гипотезы. Чтобы вы лучше поняли суть происходившего, потребуется некоторая дополнительная информация.

Документация Delphi 3 достаточно четко объясняет, что каждый объект, реализующий какой-то интерфейс, должен также реализовать интерфейс IUnknown, в котором производятся подсчет ссылок и запросы поддерживаемых интерфейсов. Если компилятор встретит следующее объявление:

type IFoo = interface procedure Foo; end; TFoo = class (TObject, IFoo) procedure Foo; end;

procedure TFoo.Foo; begin end;

он пожалуется на наличие необъявленных идентификаторов QueryInterface, _AddRef и _Release. Вам придется явным образом реализовать IUnknown или создавать свой объект на базе TInterfaced, а не TObject. С другой стороны, следующий фрагмент не вызовет у компилятора никаких проблем:

type
TFoo = class (TForm, IFoo) procedure Foo; end; procedure TFoo.Foo; begin end;

Это означает, что фирма Borland реализовала IUnknown где-то в недрах VCL и у нас стало одной заботой меньше, не так ли?

Нет, не так. При передаче TForm в качестве интерфейсной ссылки VCL выдает ошибку защиты (GPF). Хотя класс TComponent и реализует методы IUnknown, это вряд ли поможет тем из нас, кто захочет воспользоваться интерфейсами в приложении. Вызовы IUnknown передаются FVCLComObject — указателю, значение которого задается лишь при вызове GetComObject для получения интерфейсной ссылки объекта. Более того, GetComObject задает значение FVCLComObject лишь в том случае, если вы использовали VCLCom в своем проекте. Если сделать это, GetComObject начинает жаловаться на то, что фабрика класса (class factory) не была зарегистрирована, и… на этом я прекратил свои исследования. Возможно, все это очень здорово, если вы собираетесь использовать COM-объекты совместно с другими приложениями, но совершенно не подходит, если нужно всего лишь добавить интерфейсы к формам.

Намного проще будет заглянуть в реализацию TInterfacedObject и включить в TForm простую, независимую реализацию IUnknown, а затем порождать формы от TInterfacedForm вместо TForm.



Содержание раздела