Delphi 如何将单元动态添加到帧';s使用条款?

Delphi 如何将单元动态添加到帧';s使用条款?,delphi,Delphi,假设我有一个主窗体。主窗体包含两个按钮(打开和关闭),单击每个按钮可创建一个以主窗体为父/所有者的框架。 框架包含3个按钮(添加、编辑和删除),示例代码如下: 帧代码: unit UntFrame; ... type TFmeMain = class(TFrame) procedure AddClick(Sender: TObject); procedure EditClick(Sender: TObject); procedure DeleteClick(S

假设我有一个主窗体。主窗体包含两个按钮(打开关闭),单击每个按钮可创建一个以主窗体为父/所有者的框架。 框架包含3个按钮(添加、编辑和删除),示例代码如下:

帧代码:

unit UntFrame;

...

  type
  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  private ...
  public ...
  end;

implementation

{$R *.dfm}

uses ...

procedure TFmeMain.AddClick(Sender: TObject);
begin
   AddBtnClick;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
   EditBtnClick;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
   DelBtnClick;
end;

end.
unit UntOpen;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add open');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit open');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete open');
end;
end.
unit UntClose;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add close');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit close');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete close');
end;
end.
框架使用的3种方法(AddBtnClickeditbtclickDelBtnClick)存在于两个不同的单元上,即UntOpen和UntClose,但根据所创建的框架,其操作方式有所不同。当单击打开按钮时,框架应使用UntOpen,UntoClose用于从主菜单单击关闭按钮时

打开代码:

unit UntFrame;

...

  type
  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  private ...
  public ...
  end;

implementation

{$R *.dfm}

uses ...

procedure TFmeMain.AddClick(Sender: TObject);
begin
   AddBtnClick;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
   EditBtnClick;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
   DelBtnClick;
end;

end.
unit UntOpen;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add open');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit open');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete open');
end;
end.
unit UntClose;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add close');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit close');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete close');
end;
end.
取消关闭代码:

unit UntFrame;

...

  type
  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  private ...
  public ...
  end;

implementation

{$R *.dfm}

uses ...

procedure TFmeMain.AddClick(Sender: TObject);
begin
   AddBtnClick;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
   EditBtnClick;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
   DelBtnClick;
end;

end.
unit UntOpen;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add open');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit open');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete open');
end;
end.
unit UntClose;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add close');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit close');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete close');
end;
end.
我想在每次创建框架的uses子句时动态地(如果可能的话)添加一个单元,以便单击框架的add、edit或delete按钮触发正确的方法(如果单击Open按钮,则从UntOpen调用方法;如果单击Close按钮,则从UNTOCLOSE调用方法)

还是有更有效的方法


谢谢。

您不能动态使用单位;无法在运行时操作uses子句。您似乎想更改单元列表,以便帧的代码(已调用
AddBtnClick
)将神奇地从一个单元或另一个单元中选择函数


德尔福不是那样工作的。如果你真的想要这样的东西,试试Python

Delphi单元是一种编译时结构。它们不能在运行时被操纵。在编译时,编译器会看到您对
AddBtnClick
的调用,然后根据您已经使用的单元解析-绑定-名称。以后不能重新绑定该名称

相反,您可以将参数传递给框架类构造函数。将按钮函数放入数据结构中,然后将这些对象传递给帧。(这也称为依赖项注入。)例如,您可以从以下抽象类开始:

type
  TButtonBehavior = class
    class procedure AddBtnClick; virtual; abstract;
    class procedure EditBtnClick; virtual; abstract;
    class procedure DelBtnClick; virtual; abstract;
  end;
然后,定义框架以接收该类的后代,并根据该值编写按钮处理程序:

type
  TButtonBehaviorClass = class of TButtonBehavior;

  TMainFrame = class(TFrame)
  private
    FBehavior: TButtonBehaviorClass;
  ...

constructor TMainFrame.Create(AOwner: TComponent; ABehavior: TButtonBehaviorClass);
begin
  inherited Create(AOwner);
  FBehavior := ABehavior;
end;

procedure TMainFrame.AddBtnClick(Sender: TObject);
begin
  FBehavior.AddBtnClick;
end;
接下来,为希望框架支持的每个行为集定义抽象类的后代。如果需要,可以在单独的单元中定义它们,但由于它们已经在单独的类中,因此不需要进一步的分离

type
  TOpenBehavior = class(TButtonBehavior)
    class procedure AddBtnClick; override;
    class procedure EditBtnClick; override;
    class procedure DelBtnClick; override;
  end;

  TCloseBehavior = class(TButtonBehavior)
    class procedure AddBtnClick; override;
    class procedure EditBtnClick; override;
    class procedure DelBtnClick; override;
  end;
最后,在创建框架的新实例时,将其中一个类传递给框架构造函数

Frame := TMainFrame.Create(Self, TOpenBehavior);

不能动态使用单位;无法在运行时操作uses子句。您似乎想更改单元列表,以便帧的代码(已调用
AddBtnClick
)将神奇地从一个单元或另一个单元中选择函数


德尔福不是那样工作的。如果你真的想要这样的东西,试试Python

Delphi单元是一种编译时结构。它们不能在运行时被操纵。在编译时,编译器会看到您对
AddBtnClick
的调用,然后根据您已经使用的单元解析-绑定-名称。以后不能重新绑定该名称

相反,您可以将参数传递给框架类构造函数。将按钮函数放入数据结构中,然后将这些对象传递给帧。(这也称为依赖项注入。)例如,您可以从以下抽象类开始:

type
  TButtonBehavior = class
    class procedure AddBtnClick; virtual; abstract;
    class procedure EditBtnClick; virtual; abstract;
    class procedure DelBtnClick; virtual; abstract;
  end;
然后,定义框架以接收该类的后代,并根据该值编写按钮处理程序:

type
  TButtonBehaviorClass = class of TButtonBehavior;

  TMainFrame = class(TFrame)
  private
    FBehavior: TButtonBehaviorClass;
  ...

constructor TMainFrame.Create(AOwner: TComponent; ABehavior: TButtonBehaviorClass);
begin
  inherited Create(AOwner);
  FBehavior := ABehavior;
end;

procedure TMainFrame.AddBtnClick(Sender: TObject);
begin
  FBehavior.AddBtnClick;
end;
接下来,为希望框架支持的每个行为集定义抽象类的后代。如果需要,可以在单独的单元中定义它们,但由于它们已经在单独的类中,因此不需要进一步的分离

type
  TOpenBehavior = class(TButtonBehavior)
    class procedure AddBtnClick; override;
    class procedure EditBtnClick; override;
    class procedure DelBtnClick; override;
  end;

  TCloseBehavior = class(TButtonBehavior)
    class procedure AddBtnClick; override;
    class procedure EditBtnClick; override;
    class procedure DelBtnClick; override;
  end;
最后,在创建框架的新实例时,将其中一个类传递给框架构造函数

Frame := TMainFrame.Create(Self, TOpenBehavior);

请尝试类似以下内容:

unit UntFrame;

...

type
  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  public
    OnAdd: procedure;
    OnEdit: procedure;
    OnDelete: procedure;
  end;

implementation

{$R *.dfm}

procedure TFmeMain.AddClick(Sender: TObject);
begin
  if Assigned(OnAdd) then OnAdd;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
  if Assigned(OnEdit) then OnEdit;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
  if Assigned(OnDelete) then OnDelete;
end;

end.


请尝试类似以下内容:

unit UntFrame;

...

type
  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  public
    OnAdd: procedure;
    OnEdit: procedure;
    OnDelete: procedure;
  end;

implementation

{$R *.dfm}

procedure TFmeMain.AddClick(Sender: TObject);
begin
  if Assigned(OnAdd) then OnAdd;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
  if Assigned(OnEdit) then OnEdit;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
  if Assigned(OnDelete) then OnDelete;
end;

end.


如果我是你,我会尝试以下解决方案:

unit UntFrame;

...

  type
  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  private ...
  public ...
  end;

implementation

{$R *.dfm}

uses ...

procedure TFmeMain.AddClick(Sender: TObject);
begin
   AddBtnClick;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
   EditBtnClick;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
   DelBtnClick;
end;

end.
unit UntOpen;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add open');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit open');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete open');
end;
end.
unit UntClose;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add close');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit close');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete close');
end;
end.
主框架:

unit UntFrame;

...

uses
  UntOpen, UntClose, ...;

type
  TSelectedPage = (spOpen, spClose);

  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  private 
    FSelectedPage: TSelectedPage;
    ...
  public ...
  end;

implementation

{$R *.dfm}

uses ...

procedure TFmeMain.AddClick(Sender: TObject);
begin
  case FSelectedPage of:
    spOpen: TUntOpen.AddBtnClick;
    spClose: TUntClose.AddBtnClick;
  end;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
  case FSelectedPage of:
    spOpen: TUntOpen.EditBtnClick;
    spClose: TUntClose.EditBtnClick;
  end;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
  case FSelectedPage of:
    spOpen: TUntOpen.DelBtnClick;
    spClose: TUntClose.DelBtnClick;
  end;
end;

end.
开放单元:

unit UntOpen;

...
type
  TUntOpen = class 
  public
    class procedure AddBtnClick;
    class procedure EditBtnClick;
    class procedure DelBtnClick;
  end;

implementation

class procedure TUntOpen.AddBtnClick;
begin
    ShowMessage('add open');
end;

class procedure TUntOpen.EditBtnClick;
begin
   ShowMessage('edit open');
end;

class procedure TUntOpen.DelBtnClick;
begin
   ShowMessage('delete open');
end;
end.
关闭单元:

unit UntClose;

...
type
  TUntClose = class 
  public
    class procedure AddBtnClick;
    class procedure EditBtnClick;
    class procedure DelBtnClick;
  end;

implementation

class procedure TUntClose.AddBtnClick;
begin
    ShowMessage('add close');
end;

class procedure TUntClose.EditBtnClick;
begin
   ShowMessage('edit close');
end;

class procedure TUntClose.DelBtnClick;
begin
   ShowMessage('delete close');
end;
end.

这是一种OOP方法来实现您想要实现的目标,在Delphi中是可能的。

如果我是您,我会尝试以下解决方案:

unit UntFrame;

...

  type
  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  private ...
  public ...
  end;

implementation

{$R *.dfm}

uses ...

procedure TFmeMain.AddClick(Sender: TObject);
begin
   AddBtnClick;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
   EditBtnClick;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
   DelBtnClick;
end;

end.
unit UntOpen;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add open');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit open');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete open');
end;
end.
unit UntClose;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add close');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit close');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete close');
end;
end.
主框架:

unit UntFrame;

...

uses
  UntOpen, UntClose, ...;

type
  TSelectedPage = (spOpen, spClose);

  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  private 
    FSelectedPage: TSelectedPage;
    ...
  public ...
  end;

implementation

{$R *.dfm}

uses ...

procedure TFmeMain.AddClick(Sender: TObject);
begin
  case FSelectedPage of:
    spOpen: TUntOpen.AddBtnClick;
    spClose: TUntClose.AddBtnClick;
  end;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
  case FSelectedPage of:
    spOpen: TUntOpen.EditBtnClick;
    spClose: TUntClose.EditBtnClick;
  end;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
  case FSelectedPage of:
    spOpen: TUntOpen.DelBtnClick;
    spClose: TUntClose.DelBtnClick;
  end;
end;

end.
开放单元:

unit UntOpen;

...
type
  TUntOpen = class 
  public
    class procedure AddBtnClick;
    class procedure EditBtnClick;
    class procedure DelBtnClick;
  end;

implementation

class procedure TUntOpen.AddBtnClick;
begin
    ShowMessage('add open');
end;

class procedure TUntOpen.EditBtnClick;
begin
   ShowMessage('edit open');
end;

class procedure TUntOpen.DelBtnClick;
begin
   ShowMessage('delete open');
end;
end.
关闭单元:

unit UntClose;

...
type
  TUntClose = class 
  public
    class procedure AddBtnClick;
    class procedure EditBtnClick;
    class procedure DelBtnClick;
  end;

implementation

class procedure TUntClose.AddBtnClick;
begin
    ShowMessage('add close');
end;

class procedure TUntClose.EditBtnClick;
begin
   ShowMessage('edit close');
end;

class procedure TUntClose.DelBtnClick;
begin
   ShowMessage('delete close');
end;
end.

这是一种OOP方法,可以实现您想要实现的目标,而且在Delphi中是可能的。

重新思考您的设计。这是一场维护噩梦,毫无意义。相反,使用单独的框架,并将逻辑放在它所属的位置。它不仅可以在设计器中正常工作,而且可以防止将来给您(以及任何其他必须尝试和维护您的代码的人)带来重大麻烦,这始终是一个好主意(除非您持有主要止痛药制造商的股票)。不相关,但请考虑使用Action Manager。在设计一个好的GUI时,操作是您的朋友,但您不必在uses子句中动态地包含一个单元。不同的单元被编译到应用程序中,这取决于哪些单元依赖于哪些其他单元。你的单位是否使用它取决于设计。如果应用程序中的某个单元已经在其他地方使用过,那么再次使用它也没什么坏处。请重新考虑您的设计。这是一场维护噩梦,毫无意义。相反,使用单独的框架,并将逻辑放在它所属的位置。它不仅可以在设计器中正常工作,而且可以防止将来给您(以及任何其他必须尝试和维护您的代码的人)带来重大麻烦,这始终是一个好主意(除非您持有主要止痛药制造商的股票)。不相关,但请考虑使用Action Manager。在设计一个好的GUI时,动作是你的朋友,但你不一定要在c中包含一个单元