Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.06.25;
Скачать: CL | DM;

Вниз

Создание компонента   Найти похожие ветки 

 
vladmk   (2005-12-01 10:16) [0]

Суть вопроса в следующем:
Имеется несколько компонентов(Компон1, Компон2 .. КомпонN) которые имеют общего предка и у них одинаковые названия у public и published методов и свойств, но разная их реализация.
Вопрос: как создать компонент к которому в design-time и run-time можно  подключать один из компонентов (Компон1, Компон2 .. КомпонN) и работать с их методами и свойствами.
Заранее благодарен всем ответившим.


 
Юрий Зотов ©   (2005-12-01 23:08) [1]

Если компоненты 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;


 
FH   (2005-12-03 13:17) [2]

А если у них нет общего предка, только одинаковые методы и свойства?


 
jack128 ©   (2005-12-03 14:56) [3]

FH   (03.12.05 13:17) [2]
А если у них нет общего предка,

Объявить интерфейс, реализовать его  во всех Comp1..CompN, а твоем новом компоненте описать published свойство интерфейсного типа..


 
FH   (2005-12-03 15:45) [4]

Спасибо, а как объявить интерфейс?


 
FH   (2005-12-03 16:11) [5]

и как реализовать его во всех 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...


 
jack128 ©   (2005-12-03 16:35) [6]

Ну например:
Интерфейс
 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) [7]

Сорри, опечатка
ISchemeItemControl = interface(IUnknown)
["{73861986-6815-46F1-8CBF-538AC822C42E}"]
  function GetSchemeItem: TSchemeItem;
  property SchemeItem: TSchemeItem read GetSchemeItem;
end;


 
FH   (2005-12-03 16:48) [8]

Это примерно понятно, у меня они все будут наследниками TComponent, с IUnknown заморачиваться не буду.
Сперва описываю интерфейс IMyServer, у него будет несколько процедур и событий. Потом переписываю мой первый компонент, как class(TIdUDPServer, IMyServer), у него все методы должны совпадать с тем, ч то я написал в IMyServer. А дальше? Компонент, в котором я смогу в runtime поменять TMyIdUDPServer на TMyIdIdServer?


 
jack128 ©   (2005-12-03 17:19) [9]

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 17:28) [10]

спасибо
А что там насчет глюков?
Это должно работать?


 
jack128 ©   (2005-12-03 19:41) [11]

Например в этом коде, если ты уничтожишь сначала MyIdIdServerVar, а потом SomeComp, то в  SomeComp.Destroy получишь AV. Чтобы его избежать, нужно перед уничтожением MyIdIdServerVar обнилить свойство MyServer.


 
FH   (2005-12-09 19:26) [12]

прочитал в справке, что в описании интерфейса не может быть переменных, только процедуры и функции. А как же быть с обработчиками событий?


 
Чапаев ©   (2005-12-09 20:18) [13]


> не может быть переменных, только процедуры и функции

Неверно. Ещё могут быть свойства.


 
jack128 ©   (2005-12-09 20:45) [14]

FH   (09.12.05 19:26) [12]
А как же быть с обработчиками событий?

а что обработчики событий?? Это же просто методы.  А в чем проблема??


 
FH   (2005-12-10 14:52) [15]

Ну, я пишу ему:

 ItttConnection = interface(IUnknown)
   OnRead : TConnectionReadEvent;
   procedure Run;
   procedure Stop;
   procedure SendString(s : string);
 end;

А он мне:
Field declarations not allowed in interface type


 
jack128 ©   (2005-12-10 16:13) [16]

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

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;

а уже в классах, реализующих этот интерфейс объявлять поле..



Страницы: 1 вся ветка

Текущий архив: 2006.06.25;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.034 c
1-1148046577
Damager
2006-05-19 17:49
2006.06.25
Развертывание окна


9-1131552874
Med
2005-11-09 19:14
2006.06.25
как работает Sprite?


2-1149670549
Кирей
2006-06-07 12:55
2006.06.25
Как результаты запроса записать в *.xls файл


2-1149644505
Никос
2006-06-07 05:41
2006.06.25
Типы


15-1149152342
ПЛОВ
2006-06-01 12:59
2006.06.25
Как такое сделать то?