Delphi TFrame Create/Destroy

18,791

Solution 1

You can't call Self.Free in those event handlers. When the event handler returns, the VCL code that executes next still uses a reference to an object that you just freed. And that's where the access violation comes from. If you had been running with FastMM in full debug mode then you would have been shown a helpful diagnostic message.

These frames will have to kill themselves in a more roundabout manner. Post a CM_RELEASE message to the frame asking it to call Free on the frame. You post the message, rather than sending it, so that all the in flight messages are processed first. You'll need to add a message handler to the frame to respond to the message.

Solution 2

You've got some of it.

The basic idea behind this sort of stuff.

add a private property to your mainform to hold the frame.

in the button click handler assuming you only want one at a time do

if assigned(fMyFrame) then
begin
  fMyFrame.Free;
  fMyFrame := nil;
end;
fMyFrame := TSomeFrame.Create(self);
fMyFrame.Parent := self;
fMyFrame.blah...

When you just want to get rid of it as opposed to replacing it

if assigned(fMyFrame) then
begin
  fMyFrame.Free;
  fMyFrame := nil;
end;

If you want your frame to raise another frame, repeat the above in there.

If you want the frame you raise in a frame to be a sibling, e.g. have the same Parent, then don't use Form1 var.

fMyNextFrame.Parent = self.Parent;

There's a huge number of ways you could improve on this once you get it working, it's a classic scenario for interfaces and or inheritance, but figure this bit out first.

mySomething := TMySomething.Create();

you can now do something with something. After you called free, it's not can't, it's don't and don't let anything else either.

Don't do self.free, it's like playing with matches in barrel of petrol. It will hurt....

Share:
18,791
Alex P.
Author by

Alex P.

Updated on June 05, 2022

Comments

  • Alex P.
    Alex P. almost 2 years

    How to create (when I want to show it) and destroy (when I want to hide it) frames on the main TForm? Frames' align = alClient.

    I tried this:

    The form:

    unit main;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, uFrame1, uFrame2;
    
    type
      TFormMain = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        f1: TFrame1;
        f2: TFrame2;
      end;
    
    var
      FormMain: TFormMain;
    
    implementation
    
    {$R *.dfm}
    
    procedure TFormMain.FormCreate(Sender: TObject);
    begin
      f1 := TFrame1.Create(Self);
      f1.Parent := Self;
    end;
    
    end.
    

    First frame:

    unit uFrame1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
    
    type
      TFrame1 = class(TFrame)
        btn1: TButton;
        procedure btn1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    implementation
    
    {$R *.dfm}
    
    uses main, uFrame2;
    
    procedure TFrame1.btn1Click(Sender: TObject);
    begin
      Self.Free;
      FormMain.f2 := TFrame2.Create(FormMain);
      FormMain.f2.Parent := FormMain;
    end;
    
    end.
    

    Second frame:

    unit uFrame2;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
    
    type
      TFrame2 = class(TFrame)
        lbl1: TLabel;
        btn1: TButton;
        procedure btn1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    implementation
    
    {$R *.dfm}
    
    uses main, uFrame1;
    
    procedure TFrame2.btn1Click(Sender: TObject);
    begin
      Self.Free;
      FormMain.f1 := TFrame1.Create(FormMain);
      FormMain.f1.Parent := FormMain;
    end;
    
    end.
    

    but it crashes with access vialataions when I click button on FrameStart or Frame1 (TForm FormCreate works fine i.e. it creates and shows FrameStart).

    Delphi 7.

    With the first frame With the second frame