【问题标题】:Getting a reference to an object inside the Delphi IDE在 Delphi IDE 中获取对对象的引用
【发布时间】:2015-10-16 18:07:51
【问题描述】:

这是我对这个问题的回答:

Can I change the display format for strings in the watch list?

事实证明,在 D7 和 XE3 之间的某个时刻,IDE 的 Watch Window 的实现从使用 TListView 更改为 TVirtualStringTree。

虽然我通过忽略 VST 并从剪贴板获取监视值发布了对 XE4 的答案的更新,但如果可以的话,我仍然希望能够从 VST 获取监视值。我想我知道该怎么做 一旦我参考了 VST,但问题是我尝试获取 VST 失败了。

以下是我在自定义包中使用的代码的 MCVE。希望它的作用是不言自明的。问题是块中的代码

  if WatchWindow.Components[i] is TVirtualStringTree then begin
    [...]
  end;

从不执行,尽管在 Memo1 中出现了类名“TVirtualStringTree”。显然,具有该类名的组件未能通过“是”测试。我猜测原因是编译到 IDE 中的 TVirtualTreeView 与我使用的版本不同,v.5.3.0,这是我能找到的最接近 XE4 的前身。

所以,我的问题是,这是可能的解释,我能做些什么吗?我怀疑是否有人可以从一顶帽子中蓬勃发展用于 XE4 的 TVirtualStringTree 版本,这可能会解决我的问题。

type
  TOtaMenuForm = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
  private
    WatchWindow : TForm;
    VST : TVirtualStringTree;
  end;

procedure TOtaMenuForm.FormCreate(Sender: TObject);
var
  i : Integer;
  S : String;
begin

  WatchWindow := Nil;
  VST := Nil;

  // Iterate the IDE's forms to find the Watch Window
  for i := 0 to Screen.FormCount - 1 do begin
    S := Screen.Forms[i].Name;
    if CompareText(S, 'WatchWindow') = 0 then begin
      WatchWindow := Screen.Forms[i];
      Break;
    end;
  end;

  Assert(WatchWindow <> Nil);

  if WatchWindow <> Nil then begin
    Memo1.Lines.Add('Looking for VST');
    for i := 0 to WatchWindow.ComponentCount - 1 do begin
      Memo1.Lines.Add(IntToStr(i) + ':' + WatchWindow.Components[i].ClassName);
      if WatchWindow.Components[i] is TVirtualStringTree then begin
         VST := TVirtualStringTree(WatchWindow.Components[i]);
         Memo1.Lines.Add('found VST');
         Break;
      end;
    end;
    if VST = Nil then
      Memo1.Lines.Add('VST not found');
  end;
end;

顺便说一句,我意识到依赖于 IDE 实现细节的解决方案可能很脆弱,但这只是为了消遣(我喜欢从一个组件中获取字符串数据的挑战,该组件会竭尽全力避免存储任何)。

【问题讨论】:

  • VST 版本不是唯一的问题。如果您的代码使用与 IDE 不同的 RTTI 编译,is 运算符将失败,因此二进制文件中的 VST 组件与 IDE 中的 VST 组件不同。即使您的代码使用完全相同的 VST 版本,RTTI 仍然不匹配。这就是运行时包发挥作用的地方。您的二进制文件必须与运行时包链接,因此它与 IDE 共享相同的 RTL,并且它必须链接到 IDE 用于其 VST 组件的相同包。但是如果 VST 直接编译到 IDE 中而不是从包中导入,那么你就是 SOL...
  • ... 您将不得不放弃 is 运算符并改用 ClassName() 比较。这至少可以让您检测 IDE 的 VST 组件。但是访问它是不安全的,除非你有完全相同的版本,所以内存布局仍然匹配。
  • @RemyLebeau:谢谢。实际上,我曾尝试忽略“i”结果并根据类名对其进行硬转换,但是当我尝试调用对象的方法时会出现 AV。 Fwiw,我在 D7 中使用了相同的“is”技术,其中 Watch Window 是一个 TListView,并且在获取参考和使用它方面效果很好。
  • 该 AV 可能是由于您使用的 VST 版本与 IDE 使用的 VST 版本不同,其成员偏移量和方法参数不同。 TListView “工作”,因为您和 IDE 可能链接到实现标准 TListView 组件的同一个包。
  • 我不确定,但 VST 可能是在 Delphi-2005 版本的 IDE 中引入的。

标签: delphi delphi-xe4


【解决方案1】:

也许你可以尝试通过 RTTI 方法仅使用嵌入到 IDE TVirtualStringTree 实现中的已发布属性来做你想做的事?

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 2010-12-19
  • 1970-01-01
相关资源
最近更新 更多