The right way to create styles for custom components

I kind of asked this question at the end of another post, but I think that this topic needs its own ...

If I created my own component with my own .style, then what is the correct procedure for merging with the specified styles supplied with Delphi without changing the default values?

Is it possible to embed the default style in the component that I created, and can this inline style inherit most of the style of its parent control?

I feel that I am missing a link that I am struggling to describe. My application has TStyleBook, which has (for example) loaded by default "dark.style". My component has its own file "MyComponent.style". TStyleBook can load either "dark.style" or "MyComponent.style", but not both. And it does not seem correct that the application should load "MyComponent.style", as this should be mentioned by the component in some way. This does not make the component very portable, if each time it is used in the application, a separate style file is required.

I could edit my own โ€œMyDark.styleโ€ and add MyComponent to it, but that doesn't seem right, as it creates a problem to keep it up to date with the changes made by Embarcadero.

I hope I have clearly explained this. Martin

+7
source share
2 answers

Thanks for Ray Konopka, who shared excellently with CodeRage and put me on the right track to answer these questions.

Question 1. Is it possible to embed the default style in a component?

Yes, you insert the default style that you want to distribute with the component into a resource of type RT_RCDATA. Then just include this resource in the source:

{$R *.res} 

Note: you need to delete the external object (TLayout) if you created it in the layout editor before placing it in res.

Then override the GetStyleObject method to load the style from the resource.

 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: How to combine it with the default style.

In my case, the base of my component was TCornerButton. I truncated my .style file so that it just had the code for the extra bits that I wanted. In this case, a small triangle to indicate the drop-down list button and a line to separate the button:

 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 

And I put it in the resource in exactly the same way.

In my constructor, I set StyleLookup as the "cornerbutton style"

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

Then I modify GetStyleObject so that it loads new material and adds it to the existing style.

 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; 

I hope this helps someone else, and I found it all very difficult to get information.

Martin

+4
source

Usage: 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; 
+2
source

All Articles