如何从Delphi IDE专家中枚举IDE的表单类型

4

我正在使用 Delphi IDE 专家,并需要枚举 Delphi IDE 显示的所有窗体,目前我正在使用 Screen.Forms 属性,但我想知道是否存在另一种方法可以使用 OTA 来实现这个功能。因为当我的专家是 BPL 时,使用 Screen.Forms 可以工作,但现在我正在迁移到一个 DLL 专家。

2个回答

8

Screen.Forms 在 DLL 中仍然可以使用。只需确保您选择了“使用运行时包”链接器选项来编译您的 DLL。这样,您的 DLL 将使用与 IDE 相同的 VCL 实例,并且您将能够访问所有相同的全局变量,包括 Screen


哇,rob说:“这样,你的DLL将使用与IDE相同的VCL实例”真是太棒了。 - Johan

2

使用OpenToolsAPI完全可以实现此功能。

要提取IDE中所有打开的窗体的列表,您可以使用以下代码:

procedure GetOpenForms(List: TStrings);
var
  Services: IOTAModuleServices;
  I: Integer;
  Module: IOTAModule;
  J: Integer;
  Editor: IOTAEditor;
  FormEditor: IOTAFormEditor;
begin
  if (BorlandIDEServices <> nil) and (List <> nil) then
  begin
    Services := BorlandIDEServices as IOTAModuleServices;
    for I := 0 to Services.ModuleCount - 1 do
    begin
      Module := Services.Modules[I];
      for J := 0 to Module.ModuleFileCount - 1 do
      begin
        Editor := Module.ModuleFileEditors[J];
        if Assigned(Editor) then
          if Supports(Editor, IOTAFormEditor, FormEditor) then
             List.AddObject(FormEditor.FileName,
               (Pointer(FormEditor.GetRootComponent)));
      end;
    end;
  end;
end;

请注意,该StringList中的指针是一个IOTAComponent。要将其解析为TForm实例,您必须深入挖掘。待续。
还可以通过将类型为IOTAIDENotifier的通知器添加到IOTAServices来跟踪在IDE中打开的所有窗体,方法如下:
type
  TFormNotifier = class(TNotifierObject, IOTAIDENotifier)
  public
    procedure AfterCompile(Succeeded: Boolean);
    procedure BeforeCompile(const Project: IOTAProject; var Cancel: Boolean);
    procedure FileNotification(NotifyCode: TOTAFileNotification;
      const FileName: String; var Cancel: Boolean);
  end;

procedure Register;

implementation

var
  IdeNotifierIndex: Integer = -1;

procedure Register;
var
  Services: IOTAServices;
begin
  if BorlandIDEServices <> nil then
  begin
    Services := BorlandIDEServices as IOTAServices;
    IdeNotifierIndex := Services.AddNotifier(TFormNotifier.Create);
  end;
end;

procedure RemoveIdeNotifier;
var
  Services: IOTAServices;
begin
  if IdeNotifierIndex <> -1 then
  begin
    Services := BorlandIDEServices as IOTAServices;
    Services.RemoveNotifier(IdeNotifierIndex);
  end;
end;

{ TFormNotifier }

procedure TFormNotifier.AfterCompile(Succeeded: Boolean);
begin
  // Do nothing
end;

procedure TFormNotifier.BeforeCompile(const Project: IOTAProject;
  var Cancel: Boolean);
begin
  // Do nothing
end;

procedure TFormNotifier.FileNotification(NotifyCode: TOTAFileNotification;
  const FileName: String; var Cancel: Boolean);
begin
  if BorlandIDEServices <> nil then
    if (NotifyCode = ofnFileOpening) then
    begin
      //...
    end;
end;

initialization

finalization
  RemoveIdeNotifier;

end.

这将枚举在IDE中打开的源模块表单,如果这是目标,则应优先使用此方法。但是,要枚举内部IDE表单,例如项目管理器(TProjectManagerForm),需要另一种方法(也许是Screen.Forms)。 - Ondrej Kelle
啊啊啊,IDE本身的表单!好吧,这可以通过INTAServices实现。我想以类似的方式,但我还没有使用过它。 - NGLN
1
Editor := Module.ModuleFileEditors[I]; 应该修改为 Editor := Module.ModuleFileEditors[J]; - Atys

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接