3
votes

I have problem with Frames and inheritance in Delphi 7.

Suppose I define a Frame with visible=false (on design time). Now I embed this frame in some Form, and set visible=true on the embedded instance of the frame inside the form (also on design time).

Now suppose I want to initialize the embedded frame according to its visible property that was set in design time. The problem is that simple overriding the frame's constructor doesn't work, since inside the constructor I always get visible=false (I guess because the DFM properties hasn't been read yet). I also don't want to put the initialization code inside the Form unit, because this logic belongs only to the Frame.

What is your best rule of thumb for dealing with such cases?

Clarification Frame.Visible is only an example. The question is relevant for all other properties of the Frame, or its inner components, that are set in design time. For example let's say we are talking about the color of TEdit inside the Frame.

2

2 Answers

4
votes

You cannot write property-sensitive code in the constructor because, as you noted, the DFM properties have not necessarily been read yet when the constructor is running. Instead, override the Loaded method of your frame class and put your code there. It's called after the properties are loaded from the DFM.

Add noted, Visible won't work with that technique, but other properties will.

3
votes

The Visible property is ignored at design time. All informations about visible is only stored in the dfm of the Frame. Setting visible of a instance to true in a form using a frame won't be stored in the dfm of the form. Adding it manually does not help, it's ignored and removed on next saving.

After clarification it can be show with e.g. Property Color. Created a frame Color at designtime clBlack, in the Form used 2 Frames, Color set to clRed and clBlue.

unit Unit7;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TCallOnCreate=Procedure(Sender:TObject) of object;

  TFrame7 = class(TFrame)
    Button1: TButton;
    Procedure Loaded;override;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    Public Constructor Create(AOwner:TComponent);Override;
  end;

implementation
uses RTTI;
{$R *.dfm}

{ TFrame7 }

constructor TFrame7.Create(AOwner: TComponent);
var
   ToCall    : TCallOnCreate;
   Routine : TMethod;
begin

  inherited;
     Showmessage('Created ' + IntToStr(Color));


   Routine.Data := Pointer(AOwner);
   Routine.Code := AOwner.MethodAddress('InfoOnFrameCreate');
   if Assigned(Routine.Code) then
      begin
        ToCall:= TCallOnCreate(Routine);
        ToCall(Self);
      end;

end;

procedure TFrame7.Loaded;
begin
  inherited;
    Showmessage('Loaded ' + IntToStr(Color));
end;

end.

With the following Example how to implement code in then Form on which then Frame will be used.

unit Unit6;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Unit7;

type
  TForm6 = class(TForm)
    Frame71: TFrame7;
    Procedure InfoOnFrameCreate(Sender:TObject);
  private

    { Private-Deklarationen }
  public

    { Public-Deklarationen }
  end;

var
  Form6: TForm6;

implementation

{$R *.dfm}

{ TForm6 }

procedure TForm6.InfoOnFrameCreate(Sender: TObject);
begin
  Showmessage('Frame Created');
end;

end.