2016-07-24 11 views
11

Mam TComponent, który kontroluje niektóre interfejsy. Ten komponent został zaprojektowany do obsługi zarówno VCL, jak i Firemonkey za pomocą warunkowych. Takie czynniki warunkujące instruują mój komponent, czy akceptować kontrolę VCL czy kontrolę FMX. Obecnie oczekuje się, że to warunkowe jest zdefiniowane na poziomie aplikacji, aby instruować komponent w czasie wykonywania, czy ma on zarządzać kontrolką VCL czy FMX.Jak sprawić, by pojedynczy komponent obsługiwał zarówno VCL, jak i FMX?

Chciałbym opublikować mój składnik do IDE z obsługą zarówno VCL i FMX, dzieląc tę ​​samą jednostkę z warunkami. Jednak w zależności od tego, czy VCL lub FMX są aktualnie używane, nazwy/typy właściwości różnią się.

Na przykład ...

type 
    TMyComponent = class(TComponent) 
    published 
    {$IFDEF USE_FMX} 
    property TabControl: TTabControl read FTabControl write SetTabControl; 
    {$ENDIF} 
    {$IFDEF USE_VCL} 
    property PageControl: TPageControl read FPageControl write SetPageControl; 
    {$ENDIF} 
    end; 

Moim celem jest, aby móc upuścić tego komponentu non-wizualny na albo VCL lub formy FMX i automatycznie wyświetlać odpowiednie właściwości specyficzne ramowe w Inspektorze obiektów .

Jak mam rejestrować ten komponent, który współużytkuje zarówno kod VCL, jak i FMX za pośrednictwem warunków warunkowych?

+5

Chciałbym użyć dwóch składników odziedziczonych po klasie bazowej zawierającej cały kod, który można udostępnić. –

+0

@SirRufo To świetny projekt, dziękuję. –

+0

Możesz podzielić się jeszcze większym kodem, jeśli wewnętrznie zawijasz formanty. –

Odpowiedz

4

Zdecydowanie odradzam przed, tworząc właściwości specyficzne dla platformy, jak próbujesz to zrobić. Proponuję zamiast tworzenia oddzielnych komponentów adaptera specyficzne dla platformy, a następnie można przypisać jedną z tych kart do głównego składnika w miarę potrzeb, na przykład:

unit MyComponentUI; 

interface 

uses 
    Classes; 

type 
    TMyComponentUIControl = class(TComponent) 
    public 
    procedure DoSomethingWithControl; virtual; abstract; 
    ... 
    end; 

implementation 

... 

end. 

unit MyComponentFmxUI; 

uses 
    MyComponentUI, 
    FMX.TabControl; 

type 
    TMyComponentUIControl_FMXTabControl = class(TMyComponentUIControl) 
    private 
    FTabControl: TTabControl; 
    procedure SetTabControl(Value: TTabControl); 
    protected 
    procedure Notification(AComponent: TComponent; Operation: TOperation); override; 
    public 
    procedure DoSomethingWithControl; override; 
    published 
    property TabControl: TTabControl read FTabControl write SetTabControl; 
    end; 

procedure Register; 

implementation 

uses 
    FMX.Controls; 

procedure TMyComponentUIControl_FMXTabControl.DoSomethingWithControl; 
begin 
    if FTabControl <> nil then 
    begin 
    ... 
    end; 
end; 

procedure TMyComponentUIControl_FMXTabControl.SetTabControl(Value: TTabControl); 
begin 
    if FTabControl <> Value then 
    begin 
    if FTabControl <> nil then FTabControl.RemoveFreeNotification(Self); 
    FTabControl := Value; 
    if FTabControl <> nil then FTabControl.FreeNotification(Self); 
    end; 
end; 

procedure TMyComponentUIControl_FMXTabControl.Notification(AComponent: TComponent; Operation: TOperation); 
begin 
    inherited; 
    if (Operation = opRemove) and (AComponent = FTabControl) then 
    FTabControl := nil; 
end; 

procedure Register; 
begin 
    GroupDescendantsWith(TMyComponentUIControl_FMXTabControl, TControl); 
    RegisterComponents('My Component', [TMyComponentUIControl_FMXTabControl]); 
end; 

end. 

unit MyComponentVclUI; 

interface 

uses 
    MyComponentUI, 
    Vcl.ComCtrls; 

type 
    TMyComponentUIControl_VCLPageControl = class(TMyComponentUIControl) 
    private 
    FPageControl: TPageControl; 
    procedue SetPageControl(Value: TPageControl); 
    protected 
    procedure Notification(AComponent: TComponent; Operation: TOperation); override; 
    public 
    procedure DoSomethingWithControl; override; 
    published 
    property PageControl: TPageControl read FPageControl write SetPageControl; 
    end; 

procedure Register; 

implementation 

uses 
    Vcl.Controls; 

procedure TMyComponentUIControl_VCLPageControl.DoSomethingWithControl; 
begin 
    if FPageControl <> nil then 
    begin 
    ... 
    end; 
end; 

procedure TMyComponentUIControl_VCLPageControl.SetPageControl(Value: TPageControl); 
begin 
    if FPageControl <> Value then 
    begin 
    if FPageControl <> nil then FPageControl.RemoveFreeNotification(Self); 
    FPageControl := Value; 
    if FPageControl <> nil then FPageControl.FreeNotification(Self); 
    end; 
end; 

procedure TMyComponentUIControl_VCLPageControl.Notification(AComponent: TComponent; Operation: TOperation); 
begin 
    inherited; 
    if (Operation = opRemove) and (AComponent = FPageControl) then 
    FPageControl := nil; 
end; 

procedure Register; 
begin 
    GroupDescendantsWith(TMyComponentUIControl_VCLPageControl, TControl); 
    RegisterComponents('My Component', [TMyComponentUIControl_VCLPageControl]); 
end; 

end. 

unit MyComponent; 

interface 

uses 
    Classes, 
    MyComponentUI; 

type 
    TMyComponent = class(TComponent) 
    private 
    FUIControl: TMyComponentUIControl; 
    procedure SetUIControl(Value: TMyComponentUIControl); 
    protected 
    procedure Notification(AComponent: TComponent; Operation: TOperation); override; 
    public 
    procedure DoSomething; 
    published 
    property UIControl: TMyComponentUIControl read FUIControl write SetUIControl; 
    end; 

procedure Register; 

implementation 

procedure TMyComponent.DoSomething; 
begin 
    ... 
    if FUIControl <> nil then 
    FUIControl.DoSomethingWithControl; 
    ... 
end; 

procedure TMyComponent.SetUIControl(Value: TMyComponentUIControl); 
begin 
    if FUIControl <> Value then 
    begin 
    if FUIControl <> nil then FUIControl.RemoveFreeNotification(Self); 
    FUIControl := Value; 
    if FUIControl <> nil then FUIControl.FreeNotification(Self); 
    end; 
end; 

procedure TMyComponent.Notification(AComponent: TComponent; Operation: TOperation); 
begin 
    inherited; 
    if (Operation = opRemove) and (AComponent = FUIControl) then 
    FUIControl := nil; 
end; 

procedure Register; 
begin 
    RegisterComponents('My Component', [TMyComponent]); 
end; 

end. 

Korzystając GroupDescendentsWith() do grupy każdy zasilacz albo FMX.Controls.TControl lub Vcl.Controls.TControl, pozwala to IDE do filtrowania komponentów w czasie projektowania w oparciu o ramy użyta w projekcie dominującej:

na formularzu VCL Designer, widać tylko TMyComponentUIControl_VCLPageControl dostępny w Palecie narzędzi.

W programie do projektowania formularzy FMX w Palecie narzędzi można zobaczyć tylko TMyComponentUIControl_FMXTabControl.

Na projektancie modułów danych nie zobaczysz żadnej karty, chyba że ustawisz właściwość TDataModule.ClassGroup na grupę VCL lub FMX. Następnie zobaczysz odpowiedni adapter dostępny w Palecie narzędzi.

Powiązane problemy