delphi - 扩展TWebBrowser外部对象来执行Delphi代码: how to access my form components?

标签 delphi interface delphi-10-seattle twebbrowser

我正在关注 How to call Delphi code from scripts running in a TWebBrowser DelphiDabbler 教程(作者:Peter Johnson)允许 Delphi 监听 TWebBrowser JavaScript 事件。

这直到我看到我的 Delphi 程序被调用为止。但是,从那里我需要更新一些表单标签,并且我看不到如何从这些过程访问我的表单。
DelphiDabbler 示例代码通过 creating 很好地规避了“直接表单访问” THintAction.Create(nil); 这将完成它的事情:

This let's us decouple our external object implementation quite nicely from the program's form

但我想访问我的表单!传递的数据有整数和字符串。
我可以使用 PostMessage() 和 WM_COPYDATA 消息,但这些消息仍然需要表单句柄。难道没有一个“直接”的途径来填写表格吗?

相关代码:

type
   TWebBrowserExternal = class(TAutoIntfObject, IWebBrowserExternal, IDispatch)
   protected
      procedure SetVanLabel(const ACaption: WideString); safecall;  // My 3 procedures that are called...
      procedure SetNaarLabel(const AValue: WideString); safecall;   // ... declared in the type library.
      procedure SetDistanceLabel(AValue: Integer); safecall;
   public
      constructor Create;
      destructor Destroy; override;
   end;

type
   TExternalContainer = class(TNulWBContainer, IDocHostUIHandler, IOleClientSite)
   private
      fExternalObj: IDispatch;  // external object implementation
   protected
      { Re-implemented IDocHostUIHandler method }
      function GetExternal(out ppDispatch: IDispatch): HResult; stdcall;
   public
      constructor Create(const HostedBrowser: TWebBrowser);
   end;

constructor TExternalContainer.Create(const HostedBrowser: TWebBrowser);
begin
   inherited Create(HostedBrowser);
   fExternalObj := TWebBrowserExternal.Create;
end;

表单有一个属性FContainer: TExternalContainer;,在FormCreate中我做fContainer := TExternalContainer.Create(WebBrowser);(参数是设计时TWebBrowser),所以 TExternalContainer.fExternalObj 已分配给它。

问题:

  procedure TWebBrowserExternal.SetDistanceLabel(AValue: Integer);
  begin
     // **From here, how do I send AValue to a label caption on my form?**
  end;

我必须承认接口(interface)不是我的强项;-)

[补充:]注意:我的表单都是动态创建的,当前单元没有TForm实例。

最佳答案

您说您想要访问您的表单,但您实际上并不这样做 - 至少不是直接这样做。您确实希望“将我们的外部对象实现与程序的形式很好地分离”。您真正需要做的就是编写一个函数或过程来在程序中执行您想要的操作,然后从 Web 浏览器调用该函数或过程。这就是解耦和接口(interface)的意义所在。您永远不会直接从另一个应用程序处理属于一个应用程序的数据。相反,您使用函数和过程作为界面。顺便说一句,这就是为什么接口(interface)只包含函数和过程原型(prototype)(以及属性 - 但它们只是在内部转换为函数和过程) - 而不是数据。

现在讨论你的具体问题。当然,您可以访问您的表单 - 它是一个全局变量。假设你的主窗体是 TMainForm 类型,在一个名为 Main.pas 的单元中,将会有一个名为 MainForm 的全局变量

var
  MainForm : TMainForm;

因此,在您的网络浏览器单元中,您将在实现部分中放置

implementation

uses Main;

...

procedure TWebBrowserExternal.SetDistanceLabel(AValue: Integer);
begin
   // **From here, how do I send AValue to a label caption on my form?**
   FormMain.MyLabel.Caption := StrToInt( AValue );
end;

就我所说的而言,SetDistanceLabel 是接口(interface)函数,并且只能从 Delphi 应用程序中直接访问 Form。

关于delphi - 扩展TWebBrowser外部对象来执行Delphi代码: how to access my form components?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37964716/

相关文章:

macos - 在 OS X 上运行 Delphi 10 Seattle 应用程序时出现 Dylib 版本错误

delphi - 检查 Active DIRECTORY 中是否存在用户身份验证

delphi - CheckException仅接受0参数方法;如何测试其他方法是否抛出异常?

delphi - 如何使用 ReadProcessMemory 读取 pchar

windows - 如何使用 Delphi 2010 以编程方式确定 Windows 的性能设置

C# 将泛型类型向上转型为接口(interface)

ios - 通过 RAD Studio 10.0 开发的 Firemonkey 应用程序在 iOS 7.1 上崩溃?

delphi - Delphi 中的文件流 - 最佳缓冲区大小

java - 将存储库接口(interface)注释为 @Component 有什么缺点吗?

java - 如何实现扩展类的构造函数