Как открыть "родные функции" для Javascript на веб-странице с помощью Chromium и Delphi 6?

Я успешно включил Chromium в свои проекты Delphi 6 с помощью Delphi Chromium Embedded. Теперь я хочу, чтобы иметь возможность выполнять Javascript-код, и результаты возвращаются в мое приложение-приложение Delphi. Мой текущий метод - вызвать ExecuteJavascript() и использовать элемент DOM, который Javascript-вызов записывает свои результаты, и опросить этот элемент в методе TTimer из Delphi для получения результатов. Тем не менее, я прочитал об использовании встроенных функций и расширений V8, чтобы заставить Javascript-вызов "перезвонить" в мой код Delphi как способ получения результатов:

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

Я хотел бы попробовать это, и я также хотел бы знать, как подключать слушателей событий на основе Delphi к элементам DOM на веб-странице (onblur, onmousedown и т.д.). Я ищу некоторые образцы, которые показывали бы мне, как делать эти две вещи, если кто-нибудь знает, где их найти.

Ответы

Ответ 1

Присоединение слушателей довольно просто (только в более старых версиях 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: соединительная линия не содержит их (пока?). Кажется, что работа продолжается.

Edit

Избавление от опроса с помощью расширений:

Вполне возможно, что ваш код 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;

TMyHandler Execute будет вызываться позже. 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;

Теперь для проверки вызова в Delphi из JavaScript просто выполните:

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

В этом окне отображается сообщение "Выполнить!".

Я вытащил демо script из образца с именем cefclient, который можно найти в папке \demos\cefclient в корневом каталоге компонента. Код примера расширения немного скрыт и смешан с другим демо-кодом. Но для нас особый интерес представляет реализация TExtension.Execute (эквивалентная my TMyHandler.Execute). Там вы можете найти, как определить, какая функция вызывается, и как передавать параметры. (Ссылка на код.)