如何公开“本地函数”;在使用Chromium和Delphi 6的网页中使用Javascript

How to expose "native functions" to Javascript in a web page using Chromium and Delphi 6?

本文关键字:Chromium Delphi Javascript 网页 何公开 函数 本地函数      更新时间:2023-09-26

我已经成功地在Delphi Chromium embedded的帮助下将Chromium嵌入到我的Delphi 6项目中。现在我想要能够执行Javascript代码,并有结果返回到我的主机Delphi应用程序。我目前的方法是调用ExecuteJavascript(),并使用一个DOM元素,Javascript调用写入其结果,并轮询该元素在TTimer方法从Delphi检索结果。然而,我读到关于使用本机函数和V8扩展有Javascript调用"回调"到我的Delphi代码作为接收结果的一种方式:

http://magpcss.org/ceforum/viewtopic.php?f=7& t = 180

我想尝试一下,我也想知道如何将基于Delphi的事件监听器附加到网页中的DOM元素(onblur, onmousedown等)。我正在寻找一些样本,这将告诉我如何做这两件事,如果有人知道在哪里找到他们。

附加监听器非常容易(仅在旧版本的CEF中):

procedure MouseDownCallback(const Event: ICefDomEvent);
begin
  ShowMessage('Mouse down on '+Event.Target.Name);
end;
procedure AttachMouseDownListenerProc(const Doc: ICefDomDocument);
begin
  Doc.Body.AddEventListenerProc('mousedown', True, MouseDownCallback);
end;
procedure TMainForm.Button1Click(Sender: TObject);
begin
  ChromiumComponent.Browser.MainFrame.VisitDomProc(AttachMouseDownListenerProc);
end;

关于直接获取JavaScript结果的扩展函数:主干不包含它们(还没有?)似乎正在进行中。

编辑:

通过扩展:

摆脱轮询

JavaScript代码确实可以使用扩展回调Delphi代码。此外,您可以将值从JavaScript发送到Delphi -这可以用于传输结果而无需轮询。

首先在initialization部分注册扩展名,它创建一个JavaScript对象,稍后在回调时使用:

procedure RegisterExtension;
var
  Code:string;
begin
  Code :=
   'var cef;'+
   'if (!cef)'+
   '  cef = {};'+
   'if (!cef.test)'+
   '  cef.test = {};'+
   '(function() {'+
   '  cef.test.__defineGetter__(''test_param'', function() {'+
   '    native function GetTestParam();'+
   '    return GetTestParam();'+
   '  });'+
   '  cef.test.__defineSetter__(''test_param'', function(b) {'+
   '    native function SetTestParam();'+
   '    if(b) SetTestParam(b);'+
   '  });'+
   '  cef.test.test_object = function() {'+
   '    native function GetTestObject();'+
   '    return GetTestObject();'+
   '  };'+
   '})();';
  CefRegisterExtension('example/v8', Code, TMyHandler.Create as ICefv8Handler);
end;
initialization
  RegisterExtension;

TMyHandlerExecute稍后会被调用。TMyHandler定义为

TMyHandler = class(TCefv8HandlerOwn)
protected
  function Execute(const name: ustring; const obj: ICefv8Value;
    const arguments: TCefv8ValueArray; var retval: ICefv8Value;
    var exception: ustring): Boolean; override;
end;

用于演示的实现现在很简单:

function TMyHandler.Execute(const name: ustring; const obj: ICefv8Value; const arguments: TCefv8ValueArray; var retval: ICefv8Value; var exception: ustring): Boolean;
begin
  ShowMessage('Execute!');
end;

现在测试从JavaScript调用Delphi只需执行:

ChromiumComponent.Browser.MainFrame.ExecuteJavaScript('cef.test.test_object().GetMessage();', 'about:blank', 0);

这应该显示消息框说"执行!"。

我从一个名为cefclient的示例中提取了演示脚本,您可以在组件根目录中的'demos'cefclient文件夹中找到该示例。扩展示例代码有点隐藏,并与其他演示代码混合在一起。但我们特别感兴趣的是TExtension.Execute的实现(相当于我的TMyHandler.Execute)。在这里,您可以找到如何确定正在调用哪个函数以及如何传递参数。(链接到代码)