You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测IDE完全加载?Delphi插件添加菜单遇阻求助

Delphi DLL IDE插件添加菜单的最优方案

问题背景

编写Delphi IDE的DLL插件时,在插件构造函数中调用fNTAServices.AddActionMenu('ViewToolWindowsItem', nil, CustomMenuItem)会失败,原因是插件初始化阶段IDE主菜单尚未完全创建。目前使用IOTAIDENotifier在ofnEndProjectGroupOpen通知时执行菜单添加,但该方案存在局限性,希望找到更可靠的实现方式。测试发现,IDE主菜单完全生成需要100-300ms,构造阶段仅部分菜单可用。

推荐方案

方案1:监听IDE启动完成通知(Delphi XE及以上版本)

从Delphi XE开始,IOTAIDENotifier的Notify方法会收到ofnStartupComplete通知,这是IDE完全启动就绪的官方信号,此时所有主菜单已创建完毕。

实现步骤:

  1. 让向导类实现IOTAIDENotifier接口(补充Notify方法)
  2. 在构造函数中注册通知器:
var
  IDEServices: IOTAIDEServices;
begin
  inherited;
  // ... 原有初始化代码
  if Supports(BorlandIDEServices, IOTAIDEServices, IDEServices) then
    IDEServices.AddNotifier(Self);
end;
  1. 实现Notify方法处理启动完成事件:
procedure TMenuTest.Notify(NotifyCode: TOTANotifyCode);
var
  IDEServices: IOTAIDEServices;
begin
  if NotifyCode = ofnStartupComplete then
  begin
    try
      fNTAServices.AddActionMenu('ViewToolWindowsItem', nil, fCustomMenuItem);
      // 完成后移除通知器,避免不必要的触发
      if Supports(BorlandIDEServices, IOTAIDEServices, IDEServices) then
        IDEServices.RemoveNotifier(Self);
    except
      on E: Exception do
        OutputDebugString(PChar('添加菜单失败: ' + E.Message));
    end;
  end;
end;

方案2:监听IDE主窗口显示事件(兼容旧版本Delphi)

如果插件需要兼容更早的Delphi版本(如Delphi 2010及以前),可以监听IDE主窗口的WM_SHOWWINDOW消息,在窗口首次显示时执行菜单添加。

实现步骤:

  1. 在构造函数中创建TApplicationEvents监听消息:
var
  AppEvents: TApplicationEvents;
begin
  inherited;
  // ... 原有初始化代码
  AppEvents := TApplicationEvents.Create(nil);
  AppEvents.OnMessage := HandleIDEMainWindowMessage;
end;
  1. 实现消息处理方法:
procedure TMenuTest.HandleIDEMainWindowMessage(var Msg: tagMSG; var Handled: Boolean);
var
  IDEMainWindow: IOTAIDEWindow;
begin
  if Msg.Message = WM_SHOWWINDOW then
  begin
    if Supports(BorlandIDEServices, IOTAIDEWindow, IDEMainWindow) then
    begin
      if Msg.hwnd = IDEMainWindow.Handle then
      begin
        try
          fNTAServices.AddActionMenu('ViewToolWindowsItem', nil, fCustomMenuItem);
          // 执行完成后销毁事件对象,防止重复触发
          TObject(Sender).Free;
        except
          on E: Exception do
            OutputDebugString(PChar('添加菜单失败: ' + E.Message));
        end;
      end;
    end;
  end;
end;

方案对比与避坑说明

  • 原方案ofnEndProjectGroupOpen的局限性:用户打开IDE时如果不加载项目组,该通知不会触发,导致菜单无法添加。
  • 匿名线程轮询方案:虽然能临时解决问题,但会占用CPU资源,且属于非官方的hack方式,不建议在正式插件中使用。

内容的提问来源于stack exchange,提问作者k0tt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 22:41:05