从Delphi程序中调用Javascript函数

Call a Javascript function from a Delphi program

本文关键字:Javascript 函数 调用 Delphi 程序      更新时间:2023-09-26

我有一个问题,在…上找不到明确的答案

所以我有了这个JavaScript代码:

var asp = {
    alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
    lookup: null,
    ie: /MSIE/.test(navigator.userAgent),           // Checks the browser client
    ieo: /MSIE[67]/.test(navigator.userAgent),      // Checks The Browser Client
    encode: function(s) {
        var buffer = asp.toUtf8(s),
            position = -1,
            len = buffer.length,
            nan0, nan1, nan2, enc = [, , , ];
        if (asp.ie) {
            var result = [];
            while (++position < len) {
                nan0 = buffer[position];
                nan1 = buffer[++position];
                enc[0] = nan0 >> 2;
                enc[1] = ((nan0 & 3) << 4) | (nan1 >> 4);
                if (isNaN(nan1)) enc[2] = enc[3] = 64;
                else {
                    nan2 = buffer[++position];
                    enc[2] = ((nan1 & 15) << 2) | (nan2 >> 6);
                    enc[3] = (isNaN(nan2)) ? 64 : nan2 & 63
                }
                result.push(asp.alphabet.charAt(enc[0]), asp.alphabet.charAt(enc[1]), asp.alphabet.charAt(enc[2]), asp.alphabet.charAt(enc[3]))
            }
            return result.join('')
        } else {
            var result = '';
            while (++position < len) {
                nan0 = buffer[position];
                nan1 = buffer[++position];
                enc[0] = nan0 >> 2;
                enc[1] = ((nan0 & 3) << 4) | (nan1 >> 4);
                if (isNaN(nan1)) enc[2] = enc[3] = 64;
                else {
                    nan2 = buffer[++position];
                    enc[2] = ((nan1 & 15) << 2) | (nan2 >> 6);
                    enc[3] = (isNaN(nan2)) ? 64 : nan2 & 63
                }
                result += asp.alphabet[enc[0]] + asp.alphabet[enc[1]] + asp.alphabet[enc[2]] + asp.alphabet[enc[3]]
            }
            return result
        }
    },
    wrap: function(s) {
        if (s.length % 4) throw new Error("InvalidCharacterError: 'asp.wrap' failed: The string to be wrapd is not correctly encoded.");
        var buffer = asp.fromUtf8(s),
            position = 0,
            len = buffer.length;
        if (asp.ieo) {
            var result = [];
            while (position < len) {
                if (buffer[position] < 128) result.push(String.fromCharCode(buffer[position++]));
                else if (buffer[position] > 191 && buffer[position] < 224) result.push(String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63)));
                else result.push(String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63)))
            }
            return result.join('')
        } else {
            var result = '';
            while (position < len) {
                if (buffer[position] < 128) result += String.fromCharCode(buffer[position++]);
                else if (buffer[position] > 191 && buffer[position] < 224) result += String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63));
                else result += String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63))
            }
            return result
        }
    },
    toUtf8: function(s) {
        var position = -1,
            len = s.length,
            chr, buffer = [];
        if (/^['x00-'x7f]*$/.test(s))
            while (++position < len) buffer.push(s.charCodeAt(position));
        else
            while (++position < len) {
                chr = s.charCodeAt(position);
                if (chr < 128) buffer.push(chr);
                else if (chr < 2048) buffer.push((chr >> 6) | 192, (chr & 63) | 128);
                else buffer.push((chr >> 12) | 224, ((chr >> 6) & 63) | 128, (chr & 63) | 128)
            }
        return buffer
    },
    fromUtf8: function(s) {
        var position = -1,
            len, buffer = [],
            enc = [, , , ];
        if (!asp.lookup) {
            len = asp.alphabet.length;
            asp.lookup = {};
            while (++position < len) asp.lookup[asp.alphabet.charAt(position)] = position;
            position = -1
        }
        len = s.length;
        while (++position < len) {
            enc[0] = asp.lookup[s.charAt(position)];
            enc[1] = asp.lookup[s.charAt(++position)];
            buffer.push((enc[0] << 2) | (enc[1] >> 4));
            enc[2] = asp.lookup[s.charAt(++position)];
            if (enc[2] == 64) break;
            buffer.push(((enc[1] & 15) << 4) | (enc[2] >> 2));
            enc[3] = asp.lookup[s.charAt(++position)];
            if (enc[3] == 64) break;
            buffer.push(((enc[2] & 3) << 6) | enc[3])
        }
        return buffer
    }
};

这是我电脑上的一个本地JavaScript文件,我需要能够从我的Delphi程序中调用函数(并接收函数的输出)。。。实现这一点最简单的方法是什么?我发现了一些关于堆栈溢出的源代码,但项目不完整,我无法使用包含的脚本。另一种选择是在两者之间创建一个中介(也许像网页一样?)但我最好让解决方案尽可能简单,所以如果你们能帮我解决这个问题,我将不胜感激!

对于好奇的人来说:上面的脚本是一个加密和解密算法编辑:这不是一个加密算法,而是一个简单的base64编码器,因此这个问题已经解决了!

谢谢你花时间读这篇文章,现在干杯!

该代码需要在浏览器环境中运行,因此要直接使用它,您必须在浏览器中运行,也许是无头浏览器。尽管可以删除其中特定于浏览器的部分,但这似乎主要是解决Internet Explorer问题的方法。

与其尝试直接使用它(这将非常复杂),我只想将它翻译成Delphi。

要运行JavaScript函数,必须使用WebBrowser组件(如TWebBrowser)。但是,默认情况下,TWebBrowser组件与最旧版本的Internet Explorer兼容。在第一步中,您必须与最新版本兼容。为此,您必须使用以下代码(适用于IE10):

procedure TForm1.btnIE10EmulatorClick(Sender: TObject);var
  RegObj: TRegistry;
begin
  RegObj := TRegistry.Create;
  try
    RegObj.RootKey := HKEY_LOCAL_MACHINE;
    RegObj.Access := KEY_ALL_ACCESS;

    if (TOSVersion.Architecture = arIntelX64) then
    begin
      RegObj.OpenKey(''SOFTWARE'Wow6432Node'Microsoft'Internet ' +
        'Explorer'MAIN'FeatureControl'FEATURE_BROWSER_EMULATION', True);
    end
    else if (TOSVersion.Architecture = arIntelX86) then
    begin
      RegObj.OpenKey(''SOFTWARE'Microsoft'Internet ' +
        'Explorer'MAIN'FeatureControl'FEATURE_BROWSER_EMULATION', True);
    end;

    RegObj.WriteInteger(ExtractFileName(Application.ExeName), 10000 {compatibility with IE10}); // for other versions read msdn
  finally
    RegObj.Free;
  end;
end;

在第二步中,在您的表单上放置一个TWebBrowser组件

在下一步中,在您的应用程序中添加此功能:

procedure ExecuteJavaScript(document:IHTMLDocument2; Code: string);
var
  Window:IHTMLWindow2;
begin
  if not Assigned(Document) then Exit;
  Window:=Document.parentWindow;
  if not Assigned(Window) then Exit;
  try
    Window.execScript(Code,'JavaScript');
  except
    on E:Exception do raise Exception.Create('Javascript error '+E.Message+' in: '#13#10+Code);
  end;
end;

通过这个函数可以运行javascript函数。

示例1(运行函数而不返回值):

ExecuteJavaScript((WebBrowser1.Document as IHTMLDocument2), 'JsFunctionName();');

示例2(javascript代码返回值):如果您的JS代码返回值,请将此函数添加到您的delphi程序中:

function GetElementIdValue(WebBrowser:TWebBrowser; TagName,TagId,TagAttrib:String):String;
var
  Document: IHTMLDocument2;
  Body: IHTMLElement2;
  Tags: IHTMLElementCollection;
  Tag: IHTMLElement;
  I: Integer;
begin
  Result:='';
  if not Supports(WebBrowser.Document, IHTMLDocument2, Document) then
    raise Exception.Create('Invalid HTML document');
  if not Supports(Document.body, IHTMLElement2, Body) then
    raise Exception.Create('Can''t find <body> element');
  Tags := Body.getElementsByTagName(UpperCase(TagName));
  for I := 0 to Pred(Tags.length) do begin
    Tag:=Tags.item(I,EmptyParam) as IHTMLElement;
    if Tag.id=TagId then Result:=Tag.getAttribute(TagAttrib,0);
  end;
end;

并使用此代码返回值:

procedure TForm1.Button3Click(Sender: TObject);
begin
  // eval demo cpde
  try
    ExecuteJavaScript(WebBrowser1,'DoEval("'+Edit1.Text+'");');
    ResultLabel.Caption := GetElementIdValue(WebBrowser1,'input','result','value'));
  except
    on E:Exception do ConsoleRed(E.Message);
  end;
end;

本例中的JavaScript代码为:

function DoEval(expr){
 // eval for delphi!
 document.getElementById('result').value=eval(expr);
}

对于使用这个例子,你的用法必须是这样的:

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, OleCtrls, ExtCtrls, {REQUIRED UNITS} SHDocVw, MSHTML,
  ComCtrls {/REQUIRED UNITS};