Как создать различные типы фреймов?

Я снова здесь с кадрами. У меня есть эта основная форма:

Это всего лишь простая форма, созданная для того, чтобы понять использование фреймов. С помощью двух кнопок в верхней части формы я хотел бы открыть эти два кадра:

Frame1

и Frame2

Вот код простой код первого кадра:

unit AppFrame1;

interface

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

type
  TFrame1 = class(TFrame)
    lblFrame1: TLabel;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

implementation

{$R *.dfm}

end.

и вот код второго кадра:

unit AppFrame2;

interface

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

type
  TFrame2 = class(TFrame)
    lblFrame2: TLabel;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

implementation

{$R *.dfm}

end.

Так что ничего особенного в двух кадрах. чтобы открыть фреймы из главной формы, я создал такой интерфейс:

unit FramesManager;

interface

uses
  Vcl.Forms, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Controls;

type

  TFrameClass = class(TFrame)

  end;


  IFrameManager = interface
  ['{A00E0D1B-3438-4DC4-9794-702E8302B567}']
    procedure CreateGenericFrame(AParentPanel: TPanel; AFrameClass: TFrameClass);
    procedure DestroyGenericFrame();
  end;

  TFrameManager = class(TInterfacedObject, IFrameManager)
  private
    FGenericFrame: TFrameClass;
    procedure CreateGenericFrame(AParentPanel: TPanel; AFrameClass: TFrameClass);
    procedure DestroyGenericFrame();
  public
    property Frame: TFrameClass read FGenericFrame write FGenericFrame;
  end;

implementation

{ TFrameManagement }

procedure TFrameManager.CreateGenericFrame(AParentPanel: TPanel;
  AFrameClass: TFrameClass);
begin
  FGenericFrame := AFrameClass.Create(AParentPanel);
  FGenericFrame.Parent := AParentPanel;
  FGenericFrame.Align := alClient;
end;

procedure TFrameManager.DestroyGenericFrame;
begin
  FGenericFrame.Free;
end;

end.

На данный момент я намерен использовать интерфейс для создания двух фреймов, но я не могу понять, как решить эту задачу. Мой основной код формы это:

unit Main;

interface

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

type
  TfrmMain = class(TForm)
    pnlCommands: TPanel;
    pnlFrames: TPanel;
    btnCrtFrame1: TButton;
    btnCrtFrame2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnCrtFrame1Click(Sender: TObject);
    procedure btnCrtFrame2Click(Sender: TObject);
  private
    FFrame: IFrameManager;
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}


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


procedure TfrmMain.btnCrtFrame1Click(Sender: TObject);
begin
  FFrame.CreateGenericFrame(pnlFrames, TFrame1);
end;

procedure TfrmMain.btnCrtFrame2Click(Sender: TObject);
begin
  FFrame.CreateGenericFrame(pnlFrames, TFrame2);
end;

end.

Когда я пытаюсь скомпилировать проект, я получаю следующие ошибки:

[dcc32 Error] Main.pas(41): E2010 Incompatible types: 'TFrameClass' and 'class of TFrame1'
[dcc32 Error] Main.pas(46): E2010 Incompatible types: 'TFrameClass' and 'class of TFrame2'

Поэтому я хотел бы понять, как создать два кадра из основного. Как я могу назначить правильный тип объекта для TFrameClass? Я думал о дженериках, но я не представляю, как реализовать этот вид интерфейса, чтобы открыть "универсальный" фрейм, который можно создать из основного, когда пользователь выберет его открыть.

Я надеюсь, что четко объяснил свою проблему, но я знаю, что это может показаться сложным для понимания.

1 ответ

Решение
type
    TFrameClass = class(TFrame)
    end;

Ваш TFrameClass декларация неверна. Прямо сейчас это объявлено как потомок TFrame, который является просто другим классом.

Что вам нужно, это ссылка на класс:

type
  TFrameClass = class of TFrame;

Потому что оба TFrame1 а также TFrame2 спуститься с TFrame, оба могут быть помещены в TFrameClass переменная.

Но я уверен, что это TFrameClass уже существует где-то в VCL, и в этом случае вам не нужно повторно объявлять этот тип.

Впоследствии тип FGenericFrame частное поле должно стать TFrame вместо TFrameClass,

(Кроме того, это не имеет ничего общего с Generics.)

Другие вопросы по тегам