Передача объекта в качестве ссылки / одного места для объектов стиля - PullRequest
2 голосов
/ 25 марта 2011

Я получил довольно большое приложение, которое в настоящее время разрабатывается.Чтобы избавить меня от изменения всех кнопок в IDE / Object Inspector, я планирую просто выполнить несколько функций для основных объектов, таких как

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

и т. Д., И затем добавить их в формы onCreates по мере необходимости

StyleButton(Button1); whatever etc

Нет проблем с передачей объектов в таких параметрах, как этот.Он просто ссылается на первый объект, верно?

Он отлично работает, и я не могу думать ни о каких проблемах, но потому что это большое приложение, тысячи пользователей которого я просто хочу быть уверенным, что проблем не будет/ утечки памяти / проблемы с потреблением ресурсов.

Также будут происходить аналогичные действия с компонентами TAdvStringGrid и TEdit / TMemo.

Затем только 1 место может изменить эти настройки.

Или у кого-то есть идея получше?

Ответы [ 4 ]

6 голосов
/ 25 марта 2011

Это отличная идея. Функция изменит любой объект, который вы передадите ему.

Вы не передаете по ссылке. Вы передаете по значению. Значение, которое вы передаете , является ссылкой . «Передача по ссылке» означает, что вы будете использовать ключевые слова var или out, которые не подходят в данной ситуации.

4 голосов
/ 25 марта 2011

Ваша идея в порядке, как уже говорили другие ответчики. Просто хочу предложить решение, которое идет даже дальше, чем у Дэвида, и что-то, что вы, возможно, захотите рассмотреть, чтобы избежать необходимости добавлять много утверждений, таких как:

StyleButton(Button1);
StyleButton(Button2);

для каждой формы для каждого элемента управления, который вы хотели бы оформить;

Я бы предложил добавить один вызов метода, например, для события OnShow каждой формы:

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

TStyler может быть реализован в отдельном модуле, который выглядит следующим образом:

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.

Это решение в основном использует полиморфизм и реестр, который связывает классы управления с классами стайлера. Он также использует процедуры и функции класса, чтобы избежать необходимости что-либо создавать.

Обратите внимание, что в этом примере реестр реализован в виде двух списков, которые необходимо синхронизировать вручную, поскольку код предполагает, что при нахождении класса по индексу X будет найден стилист с тем же индексом в другом списке. Это, конечно, можно значительно улучшить, но здесь достаточно показать концепцию.

2 голосов
/ 25 марта 2011

Чтобы добавить к тому, что уже сказали Роб и РРУЗ, вы можете рассмотреть дополнительный помощник, используя параметры открытого массива:

procedure StyleButtons(const Buttons: array of TButton);
var
  i: Integer;
begin
  for i := low(Buttons) to high(Buttons) do
    StyleButton(Buttons[i]);
end;

Затем вы можете вызвать это как:

StyleButtons([btnOK, btnCancel, btnRelease64bitDelphi]);

который, на мой взгляд, более читабелен на сайте вызова, чем:

StyleButton(btnOK);
StyleButton(btnCancel);
StyleButton(btnRelease64bitDelphi);

Обратите внимание, что я передал открытый массив как параметр const, потому что он более эффективен при работе с массивами.Поскольку каждый элемент массива сам является ссылкой на кнопку, вы можете изменить фактическую кнопку.Const просто означает, что вы не можете изменить ссылку.

2 голосов
/ 25 марта 2011

Нет, нет проблемы (в вашем конкретном случае), передавая объект в качестве параметра

procedure StyleButton(AButton : TButton)

, когда вы делаете это, вы передаете адресную память (ссылку) и устанавливаете некоторые свойства ссылочного объектатак что тут проблем нет.

...