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;
EmbeddedWb不能完全屏蔽脚本错误的修改
最新推荐文章于 2018-09-27 08:59:52 发布