3

我又带着相框来了。我有这个主要形式:

在此处输入图像描述

它只是为了理解框架的使用而创建的一个简单的表单。使用表单顶部的两个按钮,我想打开这两个框架:

框架1

在此处输入图像描述

和框架2

在此处输入图像描述

这是第一帧的简单代码:

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?我已经讨论过泛型,但我不知道如何实现这种接口以打开一个“通用”框架,当用户选择打开它时,可以从主框架中创建该框架。

我希望我已经清楚地解释了我的问题,但我知道理解起来似乎很复杂。

4

1 回答 1

5
type
    TFrameClass = class(TFrame)
    end;

你的TFrameClass声明是错误的。现在它被声明为 TFrame 的后代,它只是另一个类。

您需要的是类参考

type
  TFrameClass = class of TFrame;

因为 bothTFrame1TFrame2descend from TFrame,所以都可以放入一个TFrameClass变量中。

但我很确定这TFrameClass已经存在于 VCL 中的某个地方,在这种情况下你不必重新声明这种类型。

随后,FGenericFrame私有字段的类型需要变为TFrame而不是TFrameClass.

(此外,这与泛型无关。)

于 2016-09-28T09:33:52.323 回答