0

假设我有 1 个主要形式。主窗体包含两个按钮(打开关闭),单击每个按钮会创建一个以主窗体作为父/所有者的框架。该框架包含 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.

框架使用的 3 种方法(AddBtnClickEditBtnClickDelBtnClick)存在于两个不同的单元上,即 UntOpen 和 UntClose ,但根据创建的框架不同,做的事情也不同。当单击打开按钮时,框架应使用 UntOpen,当单击主菜单中的关闭按钮时,应使用 UntClose。

UntOpen 代码:

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.

我想在每次创建框架的使用子句时动态添加一个单元(如果可能),以便单击框架的添加、编辑或删除按钮会触发正确的方法(如果单击打开按钮,则来自 UntOpen 的方法如果单击关闭按钮,则来自 UntClose 或方法)。

还是有更有效的方法来做到这一点?

谢谢。

4

3 回答 3

5

您不能动态使用单位;不能在运行时操纵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);
于 2013-09-05T03:49:49.430 回答
0

尝试更多类似的东西:

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 MainForm;

...

uses
  ..., UntFrame, UntOpen, UntClose;

...

procedure TFormMain.OpenClick(Sender: TObject);
begin
  with TFmeMain.Create(Self) do
  begin
    Parent := ...;
    OnAdd := Addr(UntOpen.AddBtnClick);
    OnEdit := Addr(UntOpen.EditBtnClick);
    OnDelete := Addr(UntOpen.DelBtnClick);
  end;
end;

procedure TFormMain.CloseClick(Sender: TObject);
begin
  with TFmeMain.Create(Self) do
  begin
    Parent := ...;
    OnAdd := Addr(UntClose.AddBtnClick);
    OnEdit := Addr(UntClose.EditBtnClick);
    OnDelete := Addr(UntClose.DelBtnClick);
  end;
end;

end.
于 2013-09-05T05:15:44.613 回答
0

如果我是你,我会尝试这个解决方案:

主机架:

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 中是可能的。

于 2013-09-05T07:21:29.010 回答