I know I\'ve seen an example somewhere of a hack to define a custom version of an existing VCL component, like TButton or TEdit, with the same class name and do something to
I guess what you're trying to remember is an "interposer class": inheriting a class giving the same name as the ancestor, by prefixing the ancestor's unit name. Since the class name is not changed, the dfm streaming mechanism is not disturbed. Would only affect the unit the class is re-declared in, unless it is put in a separate unit and that unit is included in the uses section after the base class'es. Obviously, you cannot have published properties in an interposed class.
type
TButton = class(stdctrls.TButton)
protected
procedure CreateParams(var Params: TCreateParams); override;
end;
TForm1 = class(TForm)
Button1: TButton;
[...]
private
In your form you can override the ReadState
method like so:
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;
There are likely numerous other ways to do this, but this is how I do it!
EDIT: Inspecting TReader.GetFieldClass(Instance: TObject; const ClassName: string)
suggests the hack that Mason recalls. The first line sets ClassType := Instance.ClassType
. So I suspect that by changing the declaration in the pas file from Button1: TButton
to Button1: MyUnit.TButton
will result in your button being created. Or perhaps the hack was to add MyUnit
to the uses clause right at the end so that your version of TButton is the one that is in scope. However, none of this sounds very practical.