2011-10-17 15 views
7

tipo de hice esta pregunta al final de otro puesto de sentir este tema necesita una cuestión de su propia ...manera correcta para crear estilos personalizados para los componentes

Si he creado mi propio componente con su propio .style ¿cuál es el procedimiento correcto para fusionar eso con los estilos definidos suministrados con Delphi sin modificar los valores predeterminados?

¿Puedo incrustar un estilo predeterminado en un componente que he creado y puede ese estilo incrustado heredar la mayor parte del estilo de su control principal?

Siento que me falta un enlace que estoy luchando por describir. Mi aplicación tiene un TStyleBook que tiene (por ejemplo) el "dark.style" cargado por defecto. Mi componente tiene su propio archivo "MyComponent.style". El TStyleBook puede cargar "dark.style" o "MyComponent.style" pero no ambos. Y no parece correcto que la aplicación necesite cargar "MyComponent.style", ya que el componente debe hacer referencia de alguna manera a este. No hace que el componente sea muy portátil si cada vez que se usa en una aplicación también se necesita un archivo de estilo diferente.

Podría editar mi propio "MyDark.style" y agregar MyComponent en él, pero esto no parece correcto, ya que crea un problema para mantenerlo actualizado con los cambios realizados por Embarcadero.

Espero haber explicado esto claramente. Martin

Respuesta

4

Gracias por Ray Konopka que dieron una gran charla sobre CodeRage y me puso en el camino correcto para responder a estas preguntas.

Pregunta 1. ¿Puedo incrustar un estilo predeterminado en un componente?

Sí, inserta el estilo predeterminado que desea distribuir con el componente en un recurso de tipo RT_RCDATA. A continuación, basta con incluir este recurso en la fuente:

{$R *.res} 

Nota: Es necesario eliminar el objeto exterior (TLayout) si ha creado en el editor de diseño antes de ponerlo en la res.

Luego, anule el método GetStyleObject para cargar el estilo del recurso.

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; 

Pregunta 2: Cómo fusionarlo con un estilo predeterminado.

En mi caso, la base de mi componente era un TCornerButton. Recorté mi archivo .style para que solo tuviera el código para los bits adicionales que quería. En este caso, un pequeño triángulo para indicar una caída de botón y una línea hacia abajo para dividir el botón:

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 

Y me puso en un recurso que exactamente de la misma manera.

En mi constructor que establezca la StyleLookup para ser el "cornerbuttonstyle"

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

luego cambio el GetStyleObject para que cargue el nuevo material y ha añadido que el estilo existente.

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; 

Espero que esto ayude a otra persona y me pareció muy difícil obtener información sobre esto.

Martin

+1

He editado el anterior para conseguir este trabajo en XE3 – Martin

+0

muy útil. ¡Gracias! – 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; 
Cuestiones relacionadas