在参考中传递对象/一处样式对象 [英] Passing object in reference / one place to style objects

查看:77
本文介绍了在参考中传递对象/一处样式对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个很大的应用程序,当前正在对其进行样式设置。
为了避免更改IDE / Object Inspector中的所有按钮,我打算只对主要对象执行一些功能,例如

I got quite a large application which is currently being styled up. To save me changing all the buttons in the IDE/Object Inspector I am planning on just doing a few functions for the main objects like

procedure StyleButton(AButton : TButton)
begin
    AButton.Color := clGreen;
    AButton.Font.Style = [fsBold];
end;

etc等,然后根据需要将其添加到onCreates表单中

etc etc and then add that to the forms onCreates as needed

StyleButton(Button1); whatever etc

在这样的参数中传递对象没有问题。

There is no issue passing objects in params like this. It does just reference the first object right?

它工作正常,我想不出任何问题,但是因为这是一个大型应用程序,我只是成千上万的用户希望确保不会出现任何问题/内存泄漏/资源消耗问题。

It works fine and I can't think of any issues, but because this is a large application which thousands of users I just want to be sure there will be no issues/memory leaks/resource consumpution issues.

还将对TAdvStringGrid和TEdit / TMemo组件执行类似的操作。

Will also be doing similar things with TAdvStringGrid and TEdit/TMemo components.

然后只能在1个位置更改这些设置。

Then allows just 1 place to change these settings.

还是有人有更好的主意?

Or someone have a better idea?

推荐答案

您的想法很好,就像其他回答者已经说过的那样。只是想提出一个比David的解决方案更进一步的解决方案,您可能需要考虑一些事情,以避免不得不添加许多语句,例如:

Your idea is just fine, as the other answerers have already said. Just want to propose a solution that goes even further than David's and something you may want to consider in order to avoid having to add many statements like:

StyleButton(Button1);
StyleButton(Button2);

到您要设置样式的每个控件的每个表单;

to each and every form for each and every control you would like to style;

我建议对单个表单的OnShow事件添加一个方法调用:

What I would propose is to add a single method call to for example each form's OnShow event:

procedure TForm1.FormShow(Sender: TObject);
begin
  TStyler.StyleForm(Self);
end;

TStyler可以在单独的单元中实现,如下所示:

The TStyler could be implemented in a separate unit that looks like this:

interface

type
  TStyler = class;
  TStylerClass = class of TStyler;

  TStyler = class(TObject)
  public
    class procedure StyleForm(const aForm: TCustomForm);
    class procedure StyleControl(const aControl: TControl); virtual;
    class function GetStyler(const aControl: TControl): TStylerClass;
  end;

implementation

uses
  Contnrs;

type
  TButtonStyler = class(TStyler)
  public
    class procedure StyleControl(const aControl: TControl); override;
  end;

  TEditStyler = class(TStyler)
  public
    class procedure StyleControl(const aControl: TControl); override;
  end;

  TLabelStyler = class(TStyler)
  public
    class procedure StyleControl(const aControl: TControl); override;
  end;

var
  _Controls: TClassList;
  _Stylers: TClassList;

{ TStyler }

class function TStyler.GetStyler(const aControl: TControl): TStylerClass;
var
  idx: Integer;
begin
  Result := TStyler;
  idx := _Controls.IndexOf(aControl.ClassType);
  if idx > -1 then
    Result := TStylerClass(_Stylers[idx]);
end;

class procedure TStyler.StyleForm(const aForm: TCustomForm);

  procedure _StyleControl(const aControl: TControl);
  var
    i: Integer;
    StylerClass: TStylerClass;
  begin
    StylerClass := TStyler.GetStyler(aControl);
    StylerClass.StyleControl(aControl);
    if (aControl is TWinControl) then
      for i := 0 to TWinControl(aControl).ControlCount - 1 do
        _StyleControl(TWinControl(aControl).Controls[i]);
  end;

var
  i: Integer;
begin
  _StyleControl(aForm);
end;

class procedure TStyler.StyleControl(const aControl: TControl);
begin
// Do nothing. This is a catch all for all controls that do not need specific styling.
end;

{ TButtonStyler }

class procedure TButtonStyler.StyleControl(const aControl: TControl);
begin
  inherited;
  if aControl is TButton then
  begin
    TButton(aControl).Font.Color := clRed;
    TButton(aControl).Font.Style := [fsBold];
  end;
end;

{ TEditStyler }

class procedure TEditStyler.StyleControl(const aControl: TControl);
begin
  inherited;
  if aControl is TEdit then
  begin
    TEdit(aControl).Color := clGreen;
  end;
end;

{ TLabelStyler }

class procedure TLabelStyler.StyleControl(const aControl: TControl);
begin
  inherited;
  if aControl is TLabel then
  begin
    TLabel(aControl).Font.Color := clPurple;
    TLabel(aControl).Font.Style := [fsItalic];
  end;
end;

initialization
  _Controls := TClassList.Create;
  _Stylers := TClassList.Create;

  _Controls.Add(TButton);
  _Stylers.Add(TButtonStyler);

  _Controls.Add(TEdit);
  _Stylers.Add(TEditStyler);

  _Controls.Add(TLabel);
  _Stylers.Add(TLabelStyler);

finalization
  FreeAndNiL(_Controls);
  FreeAndNiL(_Stylers);
end.

此解决方案基本上采用了多态性和将控件类链接到样式器类的注册表。它也使用类过程和函数来避免实例化任何东西。

This solution basically employs polymorphism and a registry that links control classes to styler classes. It also uses class procedures and functions to avoid having to instantiate anything.

请注意,此示例中注册表是作为两个列表实现的,需要手动保持同步因为代码假定在索引X处找到一个类将在另一个列表的相同索引处找到样式器。当然,可以对它进行很大的改进,但是在这里足以说明这个概念。

Please note that the registry is implemented in this example as two lists that need to be kept in sync manually as the code assumes that finding a class at index X will find the styler at the same index in the other list. This can of course be improved upon very much, but is sufficient here to show the concept.

这篇关于在参考中传递对象/一处样式对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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