Замена класса компонента в delphi

Я знаю, что я видел пример где-то взломанный, чтобы определить пользовательскую версию существующего компонента VCL, например TButton или TEdit, с тем же именем класса и сделать что-то, чтобы сделать это, чтобы стример DFM создавал ваши вместо оригинала. К сожалению, я в ситуации, когда мне нужно это сделать, и я не могу найти рецензию. Кто-нибудь знает, где найти информацию о том, как это сделать?

Ответы

Ответ 1

В вашей форме вы можете переопределить метод ReadState следующим образом:

type
  TMyForm = class(TForm)
  protected
    procedure ReadState(Reader: TReader); override;
  end;

procedure TMyForm.ReadState(Reader: TReader);
begin
  Reader.OnFindComponentClass := FindComponentClass;
  inherited;
end;

procedure TMyForm.FindComponentClass(Reader: TReader; const ClassName: string;
  var ComponentClass: TComponentClass);
begin
  if ComponentClass=TButton then begin
    ComponentClass := TMySuperDuperButton;
  end else if ComponentClass=TEdit then begin
    ComponentClass := TMyTotallyAwesomeEdit;
  end;
end;

Вероятно, есть много других способов сделать это, но так я это делаю!

РЕДАКТИРОВАТЬ: Осмотр TReader.GetFieldClass(Instance: TObject; const ClassName: string) предполагает хак, который Мейсон вспоминает. Первая строка устанавливает ClassType := Instance.ClassType. Поэтому я подозреваю, что, изменив объявление в файле pas от Button1: TButton до Button1: MyUnit.TButton, вы создадите свою кнопку. Или, может быть, взлом заключался в том, чтобы добавить MyUnit в предложение uses прямо в конце, чтобы ваша версия TButton была той, которая находится в области видимости. Однако ничто из этого не кажется очень практичным.

Ответ 2

Я предполагаю, что вы пытаетесь вспомнить "класс интерполятора" : наследование класса с тем же именем, что и предок, префикс имени имени предка. Поскольку имя класса не изменяется, механизм потоковой передачи dfm не нарушается. Будет влиять только на объект, повторно объявленный классом, если только он не помещается в отдельный блок, и этот блок включен в раздел использования после базового класса. Очевидно, что вы не можете опубликовать свойства в промежуточном классе.

type
  TButton = class(stdctrls.TButton)
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    [...]
  private