Delphi generic frame

628 views Asked by At

I'm still here with a questione about Delphi frames. I would like to create an application that use various type of frames in order to manage different database tables, so trying to understand how to do this kind of task I've create a simple Delphi Form:

unit main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls, Vcl.ExtCtrls, FramesManagement;

type
  TfrmMain = class(TForm)
    pnlCommands: TPanel;
    pnlFrames: TPanel;
    btnFrame1: TButton;
    btnFrame2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnFrame1Click(Sender: TObject);
    procedure btnFrame2Click(Sender: TObject);
  private
    FFrame: IFrameManagement;
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

uses Frame1, Frame2;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  FFrame := TFramemanagement.Create;
end;

procedure TfrmMain.btnFrame1Click(Sender: TObject);
begin
  FFrame.CreateGenericFrame(pnlFrames, TFrame(Frame1.TFra1));
end;

procedure TfrmMain.btnFrame2Click(Sender: TObject);
begin
  FFrame.CreateGenericFrame(pnlFrames, TFrame(Frame2.TFra2));
end;

end.

This form make use of an interface declared as following:

unit FramesManagement;

interface

uses
  Vcl.Forms, Vcl.StdCtrls, Vcl.ExtCtrls, Frame1, Frame2;

type

  IFrameManagement = interface
  ['{A00E0D1B-3438-4DC4-9794-702E8302B567}']
    procedure CreateGenericFrame(ParentPanel: TPanel; FrameName: TFrame);
  end;

  TFrameManagement = class(TInterfacedObject, IFrameManagement)
  private
    genericFrame: TFrame;
    procedure CreateGenericFrame(ParentPanel: TPanel; FrameName: TFrame);
  end;

implementation

procedure TFrameManagement.CreateGenericFrame(ParentPanel: TPanel;
  FrameName: TFrame);
begin
  genericFrame := FrameName.Create(ParentPanel);
  genericFrame.Parent := ParentPanel;
end;

And here there are the two frames.

Frame 1:

unit Frame1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls;

type
  TFra1 = class(TFrame)
    txtFrame1: TStaticText;
    txtFrameType: TStaticText;
    lblFrameType: TLabel;
  private

  public

  end;

implementation

{$R *.dfm}

end.

and Frame 2:

unit Frame2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls;

type
  TFra2 = class(TFrame)
    txtFrame2: TStaticText;
    txtFrameType: TStaticText;
    lblFrameType: TLabel;
  private

  public

  end;

implementation

{$R *.dfm}

end.

This is all the code, but When I run the application and I try to create the first or the second frame i receive an error like this:

enter image description here

I've thought the solution may be the use of generics but I don't know how to use them. Is my thought right or there is another way to reache this gol? Can Anyone help me?

1

There are 1 answers

0
David Heffernan On BEST ANSWER
procedure TFrameManagement.CreateGenericFrame(ParentPanel: TPanel; FrameName: TFrame);
begin
  genericFrame := FrameName.Create(ParentPanel);
  genericFrame.Parent := ParentPanel;
end;

Here FrameName is an instance and you are calling the constructor of that instance. You are not creating a new instance as you intend to do.

You need to use meta classes.

type
  TFrameClass = class of TFrame;

procedure TFrameManagement.CreateGenericFrame(ParentPanel: TPanel; FrameClass: TFrameClass);
begin
  genericFrame := FrameClass.Create(ParentPanel);
  genericFrame.Parent := ParentPanel;
end;

You can call this like so:

FFrame.CreateGenericFrame(pnlFrames, Frame2.TFra2);