![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Создание компонента [D6, Win2k]
vladmk © (2005-12-01 10:16:00)Суть вопроса в следующем:
Имеется несколько компонентов(Компон1, Компон2 .. КомпонN) которые имеют общего предка и у них одинаковые названия у public и published методов и свойств, но разная их реализация.
Вопрос: как создать компонент к которому в design-time и run-time можно подключать один из компонентов (Компон1, Компон2 .. КомпонN) и работать с их методами и свойствами.
Заранее благодарен всем ответившим.
jack128 (2005-12-10 16:13:00) [1]ну во первых, это не обработчик события, а поле. а во вторых те нужно сделать примерно так:
ItttConnection = interface(IUnknown)
{ Getters&Setters }
function GetOnRead: TConnectionReadEvent;
procedure SetOnRead(const Value: TConnectionReadEvent);
property OnRead : TConnectionReadEvent read GetOnRead write SetOnRead;
procedure Run;
procedure Stop;
procedure SendString(s : string);
end;
а уже в классах, реализующих этот интерфейс объявлять поле..
FH (2005-12-10 14:52:00) [2]Ну, я пишу ему:
ItttConnection = interface(IUnknown)
OnRead : TConnectionReadEvent;
procedure Run;
procedure Stop;
procedure SendString(s : string);
end;
А он мне:
Field declarations not allowed in interface type
jack128 (2005-12-09 20:45:00) [3]FH (09.12.05 19:26) [12]
А как же быть с обработчиками событий?
а что обработчики событий?? Это же просто методы. А в чем проблема??
Чапаев (2005-12-09 20:18:00) [4]
> не может быть переменных, только процедуры и функции
Неверно. Ещё могут быть свойства.
FH (2005-12-09 19:26:00) [5]прочитал в справке, что в описании интерфейса не может быть переменных, только процедуры и функции. А как же быть с обработчиками событий?
jack128 (2005-12-03 19:41:00) [6]Например в этом коде, если ты уничтожишь сначала MyIdIdServerVar, а потом SomeComp, то в SomeComp.Destroy получишь AV. Чтобы его избежать, нужно перед уничтожением MyIdIdServerVar обнилить свойство MyServer.
FH (2005-12-03 17:28:00) [7]спасибо
А что там насчет глюков?
Это должно работать?
jack128 (2005-12-03 17:19:00) [8]IMyServer = interface
['{4CD6D36D-B404-4513-B6FA-21931B2F3F88}']
end;
TSomeComp = class(TComponent)
private
FMyServer: IMyServer;
published
property MyServer: IMyServer read FMyServer write FMyServer;
end;
var
SomeComp: TSomeComp;
begin
...
SomeComp.MyServer := MyIdUDPServerVar;
...
SomeComp.MyServer := MyIdIdServerVar;
..
...
end;
FH (2005-12-03 16:48:00) [9]Это примерно понятно, у меня они все будут наследниками TComponent, с IUnknown заморачиваться не буду.
Сперва описываю интерфейс IMyServer, у него будет несколько процедур и событий. Потом переписываю мой первый компонент, как class(TIdUDPServer, IMyServer), у него все методы должны совпадать с тем, ч то я написал в IMyServer. А дальше? Компонент, в котором я смогу в runtime поменять TMyIdUDPServer на TMyIdIdServer?
jack128 (2005-12-03 16:35:00) [10]Ну например:
Интерфейс
ISchemeItemControl = interface(IUnknown)
['{73861986-6815-46F1-8CBF-538AC822C42E}']
property SchemeItem: TSchemeItem read GetSchemeItem;
end;
Классы, реализующие этот интерфейс
TSchemeTransportNodeControl = class(TDesignControl, ISchemeItemControl) // Это наследник TComponent, поэтому реализовать IUnknown не нужно.
protected
{ ISchemeItemControl }
function GetSchemeItem: TSchemeItem;
end;
TSchemeWayConnector = class(TControlConnector, IUnknown, ISchemeItemControl) // Это "просто" класс, нужно реализовать IUnknown
protected
{ IUnknown }
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
{ ISchemeItemControl }
function GetSchemeItem: TSchemeItem;
end;
И еще, для нормальной работы с интерфейсами нужно четко представлять себе, что такое посчет ссылок и как он реалиован в Дельфи. Что то мне кажется, что тебе он не нужен, значит те придется его проигноривать. Иначе огребешь немерено глюков..
jack128 (2005-12-03 16:35:00) [11]Сорри, опечатка
ISchemeItemControl = interface(IUnknown)
['{73861986-6815-46F1-8CBF-538AC822C42E}']
function GetSchemeItem: TSchemeItem;
property SchemeItem: TSchemeItem read GetSchemeItem;
end;
FH (2005-12-03 16:11:00) [12]и как реализовать его во всех Comp1..CompN
Прошу прощения за дебильный вопрос, никогда не сталкивался с такими вещами. В справке нашел вот это
type
IMyInterface = interface
procedure P1;
procedure P2;
end;
TMyClass = class(TObject, IMyInterface)
FMyInterface: IMyInterface;
property MyInterface: IMyInterface read FMyInterface implements IMyInterface;
end;
var
MyClass: TMyClass;
MyInterface: IMyInterface;
begin
MyClass := TMyClass.Create;
MyClass.FMyInterface := ... // some object whose class implements IMyInterface
MyInterface := MyClass;
MyInterface.P1;
end;
но как-то слабо помогает.
у меня первый компонент - наследник TIdUdpServer, второй будет наследником TIdTCPServer...
FH (2005-12-03 15:45:00) [13]Спасибо, а как объявить интерфейс?
jack128 (2005-12-03 14:56:00) [14]FH (03.12.05 13:17) [2]
А если у них нет общего предка,
Объявить интерфейс, реализовать его во всех Comp1..CompN, а твоем новом компоненте описать published свойство интерфейсного типа..
FH (2005-12-03 13:17:00) [15]А если у них нет общего предка, только одинаковые методы и свойства?
Юрий Зотов (2005-12-01 23:08:00) [16]Если компоненты 1..N и их общий предок выполнены правильно, то так:
type
TMyComp = class(...)
private
FCompRef: TОбщийПредок;
procedure SetCompRef(const Value: TОбщийПредок);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
published
property CompRef: TОбщийПредок read FCompRef write SetCompRef;
end;
procedure TMyComp.SetCompRef(const Value: TОбщийПредок);
begin
if FCompRef <> Value then
begin
if FCompRef <> nil then
RemoveFreeNotification(FCompRef);
FCompRef := Value;
if FCompRef <> nil then
FreeNotification(FCompRef)
end
end;
procedure TMyComp.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = FCompRef) then
FCompRef := nil
end;