【问题标题】:Delphi - Form in DLL - Hints not showingDelphi - DLL 中的表单 - 提示未显示
【发布时间】:2010-02-17 11:40:59
【问题描述】:

我在 DLL 中有一个 Delphi 表单(我知道这会将 DLL 的使用限制为 Delphi,但在这种情况下这不是问题)。

DLL 导出一个函数ShowForm,大致如下:

procedure ShowForm (App : TApplication);
begin
  OldApp := Application;
  try
    Application := App;
    MyForm := TMyForm.Create (nil);
    try
      MyForm.ShowModal;
    finally
      FreeAndNil (MyForm);
    end;
  finally
    Application := OldApp;
  end;
end;

现在我在表单上使用TAdvOfficeHint(来自TMS 组件包)。不幸的是,提示没有显示出来。

我在这里遗漏了什么吗?如果我在主应用程序中显示它,我怎样才能使表单的行为与它完全一样?

谢谢!

【问题讨论】:

  • 你不想听到的答案是:使用运行时包。
  • 您可以将其保留为 dll,但至少使用运行时包编译您的 exe 和 dll。如果您不使用运行时包,您将遇到越来越多的此类问题。真的……你自己已经找到其他人了:stackoverflow.com/questions/2250291/…

标签: delphi dll


【解决方案1】:

我不知道TAdvOfficeHint,但我猜它挂钩Application.OnShowHint 设置自己的THintWindowClass,即使主可执行文件和DLL 都在TMS 单元中链接,它们都有自己的副本出了问题的班级。

分配Application 是不够的:还有其他全局变量,如ScreenMouse 等。其他变量甚至隐藏在实现中,所以我想说你有机会使表单正常运行与主应用程序完全一样很苗条。

【讨论】:

  • 这似乎是正确的:作为一种可能的解决方案:是否可以将 dll 制作成一个包?这样您就可以确保您的地址空间中只有一个 Application 和一个 Screen 对象。
  • 是的,这会有所帮助。如果可能,请将您的 DLL 设为运行时包,或者至少编译 DLL 和主应用程序以使用运行时包。
  • 感谢和 +1!在不切换到包的情况下我能做些什么?
  • 正如他们解释的那样,不。或者您可以停止使用 TAdvOfficeHint 并提出另一个提示解决方案。
【解决方案2】:

应用程序设置错误。

试试这个,看看它是否能解决你的问题:

procedure ShowForm (AppHandle : THandle);
begin
  OldAppHandle := Application.Handle;
  try
    Application.Handle := AppHandle;
    ........
  finally
    Application.Handle := OldAppHandle;
  end;
end;

【讨论】:

    【解决方案3】:

    刚刚找到它不起作用的原因。正如 TOndrej 所说,TAdvOfficeHinthooks Application.OnShowHint 并在内部执行以下代码行:

    FHintInfo.Assign (AHintInfo);
    

    Assign 内部使用动态类型检查

    if (Source is TAddvHintInfo) then ...
    

    由于 DLL 和主应用程序的不同类型注册表而失败。

    我已经遇到过几次这个问题,也许我真的必须切换到运行时包来避免所有这些问题。

    无论如何,如果我能做些什么来防止这种情况发生,请发表评论。

    【讨论】:

    • 也许您可以尝试重写它以检查类名,然后进行硬广播:如果 Source.ClassNameIs('TAdvHintInfo') then with TAdvHintInfo(Source) do ...
    • 我以前用过几次。我宁愿不接触消息来源。但这似乎是唯一的方法,所以谢谢!
    • 不能保证该代码(上面评论中的类名hack)运行而不会崩溃。
    • 对不起。我认为这很明显。 :-) 是的,这是一个丑陋、肮脏、危险的黑客行为。不要在家里这样做。
    • 更重要的是,不要在工作中这样做。 :-)
    【解决方案4】:

    我猜在Delphi 2006及以后的版本中你可以在EXE代码中调用System.ShareMemoryManager方法,使其内存管理器与加载到进程内存空间的其他模块共享。

    【讨论】:

    • 我在应用程序和 DLL 中都包含了SimpelShareMem。这不应该有同样的效果吗?并且类型注册表问题与内存管理器有关吗?
    • 如果没有运行时包,您可以共享模块,但如果 VCL 类不在共享包中,则 mainexe::TObject 将不等于 mydll::TObject,直到您启用运行时包。你为什么这么反对运行时包?
    • 看来沃伦是对的,我稍后会删除这个答案。对不起。
    • 因为这意味着很多努力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-29
    • 2014-08-18
    • 2010-09-21
    • 1970-01-01
    • 2012-07-29
    相关资源
    最近更新 更多