EmbeddedWb不能完全屏蔽脚本错误的修改

  EmbeddedWb的版本有点看不懂。。。。。。

 EmbeddedWb v14是可以完全屏蔽脚本错误,但问题多多,在多人使用环境下错误多多。



不得已用v13,稳定,但脚本错误经常跳出来。



  找了很多地方,也改了不少属性,失败。

  看到这篇,是好方法:

  http://www.winu.cn/space-14160-do-blog-id-14070.html###





-----------------------------------------------------------------------------

    EmbeddedWb(ver 1.16b)的一个BUG



按照文档,当有脚本错误产生时EmbeddedWb会触发OnScriptError事件. 这个问题好模拟,顺便建个文本文件,改名.html,然后输入:
<script language="JavaScript">
  alert("Hello!")111;
</script>
最后用EmbeddedWb来访问这个HTML,就可以在它的OnScriptError中抓到这个事件.

这是最一般的情况.如果我们把这个HTML作为一个帧(Frame)给其它的HTML用,然后让EmbeddedWb访问那个HTML,这时候就抓不到错误了,只能由IE的来弹出错误对话框.

我开始不知道问题出在哪,不停地去盯EmbeddedWb的那些属性,看有没有相关的东西.最后找到眼睛痛也没结果.

后来跟踪了OnScriptError里边的代码才总算知道原因在哪了:
  case nCmdID of
  OLECMDID_SHOWSCRIPTERROR:
  if Assigned(FOnScriptError)
  then begin
  pEventObj := (Document as IHTMLDocument2).parentWindow.event;
  if pEventObj <> nil then
  begin
  ...
这段代码在EmbeddedWb.pas大概2000行的位置.我的已经改过所以只好说"大概".
当错误的脚本在Frame中时,pEventObj得到的总是nil,所以程序根本没跑下去就出去了.

这显然是EmbeddedWb的一个BUG,哈哈

我当时以为Document就是产生错误的那个HTML,并且以为parentWindow.event里的event应该是最顶层的window里的event,所以用了parentWindow.top.event来取值,结果没取到.
接下来以为这个top有问题,改用循环,也就是
  htmlWin2 := (Document as IHTMLDocument2).parentWindow;
  while htmlWin2.parent <> htmlWin2 do
  htmlWin2 := htmlWin2.parent;
  pEventObj := htmlWin2.event;
来取值,还是没有取到.

:(

后来把document的内容显示出来,发现这个document就是最顶层的那个:
  Dialogs.ShowMessage((Document as IHTMLDocument2).body.innerHTML);

这样思路就清晰了,只要从这个document开始找它的event,如果找不到就看它有没有Frame,遍历每个Frame,包括Frame下面的Frame,这样最终就能够把产生脚本错误的那个Document找出来.

用一个递归来实现上面的思路:
  function GetEventObj(htmlDoc2: IHTMLDocument2; EventType: WideString): IHTMLEventObj;
  var
  i: Integer;
  OleIndex: OleVariant;
  frameDispatch: IDispatch;
  pEvent: IHTMLEventObj;
  begin
  Result := nil;
  //先判断它自己有没有事件发生
  pEvent := htmlDoc2.parentWindow.event;
  if pEvent <> nil then
  if pEvent.type_ = EventType then
  begin
  Result := pEvent;
  Exit;
  end;
  //如果没有,就找它的帧
  for i := 0 to htmlDoc2.Frames.Length - 1 do
  begin
  OleIndex := i;
  frameDispatch := htmlDoc2.Frames.Item(OleIndex);
  if Assigned(frameDispatch) then
  begin
  pEvent := GetEventObj((frameDispatch as IHTMLWindow2).document, EventType);
  if pEvent <> nil then
  begin
  Result := pEvent;
  Break;
  end;
  end;
  end;
  end;

最后改一下调用:
  case nCmdID of
  OLECMDID_SHOWSCRIPTERROR:
  if Assigned(FOnScriptError)
  then begin
  //pEventObj := (Document as IHTMLDocument2).parentWindow.event;
  pEventObj := GetEventObj(Document as IHTMLDocument2, 'error');
  if pEventObj <> nil then
  begin
  ...

问题终于解决. 嘿嘿...



-----------------------------------------------------------------------------





问题是,我按文中所写加入GetEventObj,运行,竟然出现“拒绝访问”,
按说是跨域问题,但我的应用不是跨域。

反复试验不得解决。


后来想,是因为pEventObj=nil才不会触发事件,那我自已处理它就
可以了。所以,按下面改了一下,可以了!

原文:


  pEventObj := (Document as IHTMLDocument2).parentWindow.event;
   
  if pEventObj <> nil then
  begin
  FContinueScript := True;
  FShowDialog := False;
  FOnScriptError(self,
  GetProperty('errorline'),
  GetProperty('errorCharacter'),
  GetProperty('errorCode'),
  GetProperty('errorMessage'),
  GetProperty('errorUrl'),
  FContinueScript, FShowDialog);
  TVariantArg(vaOut).vt := VT_BOOL;
  TVariantArg(vaOut).vbool := FContinueScript;
  if not FShowDialog then Result := S_OK;
  end ;


改后:


  pEventObj := (Document as IHTMLDocument2).parentWindow.event;
   
  if pEventObj <> nil then
  begin
  FContinueScript := True;
  FShowDialog := False;
  FOnScriptError(self,
  GetProperty('errorline'),
  GetProperty('errorCharacter'),
  GetProperty('errorCode'),
  GetProperty('errorMessage'),
  GetProperty('errorUrl'),
  FContinueScript, FShowDialog);
  TVariantArg(vaOut).vt := VT_BOOL;
  TVariantArg(vaOut).vbool := FContinueScript;
  if not FShowDialog then Result := S_OK;
  end else
  begin

  FContinueScript := True;
  FShowDialog := False;
  FOnScriptError(self,
  '',
  '',
  '',
  '未知的错误(我的:))',
  self.LocationURL,
  FContinueScript, FShowDialog);
  TVariantArg(vaOut).vt := VT_BOOL;
  TVariantArg(vaOut).vbool := FContinueScript;
  if not FShowDialog then Result := S_OK;
  end;


Delphi第三方控件EmbeddedWB,这是一个不错的浏览器控件,比Delphi自带的Webbrowser要强悍 EmbeddedWB安装方法: 1.下载压缩包,飘易下载的是EmbeddedWB v14.67.0版本,下载地址:http://www.delphifans.com/SoftView/SoftView_2705.html。 2.解压整个压缩包到 lib\EmbeddedWB 下; 3.复制 lib\EmbeddedWB 下的Packages目录中的EmbeddedWebBrowser_D2007.dpk(因为飘易使用的是DELPHI2007)到Source目录里; 4.用Delphi7开发环境打开 EmbeddedWebBrowser_D2007.dpk 文件,按Optios按钮,作如下调整: Directories/Conditionals标签Unit Output Dir=“D:\Program Files\CodeGear\RAD Studio\5.0\lib\EmbeddedWB\Source”(具体路径自行决定); 5.按Compile 再按Install; 6.不要保存变化了的dpk文件及压缩包; 7.在具体的编译工程时,需检查该源目录(D:\Program Files\CodeGear\RAD Studio\5.0\lib\EmbeddedWB\Source)在 Delphi IDE 的 "Search Path" 路径里(Project -> Options -> irectories/Conditionals -> Search Path); 如果没有,添加这个源目录路径。否则,在使用该控件的时候,出现“File not found: 'SHDocVw_EWB.dcu'” 错误。 8.可以正常使用了。 这里还有一篇别人的“Embedded Web Browser Delphi组件的安装”,不过是把TEmbeddedWB控件安装到 Delphi7 里的。 下面是D2005 installing steps:1.After downloading Unzip the package. 2. Put the folder that contain the package in the path "..:\Borland\BDS\3.0\lib" 3. Open Delphi IDE and press in the menu bar On: File --> "Open" In the open dialog navigate to the path where you store your package to the source folder("..:\Borland\BDS\3.0\lib\EmbeddedWB_D2005\Source"). 5.Choose file name "EmbeddedWebBrowser_D2005.dpk" and press open. 6.In the project manager (in the right corner) point with your mouse on the top file ("EmbeddedWebBrowser_D2005.bdsproj"). Then Right click and choose "Build" 7. And last In the same file & menu Press install. 8. Do not save the package changes. 9. You should make sure that the source folder is in the Delphi IDE "Search Path". If not You must add it.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值