Delphi:如何从WebBrowser访问(读写)javascript变量
我创建了一个网页,我想访问一个html页面的javascript变量进行R/WDelphi:如何从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
...
<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;