Как создать различные типы фреймов?
Я снова здесь с кадрами. У меня есть эта основная форма:
Это всего лишь простая форма, созданная для того, чтобы понять использование фреймов. С помощью двух кнопок в верхней части формы я хотел бы открыть эти два кадра:
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.)