2011-10-17 26 views
7

I sorta di fatto questa domanda alla fine di un altro post, ma sentire questo argomento ha bisogno di una domanda di un proprio ...modo corretto per creare stili per i componenti personalizzati

Se ho creato la mia componente con il proprio .style qual è la procedura corretta per unirla con gli stili definiti forniti con Delphi senza modificare i valori di default?

Posso incorporare uno stile predefinito in un componente che ho creato e che lo stile incorporato può ereditare la maggior parte dello stile del controllo genitore?

Sento che mi manca un collegamento che sto cercando di descrivere. La mia applicazione ha un TStyleBook che ha (per esempio) il "dark.style" caricato di default. Il mio componente ha il proprio file "MyComponent.style". Il TStyleBook può caricare "dark.style" o "MyComponent.style" ma non entrambi. E non sembra giusto che l'applicazione debba caricare "MyComponent.style" in quanto dovrebbe essere in qualche modo referenziato dal componente. Non rende il componente molto portabile se ogni volta che viene utilizzato in un'applicazione è necessario anche un file di stile separato.

Potrei modificare il mio "MyDark.style" e aggiungere MyComponent ma questo non sembra giusto in quanto crea un problema per tenerlo aggiornato con le modifiche apportate da Embarcadero.

Spero di averlo spiegato chiaramente. Martin

risposta

4

Grazie per Ray Konopka che ha tenuto un ottimo discorso su CodeRage e mi ha messo sulla strada giusta per rispondere a queste domande.

Domanda 1. È possibile incorporare uno stile predefinito in un componente?

Sì, si incorpora lo stile predefinito che si desidera distribuire con il componente in una risorsa di tipo RT_RCDATA. Poi basta includere quella risorsa nella fonte:

{$R *.res} 

Nota: È necessario rimuovere l'oggetto esterno (TLayout) se è stato creato nel layout editor prima di metterlo in res.

Quindi eseguire l'override del metodo GetStyleObject per caricare lo stile dalla risorsa.

function TLFButton.GetStyleObject: TControl; 
var 
    S: TResourceStream; 
    obj: TLayout; 
const 
    Style = 'LFButtonStyle'; 
begin 
    result := inherited GetStyleObject; 
    if FStyleLookup = 'cornerbuttonstyle' then 
    begin 
    if FindResource(HInstance, PChar(Style), RT_RCDATA) <> 0 then 
    begin 
     S := TResourceStream.Create(HInstance, Style, RT_RCDATA); 
     try 
     obj := TLayout(TStyleManager.LoadFromResource(HInstance, Style, RT_RCDATA)); 
     //obj := TLayout(CreateObjectFromStream(nil, S)); << XE2 version 
     Result.AddObject(obj); 
     Exit; 
     finally 
     S.Free; 
     end; 
    end; 
    end; 
end; 

Domanda 2: Come unirlo con uno stile predefinito.

Nel mio caso la base del mio componente era un TCornerButton. Ho tagliato il mio file .style in modo che avesse solo il codice per i bit extra che volevo. In questo caso un piccolo triangolo per indicare una goccia pulsante e una linea verso il basso per dividere il tasto:

object TLayout 
    Align = alRight 
    Position.Point = '(76,0)' 
    Locked = True 
    Width = 15.000000000000000000 
    Height = 24.000000000000000000 
    object TPath 
    StyleName = 'dropdownbutton' 
    Align = alCenter 
    Position.Point = '(4,9)' 
    Width = 8.000000000000000000 
    Height = 5.000000000000000000 
    HitTest = False 
    Fill.Color = claBlack 
    Stroke.Kind = bkNone 
    Data.Path = { 
     04000000000000000000000000000000010000000000803F0000000001000000 
     0000003F0000803F030000000000000000000000} 
    end 
    object TLine 
    StyleName = 'dropdownsplit' 
    Align = alLeft 
    Width = 1.000000000000000000 
    Height = 24.000000000000000000 
    HitTest = False 
    LineType = ltLeft 
    end 
end 

E ho messo che in una risorsa esattamente nello stesso modo.

Nel mio costruttore ho impostato la StyleLookup di essere il "cornerbuttonstyle"

constructor TLFButton.Create(AOwner: TComponent); 
begin 
    FStyleLookup := 'cornerbuttonstyle'; 
    FDropDownButton := false; 
    inherited; 
end; 

allora cambio la GetStyleObject in modo che caricato il nuovo materiale e ha aggiunto che per lo stile esistente.

function TLFButton.GetStyleObject: TControl; 
var 
    S: TResourceStream; 
    obj: TLayout; 
const 
    Style = 'LFButtonStyle'; 
begin 
    result := inherited GetStyleObject; 
    if FStyleLookup = 'cornerbuttonstyle' then 
    begin 
    if FindRCData(HInstance, Style) then 
    begin 
     S := TResourceStream.Create(HInstance, Style, RT_RCDATA); 
     try 
     obj := TLayout(CreateObjectFromStream(nil, S)); 
     Result.AddObject(obj); 
     Exit; 
     finally 
     S.Free; 
     end; 
    end; 
    end; 
end; 

Spero che questo aiuti qualcun altro e ho trovato tutto molto difficile ottenere informazioni su.

Martin

+1

Ho modificato il sopra per ottenere questo lavoro in XE3 – Martin

+0

Molto utile. Grazie! – Nix

2

Uso: MergeStyle ('MyComponent.Style', StyleBook1);

procedure MergeStyle(const aFilename: string; aStyleBook: TStyleBook); 
var 
    sb: TStyleBook; 
    I: Integer; 
begin 
    sb := TStyleBook.Create(nil); 
    try 
    sb.FileName := aFilename; 

    for I := 0 to sb.Root.ChildrenCount - 1 do 
     // Prevent duplicates 
     if aStyleBook.Root.FindStyleResource(sb.Root.Children[I].StyleName) = nil then 
     aStyleBook.Root.AddObject(sb.Root.Children[I].Clone(aStyleBook.Root)); 

    aStyleBook.UpdateScenes; 
    finally 
    sb.Free; 
    end; 
end; 
Problemi correlati