Замена класса компонента в Delphi - PullRequest
14 голосов
/ 14 января 2011

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

Ответы [ 2 ]

19 голосов
/ 14 января 2011

В вашей форме вы можете переопределить метод 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 к предложению использования в конце, чтобы ваша версия TButton была той, которая находится в области видимости. Тем не менее, все это не кажется очень практичным.

11 голосов
/ 14 января 2011

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

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

  TForm1 = class(TForm)
    Button1: TButton;
    [...]
  private
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...