I sort of asked this question at the end of another post but feel this topic needs a question of its own...
If I have created my own component with its own .style what is the correct procedure to merge that with the defined styles supplied with Delphi without modifying the defaults?
Can I embed a default style into a component I have created and can that embedded 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 a TStyleBook that has (for example) the "dark.style" loaded by default. My component has its own "MyComponent.style" file. The TStyleBook can load either "dark.style" or "MyComponent.style" but not both. And it does not seem right that the application needs to load "MyComponent.style" as this should be somehow referenced by the component. It does not make the component very portable if every time its used in an application a separate style file is needed also.
I could edit my own "MyDark.style" and add MyComponent into it but this does not seem right either as it creates an issue to keep it up to date with changes made by Embarcadero.
I hope I have explaine开发者_StackOverflowd this clearly. Martin
Thanks for Ray Konopka who gave a great talk on CodeRage and put me on the right track to answer these questions.
Question 1. Can I embed a default style into a component?
Yes, you embed the default style you want to distribute with the component into a resource of type RT_RCDATA. Then simply include that resource into the source:
{$R *.res}
Note: You need to remove the outside object (TLayout) if you created it in the layout editor before putting it into the 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 merge it with a default style.
In my case the base of my component was a TCornerButton. I trimmed down my .style file so that it just had the code for the extra bits I wanted. In this case a small triangle to indicate a drop down button and a line to split 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 that into a resource in exactly the same way.
In my constructor I set the StyleLookup to be the "cornerbuttonstyle"
constructor TLFButton.Create(AOwner: TComponent);
begin
FStyleLookup := 'cornerbuttonstyle';
FDropDownButton := false;
inherited;
end;
I then change the GetStyleObject so that it loaded the new stuff and added 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 this all very hard to get information on.
Martin
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;
精彩评论