我在另一篇文章的末尾问了这个问题,但觉得这个话题需要一个问题...
如果我用自己的.style创建了我自己的组件,那么将它与Delphi提供的已定义样式合并而不修改默认值的正确程序是什么?
我可以在我创建的组件中嵌入默认样式吗?嵌入式样式是否可以继承其父控件的大部分样式?
我觉得我错过了一个我正在努力描述的链接。 我的应用程序有一个TStyleBook,默认情况下加载(例如)“dark.style”。 我的组件有自己的“MyComponent.style”文件。 TStyleBook可以加载“dark.style”或“MyComponent.style”,但不能同时加载两者。 并且应用程序需要加载“MyComponent.style”似乎不正确,因为组件应该以某种方式引用它。如果组件每次在应用程序中使用时都需要单独的样式文件,那么它不会使组件非常便携。
我可以编辑自己的“MyDark.style”并将MyComponent添加到其中但这似乎也不正确,因为它会产生一个问题,以使其与Embarcadero所做的更改保持同步。
我希望我已经清楚地解释了这一点。 马丁
答案 0 :(得分:4)
感谢Ray Konopka在CodeRage上发表了精彩演讲,并让我走上正确的轨道来回答这些问题。
问题1.我可以在组件中嵌入默认样式吗?
是的,您将要与组件一起分发的默认样式嵌入到RT_RCDATA类型的资源中。然后只需将该资源包含在源中:
{$R *.res}
注意:如果在布局编辑器中创建外部对象(TLayout)之前将其放入res中,则需要将其删除。
然后重写GetStyleObject方法以从资源加载样式。
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;
问题2:如何将其与默认样式合并。
在我的情况下,我的组件的基础是TCornerButton。我修剪了我的.style文件,以便它只有我想要的额外位的代码。在这种情况下,一个小三角形表示一个下拉按钮,一条线用于分割按钮:
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
我把它以完全相同的方式放入资源中。
在我的构造函数中,我将StyleLookup设置为“cornerbuttonstyle”
constructor TLFButton.Create(AOwner: TComponent);
begin
FStyleLookup := 'cornerbuttonstyle';
FDropDownButton := false;
inherited;
end;
然后我更改了GetStyleObject,以便加载新内容并将其添加到现有样式中。
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;
我希望这有助于其他人,我发现这一切都非常难以获取信息。
马丁
答案 1 :(得分:2)
用法: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;