我正在尝试根据用户设置配置编写一个返回两个TForm
实例之一的函数:
function TfrmMain.GetCurrentRamEditFrm: TForm;
{ Get the RAM Editor Form instance according to currenttly-set protocol. }
begin
if frmSetup.GetCurrentProtocol() = FooBus then
result := RAM_Editor_FooBus.frmRAM_Editor_FooBus
else
result := RAM_Editor_SXcp.frmRAM_Editor_SXcp;
end;
我需要此功能,因为此单元(
Main.pas
)在RAM编辑器表单中读取/写入许多变量。编译器在以下行跳闸:
GetCurrentRamEditFrm().StatusBar1.Panels[1].Text := get_text(96);
错误消息:
Undeclared identifier 'StatusBar1'
如果我明确提供TForm实例,则没有错误:
RAM_Editor_SXcp.frmRAM_Editor_SXcp.StatusBar1.Panels[1].Text := get_text(96);
两种形式的
StatusBar
声明如下:type
TfrmRAM_Editor_SXcp = class(TForm)
StatusBar1: TStatusBar; // i.e. the scope is "published"
...
有趣的是,编译器不介意以下内容:
GetCurrentRamEditFrm().show();
最佳答案
编译器错误是可以理解的,因为TForm
没有名为StatusBar1
的成员。您以派生形式进行了介绍,我认为这些形式为TfrmRAM_Editor_FooBus
和TfrmRAM_Editor_SXcp
。
现在,如果这两种形式是从引入StatusBar1
的公共基类派生的,则可以改为返回该公共基类,并且可以编译代码。看起来像这样:
type
TfrmRAM_Editor_Base = class(TForm)
StatusBar1: TStatusBar;
....
end;
TfrmRAM_Editor_FooBus = class(TfrmRAM_Editor_Base)
....
end;
TfrmRAM_Editor_SXcp = class(TfrmRAM_Editor_Base)
....
end;
function TfrmMain.GetCurrentRamEditFrm: TfrmRAM_Editor_Base;
{ Get the RAM Editor Form instance according to currently-set protocol. }
begin
if frmSetup.GetCurrentProtocol() = FooBus then
result := RAM_Editor_FooBus.frmRAM_Editor_FooBus
else
result := RAM_Editor_SXcp.frmRAM_Editor_SXcp;
end;
但是,这并不是一个很好的解决方案。我的问题是继承是一个非常严格的机制,并且我不愿意将UI控件公开在表单本身之外使用。意识到Delphi的流机制会强制发布设计时控件,因此可以从外部看到它们,但是在我看来,这是一个糟糕的错误,助长了糟糕的设计。
我个人将定义一个可用于设置状态文本的界面。
type
ISetStatusText = interface
[...add GUID here]
procedure SetStatusText(const Value: string);
end;
让每个表单都实现此接口,然后可以使用
as
进行查询。也许更好的方法是让您的GetCurrentRamEditFrm
函数返回接口而不是表单。这避免了您不得不向所有人公开表单的UI实现细节。
关于delphi - 如何编写在运行时返回现有TForm实例的函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27224439/