Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi:如何从WebBrowser访问(读写)javascript变量_Javascript_Html_Delphi_Variables - Fatal编程技术网

Delphi:如何从WebBrowser访问(读写)javascript变量

Delphi:如何从WebBrowser访问(读写)javascript变量,javascript,html,delphi,variables,Javascript,Html,Delphi,Variables,我创建了一个网页,我想访问一个html页面的javascript变量进行R/W ... <script> var _ANYINT = 0; var _ANYOBJ = 0; </script> ... 怎么写呢 谢谢: dd该HTMLWindow接口公开了一个execScript函数,该函数允许在WebBrowser文档中执行javascript代码。例如,见 不幸的是,execScript不允许返回结果 因此,要访问javascript数据,您需要在javas

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

...
<script>
  var _ANYINT = 0;
  var _ANYOBJ = 0;
</script>
...
怎么写呢

谢谢:
dd

HTMLWindow
接口公开了一个
execScript
函数,该函数允许在WebBrowser文档中执行javascript代码。例如,见

不幸的是,
execScript
不允许返回结果


因此,要访问javascript数据,您需要在javascript中编写一些函数,将所需数据放入页面中的隐藏字段,然后从Delphi通过WebBrowser访问该字段。下面是一些关于如何操作的示例代码

您可以通过查询IHTMLWindow来检索全局定义变量的值

让我们假设这个简单的页面:

<html>
<head>
<script>
  var myVariable=42;
</script>
</head>
<body>
</body>
</html>
变量
MyPropertyValue
包含42个用于上述HTML

编写变量与此类似。只需在
InvokeEx
调用中使用
DISPATCH\u PROPERTYPUT

编辑:设置代码

const
  IID_NULL: TGUID = '{00000000-0000-0000-0000-000000000000}';
  DISPID_PROPERTYPUT: Integer = -3;
var
  NewValue, Dummy: OleVariant;

if (Window as IDispatchEx).GetDispID('myVariable', fdexNameCaseSensitive, DispatchIdOfProperty) = S_OK then
begin
  NewValue:= 84;
  Params.rgvarg:= @NewValue;
  Params.rgdispidNamedArgs:= @DISPID_PROPERTYPUT;
  Params.cArgs:= 1;
  Params.cNamedArgs:= 1;
  if (Window as IDispatchEx).InvokeEx(DispatchIdOfProperty, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, @Params, Dummy, Temp, nil) <> S_OK then
    Showmessage('Setting property value failed');
end else
  Showmessage('Property not found');
const
IID_NULL:TGUID='{00000000-0000-0000-0000-000000000000}';
DISPID_PROPERTYPUT:Integer=-3;
变量
NewValue,Dummy:OleVariant;
如果(窗口为IDispatchEx).GetDispID('myVariable',fdexNameCaseSensitive,DispatchIdOfProperty)=S_确定,则
开始
新值:=84;
参数rgvarg:=@NewValue;
参数rgdispidNamedArgs:=@DISPID\u PROPERTYPUT;
参数cArgs:=1;
参数cNamedArgs:=1;
如果(窗口为IDispatchEx).InvokeEx(DispatchIdOfProperty,LOCALE\u USER\u DEFAULT,DISPATCH\u PROPERTYPUT,@Params,Dummy,Temp,nil)S\u确定,则
Showmessage('设置属性值失败');
结束其他
Showmessage(“未找到属性”);

如果您想知道:在自动化服务器无法区分
DISPATCH\u PROPERTYPUT
DISPATCH\u PROPERTYGET
DISPATCH\u PROPERTYGET

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

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>
如果通过
文件://
协议加载HTML页面,则上述代码将不起作用。要使其正常工作,您应该使用
http
协议,或者首先将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;

我知道我可以访问字段,但我不知道是否可以在隐藏字段值中存储对象、数组?谢谢:ddAs我看到隐藏的输入字段不能只存储字符串。所以我不能把“数组”放进去。。。这不太好…这个答案不正确。Eugene的回答说明了如何做到这一点。这对我不起作用:窗口(作为IDispatchEx)失败了…:-(确切的错误消息是什么?我是在Windows 7上安装Internet Explorer 9时发出的。您?Project 1.exe引发了异常类EIntfCastError,消息为“Interface not supported”。进程已停止。请使用步骤或运行继续。Win7、Delphi6、IE9、x64。
窗口是否支持
IDispatch
(不带“Ex”)?我必须使用“”来读取变量,谢谢!但是“ShowMessage(v.myVariable.name)”不起作用:自动化对象不支持方法“myVariable”。
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;
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;