Search code examples
delphioopvcldelphi-2006

How to insert code to a class without modify the original class?


I have created a routine to make the corners of Delphi visual controls to be rounded.

Now what I want to do is ensure that every visual object like TMemo, TEdit and TPanel comes rounded without having to call the function for everyone of them at the form creation.

How do I make an extension of the create method for each of these classes from my code (form unit), so they keep the name of the class and the normal behavior on other units?

procedure RoundCornersOf(Control: TWinControl) ;
var
   R: TRect;
   Rgn: HRGN;
begin
   with Control do
   begin
     R := ClientRect;
     rgn := CreateRoundRectRgn(R.Left, R.Top, R.Right, R.Bottom, 20, 20) ;
     Perform(EM_GETRECT, 0, lParam(@r)) ;
     InflateRect(r, - 4, - 4) ;
     Perform(EM_SETRECTNP, 0, lParam(@r)) ;
     SetWindowRgn(Handle, rgn, True) ;
     Invalidate;
   end;
end;

Solution

  • There exist constructs or hacks to modify classes at runtime, see for example Replacing a component class in delphi and Changing component class at run-time on demand. However, as fas as I understand, you have to declare separate types of all occurring control types.

    An alternative is to transverse over all controls after the form's creation, using the Controls and ControlCount properties:

      public
        procedure AfterConstruction; override;
      end;
    
    procedure ModifyControls(Window: TWinControl);
    var
      I: Integer;
    begin
      for I := 0 to Window.ControlCount - 1 do
        if Window.Controls[I] is TWinControl then
        begin
          ModifyControls(TWinControl(Window.Controls[I]));
          RoundCorners(TWinControl(Window.Controls[I]));
        end;
    end;
    
    procedure TForm1.AfterConstruction;
    begin
      inherited AfterConstruction;
      ModifyControls(Self);
    end;
    

    But beware of control recreation, which happens more then you would think. For instance, changing the BorderStyle property of an Edit results in recreating the Edit which undoes your modification. Redo the modification in those cases, providing you could track them all.