javascript - Delphi:如何从 WebBrowser 访问(读取和写入)javascript 变量

标签 javascript html delphi variables

我创建了一个网页,我想访问一个 html 页面的 javascript 变量以进行 R/W。

...
<script>
  var _ANYINT = 0;
  var _ANYOBJ = 0;
</script>
...

如何读取变量?

function ReadInt(varName) : integer
   Result := webbrowser.document.all.?????????? var Name  ?????
end;

r := ReadInt('_ANYINT');

以及如何写入?

感谢: dd

最佳答案

要从您的 html 示例中获取 _ANYINT 变量,请使用以下代码:

function Read_ANYINT: integer;
var
  v: OleVariant;
begin
  v := Browser.Document;
  Result := v.parentWindow._ANYINT;
end;

r := Read_ANYINT;

使用这段 html 代码:

<html>
<head>
<script>
var myVariable={name: "LA LA LA", x: 3, y: 5, mul: function () {return this.x * this.y}};
var myArray=["Yello", "Green"];
</script>
</head>
<body>
</body>
</html>

你可以在 delphi 中做:

var
  v: OleVariant;

...
  v := Browser.Document.parentWindow;
  ShowMessage(v.myVariable.name); // Will display LA LA LA
  ShowMessage(v.myVariable.mul()); // Will display 15

如果 HTML 页面是通过 file:/// 协议(protocol)加载的,上述代码将无法工作。要使其正常工作,您应该使用 http 协议(protocol)或首先将 WebBrowser 控件导航到 'about:blank',然后使用以下过程从字符串加载 HTML 文档:

procedure LoadHTML(aDocument: IDispatch; aStr: WideString);
type
  TRec = packed record
    Byte1,
    Byte2: Byte;
  end;
  PRec = ^TRec;
var
  lStream: IPersistStreamInit;
  lMemStream: TMemoryStream;
  p: Pointer;
  pp: PRec absolute p;
begin
  lStream := aDocument as IPersistStreamInit;

  //BOM
  GetMem(p, Length(aStr) * 2 + 2);
  pp.Byte1 := 255;
  pp.Byte2 := 254;
  CopyMemory(Pointer(Integer(p)+2), Pointer(aStr), Length(aStr) * 2);

  lMemStream := TMemoryStream.Create;
  try
    lMemStream.WriteBuffer(p^, Length(aStr) * 2 + 2);
    //lMemStream.WriteBuffer(Pointer(aStr)^, Length(aStr) * 2);
    lMemStream.Position := 0;
    lStream.Load(TStreamadapter.Create(lMemStream));
  finally
    FreeMem(p);
    FreeAndNil(lMemStream);
  end;
end;

要访问 JavaScript 数组,您必须处理 IDispath,这里是处理它的包装类:

unit jsobj;

interface

uses
 ActiveX;

type
 TJSArraySortFunc = function(elt1, elt2: OleVariant): Integer;
 TJSArraySortMethod = function(elt1, elt2: OleVariant): Integer of object;

 TJSArrayWrapper = class
 private
   FObject: OleVariant;
   FObjectInterface: IDispatch;
   function GetItem(Index: Integer): OleVariant;
   procedure SetItem(Index: Integer; const Value: OleVariant);
   function GetLength: Integer;
 public
   constructor Create(const AObject: OleVariant);

   property AsVariant: OleVariant read FObject;
   property AsInterface: IDispatch read FObjectInterface;
   property Item[Index: Integer]: OleVariant read GetItem write SetItem; default;
   function GetEnum: IEnumVARIANT;

   property Length: Integer read GetLength;
 end;

implementation

uses
 Windows,
 SysUtils,
 ComObj;

const
 NullGuid: TGuid = "{00000000-0000-0000-0000-000000000000}";
 NullParams: DISPPARAMS = (rgvarg: nil; rgdispidNamedArgs: nil; cArgs: 0; cNamedArgs: 0);

{ TJSArrayWrapper }

constructor TJSArrayWrapper.Create(const AObject: OleVariant);
begin
 FObject := AObject;
 FObjectInterface := IDispatch(FObject);
end;

function TJSArrayWrapper.GetEnum: IEnumVARIANT;
var
 Res: OleVariant;
begin
 OleCheck(
   FObjectInterface.Invoke(
     DISPID_NEWENUM,
     NullGuid,
     GetSystemDefaultLCID,
     DISPATCH_METHOD or DISPATCH_PROPERTYGET,
     NullParams,
     @Res,
     nil,
     nil
   )
 );
 Result := IUnknown(Res) as IEnumVARIANT;
end;

function TJSArrayWrapper.GetItem(Index: Integer): OleVariant;
var
 Member: WideString;
 DispId: DWORD;
begin
 Member := IntToStr(Index);
 OleCheck(
   FObjectInterface.GetIDsOfNames(
     NullGuid,
     @Member,
     1,
     GetSystemDefaultLCID,
     @DispId
   )
 );
 OleCheck(
   FObjectInterface.Invoke(
     DispId,
     NullGuid,
     GetSystemDefaultLCID,
     DISPATCH_PROPERTYGET,
     NullParams,
     @Result,
     nil,
     nil
   )
 );
end;

function TJSArrayWrapper.GetLength: Integer;
begin
 Result := FObject.length;
end;

procedure TJSArrayWrapper.SetItem(Index: Integer; const Value: OleVariant);
const
 ParamId: TDispId = DISPID_PROPERTYPUT;
var
 Member: WideString;
 DispId: TDispId;
 Params: DISPPARAMS;
begin
 Member := IntToStr(Index);
 OleCheck(
   FObjectInterface.GetIDsOfNames(
     NullGuid,
     @Member,
     1,
     GetSystemDefaultLCID,
     @DispId
   )
 );
 Params.rgvarg := @Value;
 Params.rgdispidNamedArgs := @ParamId;
 Params.cArgs := 1;
 Params.cNamedArgs := 1;
 OleCheck(
   FObjectInterface.Invoke(
     DispId,
     NullGuid,
     GetSystemDefaultLCID,
     DISPATCH_PROPERTYPUT or DISPATCH_PROPERTYPUTREF,
     Params,
     nil,
     nil,
     nil
   )
 );
end;

end.

用法:

var 
  v: OleVariant;
  i: Integer;

  v := Browser.Document.parentWindow;
  lArray := TJScriptArray.Create(v.myArray);
  try
    for i := 0 to lArray.Count - 1 do
    begin
      ShowMessage(lArray[i]);
    end;
  finally
    FreeAndNil(lArray);
  end;

关于javascript - Delphi:如何从 WebBrowser 访问(读取和写入)javascript 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6895667/

相关文章:

Delphi 组件创 build 计时间

delphi - 是否记录了 Set 类型的星号运算符?

delphi - 如何在运行时设计器中隐藏继承的已发布属性?

javascript - 使用 Javascript 更新复选框选择的输入字段

javascript - AngularJS观察div大小

html - 如何将 div 嵌套在 rails 中的 anchor 标记内

javascript - 如何正确指向 slider #

javascript - Codepen 片段无法在本地计算机上运行

javascript - JQuery Widget - 通过引用传递选项

Javascript a4 纸张大小