先送100,问题解决后再加100
问题:
我用BHO做的COM,先用TIEHelper.invoke来处理它的IE事件,直到一个HTML文档DOCUMENTCOMPLETE时,再用TWEBEvents.invoke来处理HTML文档的事件以便监视文档中按钮的按下。可是在Advise(WEBEvents as IUnknown,Cook);时出错:'access violation at 0x0181c663:read of address 0x00000000'
//绑定IE事件!
function TIEBrowserHelper.SetSite(const pUnkSite: IUnknown): HResult;
var
  CPC: IConnectionPointContainer;
begin
  if Assigned(pUnkSite) then
  begin
    TIE:=TIEBrowserHelper.create();
    
    IE := pUnkSite as IWebbrowser2;
    CPC := IE as IConnectionPointContainer;
    CPC.FindConnectionPoint(DWebBrowserEvents2, CP);
    CP.Advise(SELF as iunknown,cookie);
  end;
  Result := S_OK
end;
//处理IE事件!
function TIEBrowserHelper.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult;
type
  POleVariant = ^OleVariant;
var
  dps: TDispParams absolute Params;
  bHasParams: boolean;
  pDispIds: PDispIdList;
  iDispIdsSize: integer;
begin
  pDispIds := nil;
  iDispIdsSize := 0;
  bHasParams := (dps.cArgs > 0);
  if (bHasParams) then
  begin
    iDispIdsSize := dps.cArgs * SizeOf(TDispId);
    GetMem(pDispIds, iDispIdsSize);
  end;
  try
    if (bHasParams) then BuildPositionalDispIds(pDispIds, dps);
    Result := S_OK;
    case DispId of
      DISPID_STATUSTEXTCHANGE: DoStatusTextChange(dps.rgvarg^[pDispIds^[0]].bstrval);
      DISPID_PROGRESSCHANGE: DoProgressChange(dps.rgvarg^[pDispIds^[0]].lval, dps.rgvarg^[pDispIds^[1]].lval);
      DISPID_COMMANDSTATECHANGE: DoCommandStateChange(dps.rgvarg^[pDispIds^[0]].lval, dps.rgvarg^[pDispIds^[1]].vbool);
      DISPID_DOWNLOADBEGIN: DoDownloadBegin();
      DISPID_DOWNLOADCOMPLETE: DoDownloadComplete();
      DISPID_TITLECHANGE: DoTitleChange(dps.rgvarg^[pDispIds^[0]].bstrval);
      DISPID_PROPERTYCHANGE: DoPropertyChange(dps.rgvarg^[pDispIds^[0]].bstrval);      DISPID_BEFORENAVIGATE2: DoBeforeNavigate2(IDispatch(dps.rgvarg^[pDispIds^[0]].dispval), POleVariant(dps.rgvarg^[pDispIds^[1]].pvarval)^, POleVariant(dps.rgvarg^[pDispIds^[2]].pvarval)^, POleVariant(dps.rgvarg^[pDispIds^[3]].pvarval)^, POleVariant(dps.rgvarg^[pDispIds^[4]].pvarval)^, POleVariant(dps.rgvarg^[pDispIds^[5]].pvarval)^, dps.rgvarg^[pDispIds^[6]].pbool^);
      DISPID_NEWWINDOW2: DoNewWindow2(IDispatch(dps.rgvarg^[pDispIds^[0]].pdispval^), dps.rgvarg^[pDispIds^[1]].pbool^);
      DISPID_NAVIGATECOMPLETE2: DoNavigateComplete2(IDispatch(dps.rgvarg^[pDispIds^[0]].dispval), POleVariant(dps.rgvarg^[pDispIds^[1]].pvarval)^);      //调用DocumentComplete时处理过程DoDocumentComplete
      DISPID_DOCUMENTCOMPLETE: DoDocumentComplete(IDispatch(dps.rgvarg^[pDispIds^[0]].dispval), POleVariant(dps.rgvarg^[pDispIds^[1]].pvarval)^);      DISPID_ONVISIBLE: DoOnVisible(dps.rgvarg^[pDispIds^[0]].vbool);
      DISPID_ONTOOLBAR: DoOnToolBar(dps.rgvarg^[pDispIds^[0]].vbool);
      DISPID_ONMENUBAR: DoOnMenuBar(dps.rgvarg^[pDispIds^[0]].vbool);
      DISPID_ONSTATUSBAR: DoOnStatusBar(dps.rgvarg^[pDispIds^[0]].vbool);
      DISPID_ONFULLSCREEN: DoOnFullScreen(dps.rgvarg^[pDispIds^[0]].vbool);
      DISPID_ONTHEATERMODE: DoOnTheaterMode(dps.rgvarg^[pDispIds^[0]].vbool);
      DISPID_WINDOWSETRESIZABLE: DoWindowSetResizable(dps.rgvarg^[pDispIds^[0]].vbool);
      DISPID_WINDOWCLOSING: DoWindowClosing(dps.rgvarg^[pDispIds^[0]].vbool, dps.rgvarg^[pDispIds^[1]].pbool^);
      DISPID_WINDOWSETLEFT: DoWindowSetLeft(dps.rgvarg^[pDispIds^[0]].lval);
      DISPID_WINDOWSETTOP: DoWindowSetTop(dps.rgvarg^[pDispIds^[0]].lval);
      DISPID_WINDOWSETWIDTH: DoWindowSetWidth(dps.rgvarg^[pDispIds^[0]].lval);
      DISPID_WINDOWSETHEIGHT: DoWindowSetHeight(dps.rgvarg^[pDispIds^[0]].lval);
      DISPID_CLIENTTOHOSTWINDOW: DoClientToHostWindow(dps.rgvarg^[pDispIds^[0]].plval^, dps.rgvarg^[pDispIds^[1]].plval^);
      DISPID_SETSECURELOCKICON: DoSetSecureLockIcon(dps.rgvarg^[pDispIds^[0]].lval);
      DISPID_FILEDOWNLOAD: DoFileDownload(dps.rgvarg^[pDispIds^[0]].pbool^);      DISPID_ONQUIT:        begin
          DoOnQuit();
          CP.Unadvise(Cookie);
        end;
    else
      Result := DISP_E_MEMBERNOTFOUND;
    end;
  finally
    if (bHasParams) then FreeMem(pDispIds, iDispIdsSize);
  end;
end;
//DoDocumentComplete时绑定HTML文档并用Invoke来响应事件
procedure DoDocumentComplete(const pDisp: IDispatch; var URL: OleVariant);
var
  CPC: IConnectionPointContainer;
  WEBEvents:TWEBEvents;
begin  WEBEvents:=TWEBEvents.Create();
  if Assigned(IE) then
  begin
    IH:=IE.document as IHTMLdocument2;
    CP.Unadvise(Cookie);
    CPC := IH as IConnectionPointContainer;
    CPC.FindConnectionPoint(HTMLButtonElementEvents2,C);
//下一句出错
    C.Advise(WEBEvents as IUnknown, cookie);  end;
end;
//TWEBEvents的定义
TWEBEvents = class(TComObject,IDispatch)
  protected
    function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
    function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
    function GetIDsOfNames(const IID: TGUID; Names: Pointer;
      NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
    function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
      Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; virtual; stdcall;
end;   //TIEBrowserHelper定义
TIEBrowserHelper = class(TComObject, IDispatch, IObjectWithSite)
  protected
    function SetSite(const pUnkSite: IUnknown): HResult; stdcall;
    function GetSite(const riid: TIID; out site: IUnknown): HResult; stdcall;    function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
    function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
    function GetIDsOfNames(const IID: TGUID; Names: Pointer;
      NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
    function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
      Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; virtual; stdcall;
  end;