为自定义组件创建样式的正确方法 [英] Correct way to create styles for custom components

查看:110
本文介绍了为自定义组件创建样式的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在另一篇文章的结尾问了这个问题,但是觉得这个话题需要一个自己的问题...

I sort of asked this question at the end of another post but feel this topic needs a question of its own...

如果我创建了自己的组件,拥有自己的.style,如何将其与Delphi提供的已定义样式合并而不修改默认值的正确过程是什么?

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?

我觉得我缺少了一个努力描述的链接。
我的应用程序有一个TStyleBook,例如,默认情况下已加载 dark.style。
我的组件有其自己的 MyComponent.style文件。
TStyleBook可以加载 dark.style或 MyComponent.style,但不能两者都加载。
而且应用程序需要加载 MyComponent.style似乎并不正确,因为组件应该以某种方式引用它。如果每次在应用程序中使用该组件时,都还需要一个单独的样式文件,它不会使组件变得非常可移植。

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.

我可以编辑自己的 MyDark.style,然后向其中添加MyComponent,但这似乎也不对,因为它会产生一个问题,以使其与Embarcadero所做的更改保持最新。

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.

我希望我已经清楚地解释了这一点。
Martin

I hope I have explained this clearly. Martin

推荐答案

感谢Ray Konopka对CodeRage进行了精彩的演讲,使我走上了正确的道路这些问题。

Thanks for Ray Konopka who gave a great talk on CodeRage and put me on the right track to answer these questions.

问题1.我可以将默认样式嵌入到组件中吗?

Question 1. Can I embed a default style into a component?

是的,您嵌入了您希望随组件一起分发到RT_RCDATA类型的资源中的默认样式。然后只需将该资源添加到源中即可。

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}

注意:如果在布局编辑器中创建了外部对象(TLayout),则需要先删除外部对象(TLayout)。

Note: You need to remove the outside object (TLayout) if you created it in the layout editor before putting it into the res.

然后重写GetStyleObject方法以从资源中加载样式。

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;

问题2:如何将其与默认样式合并。

Question 2: How to merge it with a default style.

在我的情况下,组件的基础是TCornerButton。我整理了我的.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.

在我的构造函数中,我将StyleLookup设置为 cornerbuttonstyle。

In my constructor I set the StyleLookup to be the "cornerbuttonstyle"

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

然后我更改GetStyleObject,以便它加载新内容并将其添加到现有样式中。 / p>

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.

马丁

这篇关于为自定义组件创建样式的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆