如何使用 Chromium 和 Delphi 6 在网页中向 Javascript 公开“本机函数”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6893029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to expose "native functions" to Javascript in a web page using Chromium and Delphi 6?
提问by Robert Oschler
I have successfully embedded Chromium into my Delphi 6 projects with the help of Delphi Chromium Embedded. Now I want to be able to execute Javascript code and the have results returned to my host Delphi app. My current method is to call ExecuteJavascript() and use a DOM element that the Javascript call writes its results to, and poll that element in a TTimer method from Delphi to retrieve the results. However, I read about using native functions and V8 extensions to have the Javascript call "call back" into my Delphi code as a way to receive results instead:
在Delphi Chromium Embedded的帮助下,我已经成功地将 Chromium 嵌入到我的 Delphi 6 项目中。现在我希望能够执行 Javascript 代码并将结果返回到我的主机 Delphi 应用程序。我当前的方法是调用 ExecuteJavascript() 并使用 Javascript 调用将其结果写入的 DOM 元素,然后在 Delphi 的 TTimer 方法中轮询该元素以检索结果。但是,我阅读了有关使用本机函数和 V8 扩展来让 Javascript 调用“回调”到我的 Delphi 代码中作为接收结果的一种方式:
http://magpcss.org/ceforum/viewtopic.php?f=7&t=180
http://magpcss.org/ceforum/viewtopic.php?f=7&t=180
I would like to try this and I also would like to know how to attach Delphi based event listeners to DOM elements in the web page (onblur, onmousedown, etc.). I am looking for some samples that would show me how to do these two things if anyone knows where to find them.
我想试试这个,我也想知道如何将基于 Delphi 的事件侦听器附加到网页中的 DOM 元素(onblur、onmousedown 等)。我正在寻找一些示例,如果有人知道在哪里可以找到它们,它们将向我展示如何做这两件事。
采纳答案by Heinrich Ulbricht
Attaching listeners is quite easy (only in older versions of CEF):
附加侦听器非常简单(仅在旧版本的 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;
Regarding the extended functions for getting JavaScript results directly: the trunk doesn't contain them (yet?). Seems to be work in progress.
关于直接获取 JavaScript 结果的扩展函数:trunk 不包含它们(还没有?)。似乎正在进行中。
Edit:
编辑:
Getting rid of polling via extensions:
通过扩展摆脱轮询:
It is indeed possible for your JavaScript code to call back into your Delphi code using extensions. Furthermore you can send values from JavaScript to Delphi - this could be used to transfer results without the need to poll.
您的 JavaScript 代码确实可以使用扩展回调到您的 Delphi 代码中。此外,您可以将值从 JavaScript 发送到 Delphi - 这可用于传输结果而无需轮询。
First in your initialization
section register the extension, which creates a JavaScript object later to be used when calling back:
首先在您的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;
TMyHandler
's Execute
will be invoked later. TMyHandler
is defined as
TMyHandler
'sExecute
将在稍后调用。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;
The implementation for demonstration purposes is simple for now:
用于演示目的的实现现在很简单:
function TMyHandler.Execute(const name: ustring; const obj: ICefv8Value; const arguments: TCefv8ValueArray; var retval: ICefv8Value; var exception: ustring): Boolean;
begin
ShowMessage('Execute!');
end;
Now to test calling into Delphi from JavaScript simply do:
现在要测试从 JavaScript 调用 Delphi 只需执行以下操作:
ChromiumComponent.Browser.MainFrame.ExecuteJavaScript('cef.test.test_object().GetMessage();', 'about:blank', 0);
This should display the message box saying "Execute!".
这应该显示消息框说“执行!”。
I pulled the demo script from a sample named cefclientwhich you can find in the \demos\cefclientfolder in the component root dir. The extension sample code is a bit hidden and mingled with other demo code. But of special interest for us is the implementation of TExtension.Execute
(the equivalent to my TMyHandler.Execute
). There you can find how to determine which function is being called and how to pass parameters. (Link to the code.)
我从名为cefclient的示例中提取了演示脚本,您可以在组件根目录的\demos\cefclient文件夹中找到该示例。扩展示例代码有点隐藏并与其他演示代码混合在一起。但我们特别感兴趣的是TExtension.Execute
(相当于 my TMyHandler.Execute
)的实现。在那里您可以找到如何确定正在调用哪个函数以及如何传递参数。(链接到代码。)