各们高手, 帮个忙 。 在此跪谢!!
以下是我的大致代码。BOOL EnumIE(HWND hWnd)  // 通过hwnd得到WebBrowser2接口
{
    CoInitialize(NULL);   
    SHDocVw::IShellWindowsPtr spShWinds; if (FAILED(spShWinds.CreateInstance(__uuidof(SHDocVw::ShellWindows))))
{
return FALSE;
} long nCount = spShWinds->GetCount();

for (int n = 0; n < nCount; n++)
{
IDispatchPtr spDisp;
_variant_t var = (long)n;
spDisp = spShWinds->Item(var);
SHDocVw::IWebBrowser2Ptr spBrowser(spDisp);             
if (spBrowser != NULL)
{
HWND hProcHwnd = NULL;
spBrowser->get_HWND((long*)&hProcHwnd);
if (hProcHwnd == hWnd)
{
                 ConnectIE(spBrowser);
} }
}
return TRUE;
}void ConnectIE(IUnknown *pUnkSite)  // 连接IE接口
{
HRESULT hr;
IWebBrowser2 *pSite; // the currently set site
if (pUnkSite)
pUnkSite->AddRef(); hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void**)&pSite);  // 得到WebBrowser接口
pUnkSite->Release();

if (FAILED(hr)) 
return; IConnectionPointContainer* pCPC;
IConnectionPoint *pCP;
hr = pSite->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
if (FAILED(hr)) 
  return; hr = pCPC->FindConnectionPoint(DIID_DWebBrowserEvents2,&pCP);  // 得到连接点
if (FAILED(hr)) 

pCPC->Release();
return;
} CComPtr<IUnknown> spUnk; //得到接受器接口
CSink theSink;
DWORD m_dwCookie; theSink.QueryInterface(IID_IUnknown, (LPVOID *)&spUnk);
hr = pCP->Advise(spUnk, &m_dwCookie);    // 建立连接     注意:  此处会失败。 if (FAILED(hr)) 
return;
}
以下是CSink 的代码; Sink.h
class CSink: public IDispatch
{
public:
CSink();
virtual ~CSink();
// IUnknown
STDMETHOD(QueryInterface)(const struct _GUID &iid,void ** ppv);
ULONG __stdcall AddRef(void);
ULONG __stdcall Release(void);
// IDispatch
STDMETHOD(GetTypeInfoCount)(unsigned int *);
STDMETHOD(GetTypeInfo)(unsigned int,unsigned long,struct ITypeInfo ** );
STDMETHOD(GetIDsOfNames)(const struct _GUID &,unsigned short ** ,unsigned int,unsigned long,long *);
STDMETHOD(Invoke)(long dispID,const struct _GUID &,unsigned long,unsigned short,
struct tagDISPPARAMS * pParams,struct tagVARIANT *,struct tagEXCEPINFO *,unsigned int *); STDMETHODIMP SetSite(IUnknown *pUnkSite);private:
DWORD m_dwCookie; // 连接的 cookie
};
以下是CSink 的代码; Sink.cppCSink::CSink()
{
}CSink::~CSink()
{

}
// STDMETHODIMP 是宏,等价于 long __stdcall
STDMETHODIMP CSink::QueryInterface(const struct _GUID &iid,void ** ppv)
{
*ppv=this;
return S_OK;
}ULONG __stdcall CSink::AddRef(void)
{ return 1; } ULONG __stdcall CSink::Release(void)
{ return 0; } STDMETHODIMP CSink::GetTypeInfoCount(unsigned int *)
{ return E_NOTIMPL; } STDMETHODIMP CSink::GetTypeInfo(unsigned int,unsigned long,struct ITypeInfo ** )
{ return E_NOTIMPL; } STDMETHODIMP CSink::GetIDsOfNames(const struct _GUID &,unsigned short ** ,unsigned int,unsigned long,long *)
{ return E_NOTIMPL; } STDMETHODIMP CSink::Invoke(
   long dispID,
   const struct _GUID &,
   unsigned long,
   unsigned short,
   struct tagDISPPARAMS * pParams,
   struct tagVARIANT *,
   struct tagEXCEPINFO *,
   unsigned int *)
{
MessageBox(NULL, "HAHA", "HAHA", MB_OK);
switch(dispID)
{
case 1:
break;
default:
break;
}
return S_OK;
}
调试N久都不知道是为什么连接不上, 求高手帮忙解疑。 谢谢!!

解决方案 »

  1.   

    Advise 返回错误时,查看一下错误号等
      

  2.   

    Advise 返回错误时,查看一下错误号等
    -------------------------------------
    谢谢你的回复。hr 返回的错误号是0x80004000 怎么得到通过错误号,得到错误信息? 貌似IConnectionPoint接口不支持
    ISupportErrorInfo。 
      

  3.   

    直接响应web browser对应的event事件。。 人家browser接口不一定支持你这么做
      

  4.   

    CSink theSink;
    改为CSink *theSink=new CSink;接收器对象是不能保存在栈中,因为ConnectIE()执行完毕,就会被释放了。必须保存在堆中。
      

  5.   

    还有,即使成功advise,但也没啥用,因为没有ie认可的事件。
      

  6.   

    谢谢 sgzwiz 的回复.这个我试过. 也会失败. 还有,即使成功advise,但也没啥用,因为没有ie认可的事件。
    ---------------------------------------------------
    这个是什么意思? 为什么成功advise后也会没有用. 没有IE认可的事件? 指的是什么? 
      

  7.   


    真接响应web browser事件不是我想要做的. 我想做的是监测IE的DISPID_BEFORENAVIGATE2 事件, 以达到网址URL 过滤的功能.
      

  8.   

    你要过滤IE的,可以做IE BHO 插件等,然后处理DISPID_BEFORENAVIGATE2事件等,来过滤URL
      

  9.   

    ----------------------------------------------------BHO的方式我已经实现,   只不过我认为也可以通过SINK的方式去实现. 
      

  10.   

    STDMETHODIMP CSink::GetTypeInfoCount(unsigned int *)
    { return E_NOTIMPL; } STDMETHODIMP CSink::GetTypeInfo(unsigned int,unsigned long,struct ITypeInfo ** )
    { return E_NOTIMPL; } STDMETHODIMP CSink::GetIDsOfNames(const struct _GUID &,unsigned short ** ,unsigned int,unsigned long,long *)
    { return E_NOTIMPL; } 
    这些必须实现,advise时需要调用这些method。
      

  11.   

    CSink的Invoke可以这样实现
    STDMETHODIMP CSink::Invoke(DISPID dispidMember, REFIID riid, LCID lcid,
                                    WORD wFlags,
                                    DISPPARAMS* pDispParams, VARIANT* pvarResult,
                                    EXCEPINFO*  pExcepInfo,  UINT* puArgErr)
    {
    USES_CONVERSION;

    if (!pDispParams)
    return E_INVALIDARG;

    //
    // Get the current URL
    //  
    LPOLESTR lpURL = NULL;
    m_spWebBrowser2->get_LocationURL(&lpURL);

    switch (dispidMember)
    {
    //
    // The parameters for this DISPID are as follows:
    // [0]: Cancel flag  - VT_BYREF|VT_BOOL
    // [1]: HTTP headers - VT_BYREF|VT_VARIANT
    // [2]: Address of HTTP POST data  - VT_BYREF|VT_VARIANT 
    // [3]: Target frame name - VT_BYREF|VT_VARIANT 
    // [4]: Option flags - VT_BYREF|VT_VARIANT
    // [5]: URL to navigate to - VT_BYREF|VT_VARIANT
    // [6]: An object that evaluates to the top-level or frame
    //      WebBrowser object corresponding to the event. 
    //
    case DISPID_BEFORENAVIGATE2:

    char *str;
    if (pDispParams->cArgs >= 5 && pDispParams->rgvarg[5].vt == (VT_BYREF|VT_VARIANT))
    {
                CComVariant varURL(*pDispParams->rgvarg[5].pvarVal);
                varURL.ChangeType(VT_BSTR);
    //转化要访问的网址为char *型
    str = OLE2A(varURL.bstrVal);
    }
    //如果正要访问的网址为要被拦截的,则stop
    if(strstr(str,"163.net")!=NULL)
    {
                *pDispParams->rgvarg[0].pboolVal = TRUE;
        MessageBox(NULL,"当前系统禁止浏览该页","警告",MB_ICONSTOP);
    return S_OK;
    }

    break;

    //
    // The parameters for this DISPID:
    // [0]: URL navigated to - VT_BYREF|VT_VARIANT
    // [1]: An object that evaluates to the top-level or frame
    //      WebBrowser object corresponding to the event. 
    //
    case DISPID_NAVIGATECOMPLETE2:

    break; case DISPID_DOCUMENTCOMPLETE:
    break;

    case DISPID_DOWNLOADBEGIN:
    break;

    case DISPID_DOWNLOADCOMPLETE:
    break;

    case DISPID_NEWWINDOW2:
    //设置是否允许弹出窗口
    /*READYSTATE m_ReadyState;
            m_spWebBrowser2->get_ReadyState(&m_ReadyState);
            if (m_ReadyState!=READYSTATE_COMPLETE)
            {
                *pDispParams->rgvarg[0].pboolVal = TRUE;
                return S_OK;
            }
    else
    {
                *pDispParams->rgvarg[0].pboolVal = FALSE;
                return S_OK;
    }*/
        break;

    // The parameters for this DISPID:
    // [0]: Address of cancel flag - VT_BYREF|VT_BOOL
    //
    case DISPID_QUIT:

    break;

    default:

    break;
    }

    return S_OK;
    }
      

  12.   


    这些函数要实现? advise时需要调用这些method.   那应该怎么实现才能满足advise调用呢?
      

  13.   

    atl中默认实现了的,把你的类从 IDispatchImpl 派生就可以了。