Search code examples
delphifiremonkey

Replace Call from one class to another?


I wonder if it is possible to replace the call from one class to another?

Example

TmyButton = class (TButton)
  procedure Click; override;
end;

initialization
  UnRegisterClass (TButton);
  RegisterClass (TButton);

But this code does not work properly, does anyone have any tips?

thank you

Please see the full example below, I'm calling at startup but unfortunately it has not worked correctly.

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.Controls.Presentation, FMX.StdCtrls;

type
 TmyButton = class( TButton )
  procedure Click; override;

 end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
 inherited;
 ShowMessage( 'Hello' );
end;

{ TmyButton }

procedure TmyButton.Click;
begin

 ShowMessage( 'myClass' );
 inherited;

end;

initialization
 UnRegisterClass( TButton );
 RegisterClass( TMyButton );

end.

Solution

  • You are going about this the wrong way. What you need is an interposer class instead. Meaning your custom class has the same name as the class you are trying to replace. The DFM system doesn't use full qualified class names, so at runtime, the streaming system will create instances of the last class that has been defined with a given class name.

    So, change this:

    type
     TmyButton = class( TButton )
      procedure Click; override;
     end;
    

    To this:

    type
     TButton = class( FMX.StdCtrls.TButton )
      procedure Click; override;
     end;
    

    And this:

    { TmyButton }
    
    procedure TmyButton.Click;
    begin
    
     ShowMessage( 'myClass' );
     inherited;
    
    end;
    

    To this:

    { TButton }
    
    procedure TButton.Click;
    begin
    
     ShowMessage( 'myClass' );
     inherited;
    
    end;
    

    And get rid of your initialization section completely.

    Here is the full code:

    unit Unit1;
    
    interface
    
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
      FMX.Controls.Presentation, FMX.StdCtrls;
    
    type
     TButton = class( FMX.StdCtrls.TButton )
      procedure Click; override;
    
     end;
    
    type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.fmx}
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
     inherited;
     ShowMessage( 'Hello' );
    end;
    
    { TButton }
    
    procedure TButton.Click;
    begin
    
     ShowMessage( 'myClass' );
     inherited;
    
    end;
    
    end.