2011-10-17 3 views
7

je sorte de poser cette question à la fin d'un autre poste, mais sentir ce sujet a besoin d'une question de son propre ...manière correcte de créer des styles pour des composants personnalisés

Si j'ai créé mon propre composant avec son propre .style quelle est la procédure correcte pour fusionner cela avec les styles définis fournis avec Delphi sans modifier les valeurs par défaut? Puis-je intégrer un style par défaut dans un composant que j'ai créé et ce style intégré peut-il hériter de la plus grande partie du style de son contrôle parent? Je sens qu'il me manque un lien que j'ai du mal à décrire. Mon application a un TStyleBook qui a (par exemple) le "dark.style" chargé par défaut. Mon composant a son propre fichier "MyComponent.style". Le TStyleBook peut charger "dark.style" ou "MyComponent.style" mais pas les deux. Et il ne semble pas correct que l'application doit charger "MyComponent.style" car cela devrait être référencé en quelque sorte par le composant. Il ne rend pas le composant très portable si chaque fois qu'il est utilisé dans une application, un fichier de style séparé est également nécessaire.

Je pourrais éditer mon propre "MyDark.style" et y ajouter MyComponent mais cela ne semble pas correct non plus car il crée un problème pour le garder à jour avec les modifications apportées par Embarcadero.

J'espère avoir expliqué cela clairement. Martin

Répondre

4

Merci à Ray Konopka qui a donné une excellente conférence sur CodeRage et m'a mis sur la bonne voie pour répondre à ces questions.

Question 1. Puis-je incorporer un style par défaut dans un composant? Oui, vous incorporez le style par défaut que vous souhaitez distribuer avec le composant dans une ressource de type RT_RCDATA. Ensuite, il suffit d'inclure cette ressource dans la source:

{$R *.res} 

Note: Vous devez supprimer l'objet extérieur (TLayout) si vous avez créé dans l'éditeur de mise en page avant de le mettre dans les res.

Ensuite, remplacez la méthode GetStyleObject pour charger le style à partir de la ressource.

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; 

Question 2: Comment le fusionner avec un style par défaut.

Dans mon cas, la base de mon composant était un TCornerButton. J'ai coupé mon fichier .style afin qu'il ait juste le code pour les bits supplémentaires que je voulais. Dans ce cas, un petit triangle pour indiquer un bouton déroulant et une ligne de diviser le bouton:

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 

Et je mets cela en une ressource exactement de la même manière.

Dans mon constructeur, je mis la StyleLookup d'être le « cornerbuttonstyle »

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

je change alors le GetStyleObject pour qu'il charge les nouvelles choses et ajouté au style existant.J'espère que cela aidera quelqu'un d'autre et j'ai trouvé cela très difficile d'obtenir des informations sur.

Martin

+1

J'ai modifié ci-dessus pour obtenir ce travail dans XE3 – Martin

+0

très utile. Merci! – Nix

2

Utilisation: 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; 
Questions connexes