各们高手, 帮个忙 。 在此跪谢!!
以下是我的大致代码。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久都不知道是为什么连接不上, 求高手帮忙解疑。 谢谢!!
以下是我的大致代码。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久都不知道是为什么连接不上, 求高手帮忙解疑。 谢谢!!
-------------------------------------
谢谢你的回复。hr 返回的错误号是0x80004000 怎么得到通过错误号,得到错误信息? 貌似IConnectionPoint接口不支持
ISupportErrorInfo。
改为CSink *theSink=new CSink;接收器对象是不能保存在栈中,因为ConnectIE()执行完毕,就会被释放了。必须保存在堆中。
---------------------------------------------------
这个是什么意思? 为什么成功advise后也会没有用. 没有IE认可的事件? 指的是什么?
真接响应web browser事件不是我想要做的. 我想做的是监测IE的DISPID_BEFORENAVIGATE2 事件, 以达到网址URL 过滤的功能.
{ 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。
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;
}
这些函数要实现? advise时需要调用这些method. 那应该怎么实现才能满足advise调用呢?