te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>html - Delphi: How reach (read and write) javascript variable from WebBrowser - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - Delphi: How reach (read and write) javascript variable from WebBrowser - Stack Overflow

programmeradmin4浏览0评论

I created a webpage, and I want to access a html page's javascript variable for R/W.

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

How can I read a variable?

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

r := ReadInt('_ANYINT');

And how to write into?

Thanks: dd

I created a webpage, and I want to access a html page's javascript variable for R/W.

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

How can I read a variable?

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

r := ReadInt('_ANYINT');

And how to write into?

Thanks: dd

Share Improve this question asked Aug 1, 2011 at 8:05 durumdaradurumdara 3,4735 gold badges45 silver badges71 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 10

To get _ANYINT variable from your html sample use this code:

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

r := Read_ANYINT;

With this html code:

<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>

You can do in delphi:

var
  v: OleVariant;

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

The above code will not work if HTML page was loaded via file:/// protocol. To get it working you should use http protocol or first navigate WebBrowser control to 'about:blank' and after that load HTML document from string using this procedure:

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;

To access JavaScript arrays you have to deal with IDispath, here is wrapper class to handle it:

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.

Usage:

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;

You can retrieve the value of globally defined variables by querying the IHTMLWindow for it.

Let's assume this simple page:

<html>
<head>
<script>
  var myVariable=42;
</script>
</head>
<body>
</body>
</html>

Using the TWebBrowser ponent you can get the value of myVariable this way:

uses
  MSHTML, ActiveX;

// Proper error checking omitted for brevity.
var
  Window: IHTMLWindow2;
  DispatchIdOfProperty: Integer;
  MyPropertyValue: OleVariant;
  Temp: TExcepInfo;
  Res: Integer;
  Params:TDispParams;
begin
  // get window interface
  Window:= (WebBrowser1.ControlInterface.Document as IHTMLDocument2).parentWindow;
  Assert(Assigned(Window));
  // get dispatch ID of our variable
  if (Window as IDispatchEx).GetDispID('myVariable', fdexNameCaseSensitive, DispatchIdOfProperty) = S_OK then
  begin
    // no parameters
    ZeroMemory(@Params, SizeOf(Params));
    // get value of our variable
    Res:=(Window as IDispatchEx).InvokeEx(DispatchIdOfProperty, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, @Params, MyPropertyValue, Temp, nil);
    if Res=S_OK then
    begin
      // voila - this should display the value
      ShowMessage(MyPropertyValue);
    end else
      ShowMessage('Error reading property value');
  end
  else
    ShowMessage('Property not found');
end;

The variant MyPropertyValue contains 42 for above HTML.

Writing the variable is similar. Just use DISPATCH_PROPERTYPUT in your InvokeEx call:

Edit: Code for setting.

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');

In case you wonder: a special named property is used to cover some cases where automation servers fail to distinguish between DISPATCH_PROPERTYPUT and DISPATCH_PROPERTYGET.

The HTMLWindow interface exposes an execScript function that permits the execution of javascript code inside the WebBrowser document. See http://delphi.about./od/adptips2006/qt/wb_execscript.htm , for example.

Unfortunately, execScript does not allow for a result be returned.

So, to access javascript data, you will need that in your javascript you write some function that puts the desired data into a hidden field in the page and then from your Delphi you access the field via WebBrowser. Here is some example code on how to do it. http://www.delphidabbler./articles?article=21&part=1#retval

发布评论

评论列表(0)

  1. 暂无评论