我正在基于this回答实现TWebBrowser的Exec方法。每当发生脚本错误时都会触发此方法。现在我需要获取错误信息。
我首先掌握了TWebBrowser的事件对象。
var
Doc: IHTMLDocument2;
HTMLWindow: IHTMLWindow2;
Event: IHTMLEventObj;
MethodName: String;
MethodResult: OleVariant;
DispatchId: Integer;
Param: array of OleVariant;
begin
//Avoid non-error calls
if nCmdID != OLECMDID_SHOWSCRIPTERROR then
Exit;
//Get hold of the event object
Doc := MapForm.WebBrowser.Document as IHTMLDocument2;
if not Assigned(Doc) then
Exit;
HTMLWindow := Doc.parentWindow;
if not Assigned(HTMLWindow) then
Exit;
//Get the current event
Event := HTMLWindow.event;
然后我尝试使用接口的GetIDsOfNames
和Invoke
函数获取我需要的信息(如this链接中所示)。使用这些方法的工作Delphi代码位于this文档链接中。
以下是我在Event对象上使用这些函数的方法。
MethodName := 'errorMessage';
Result := Event.GetIDsOfNames(GUID_NULL, @MethodName, 1, SysLocale.DefaultLCID, @DispatchId);
Result := Event.Invoke(DispatchId, GUID_NULL, SysLocale.DefaultLCID, DISPATCH_METHOD, Param, @MethodResult, nil, nil);
GetIDsOfNames
fuGetIDsOfNames函数正确执行,输出一个可接受的整数DispatchId
并返回S_OK
。
但Invoke
函数失败了。它返回一些负整数HRESULT
,并且不向MethodResult
输出任何内容。
我该如何解决这个问题?
答案 0 :(得分:1)
您尝试访问的错误值不是对象方法,而是属性,因此Invoke()
因使用DISPATCH_METHOD
而失败。请改用DISPATCH_PROPERTYGET
。
但是,OleVariant
(和Variant
)内置了对IDispatch.Invoke()
的支持,因此您根本不需要手动处理它。您可以正常调用对象方法和读/写对象属性,编译器将为您生成必要的IDispatch
调用。
尝试更像这样的事情:
function TWebBrowser.Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD;
const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall;
var
Event: OleVariant;
ErrorLine: Integer;
ErrorChar: Char;
ErrorCode: Integer;
ErrorMsg: String;
ErrorUrl: String;
begin
if (CmdGroup = nil) or not IsEqualGUID(CmdGroup^, CGID_DocHostCommandHandler) then
begin
Result := OLECMDERR_E_UNKNOWNGROUP;
Exit;
end;
if nCmdID <> OLECMDID_SHOWSCRIPTERROR then
begin
Result := OLECMDERR_E_NOTSUPPORTED;
Exit;
end;
Event := (IUnknown(vaIn) as IHTMLDocument2).parentWindow.event;
ErrorLine := Event.errorLine;
ErrorChar := Event.errorCharacter;
ErrorCode := Event.errorCode;
ErrorMsg := Event.errorMessage;
ErrorUrl := Event.errorUrl;
...
if (should continue running scripts) then
begin
vaOut := True;
end else
begin
vaOut := False;
end;
Result := S_OK;
end;