下面的代码是我在 D7 的设计时 .BPL 中所做的简化的。
更新:自从发布此消息以来,我找到了一种方法来做我所追求的,即只需向表单发送 WM_Close 消息,但我仍然有兴趣知道是否有更“官方”的方式来做到这一点,因为使用 WM_Close 似乎有可能使 IDE 出错。
我在这段代码中试图做的所有导致我出现问题的事情是关闭在 IDE 中打开的所有文件,然后打开一个特定的 .Pas 文件,该文件恰好有一个关联的 .Dfm 文件。我不希望 .Dfm 中定义的表单在屏幕上打开,所以我试图关闭它,而不关闭 .Pas 文件 - 我只想要 IDE 表单设计器和这个表单.
最终,我发现了如何在我的 .BPL 代码中通过 OTA + NTA 服务获取表单,并且天真地但因为想要任何其他明显的方式来做到这一点,我尝试通过这个片段调用 .Close 。
AForm := TForm(INTAComp.GetComponent);
AForm.Close;
但是,窗体不会关闭。我已经从 CPU 窗口追踪到 TCustomForm.Close,显然它没有关闭的原因是它的 Visible 属性已经是 False。这也是在 AForm.Close 返回之前评估 Visible 的内容。
在 AForm.Close 之前评估它的其他各种属性告诉我 - 它的所有者是 Nil 但是 - 它有一个明显有效的窗口句柄 // Arrghh![一分钱下降的声音......见上面的更新]
我敢说这与 IDE 的表单设计器的工作方式有关。
我的问题很简单:我需要在代码中做什么才能关闭表单,就像我只需单击其框架上的 [x] 按钮时所做的那样?
顺便说一句,我已经确认我通过 AForm := [...] 获得的表单实例是屏幕上的实例,方法是在 OI 中更改屏幕上实例的标题。
procedure TOTAForm.CloseAForm;
var
IServices : IOTAServices;
IActionServices : IOTAActionServices;
IModuleServices : IOTAModuleServices;
IEditorServices : IOTAEditorServices60;
IModule : IOTAModule;
i : Integer;
IEditor : IOTAEditor;
ISourceEditor : IOTASourceEditor;
IFormEditor : IOTAFormEditor;
IComponent : IOTAComponent;
INTAComp : INTAComponent;
AForm : TForm;
begin
IServices := BorlandIDEServices as IOTAServices;
IServices.QueryInterface(IOTAACtionServices, IActionServices);
if IActionServices <> Nil then begin
IServices.QueryInterface(IOTAModuleServices, IModuleServices);
IModuleServices.CloseAll;
if IActionServices.OpenFile(EditorFileName) then begin
IModule := IModuleServices.Modules[0];
ISourceEditor := Nil;
for i := 0 to IModule.ModuleFileCount - 1 do begin
IEditor := IModule.ModuleFileEditors[i];
IEditor.QueryInterface(IOTAFormEditor, IFormEditor);
if IFormEditor <> Nil then begin
IComponent := IFormEditor.GetRootComponent;
IComponent.QueryInterface(INTAComponent, INTAComp);
AForm := TForm(INTAComp.GetComponent);
AForm.Close;
end;
end;
end;
end;
end;