IDispEventImpl包装方法对Ajax相当无力,也就是说对Flash也是没辙,娘的又走了弯路,作为几天的总结,IDispEventImpl包装的方法如下: MyRock.h // MyRock.h : Declaration of the CMyRock #pragma once #include "resource.h" // main symbols #include "RockBHO_i.h" #include <shlguid.h> // IID_IWebBrowser2、DIID_DWebBrowserEvents2等 #include <exdispid.h> // IDispEventImpl 用于事件处理的新派生 #include <mshtml.h> // DOM 接口 #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA) #error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms." #endif // CMyRock class ATL_NO_VTABLE CMyRock : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CMyRock, &CLSID_MyRock>, public IObjectWithSiteImpl<CMyRock>, public IDispatchImpl<IMyRock, &IID_IMyRock, &LIBID_RockBHOLib, /*wMajor =*/ 1, /*wMinor =*/ 0>, public IDispEventImpl<1, CMyRock, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>, { public: CMyRock():m_spWebBrowser(NULL), m_fAdvised(FALSE), m_nVersion(0), m_hwndDlg(0) { m_pMyRock = this; } ~CMyRock() { DestroyDlg(); } DECLARE_REGISTRY_RESOURCEID(IDR_MYROCK1) DECLARE_NOT_AGGREGATABLE(CMyRock) // 接口注册,就是需要什么到什么地方找 BEGIN_COM_MAP(CMyRock) COM_INTERFACE_ENTRY(IMyRock) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IObjectWithSite) END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } public: STDMETHOD(SetSite)(IUnknown *pUnkSite); void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL); void STDMETHODCALLTYPE OnBeforeNavigate2(IDispatch *pDisp, VARIANT *pvarURL, VARIANT *Flags,VARIANT *TargetFrameName,VARIANT *PostData, VARIANT *Headers, VARIANT_BOOL *Cancel); /* void STDMETHODCALLTYPE OnCommandStateChange(long lCommand, VARIANT_BOOL bEnable){} void STDMETHODCALLTYPE OnNewWindow3(IDispatch **ppDisp,VARIANT_BOOL *Cancel,DWORD dwFlags,BSTR bstrUrlContext,BSTR bstrUrl){} void STDMETHODCALLTYPE OnDownloadBegin(){} void STDMETHODCALLTYPE OnNavigateComplete(IDispatch* pDisp, VARIANT* URL){} void STDMETHODCALLTYPE OnNavigateProgress(long Progress,long ProgressMax){} void STDMETHODCALLTYPE OnTitleChange(BSTR Text){} void STDMETHODCALLTYPE OnStatusTextChange(BSTR Text){} */ BEGIN_SINK_MAP(CMyRock) /* 打开网页调用顺序 OnBeforeNavigate2 OnDownloadBegin OnNavigateComplete OnNavigateProgress OnDocumentComplete SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_NAVIGATECOMPLETE2, OnNavigateComplete) // 网页打开完毕时调用 SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOWNLOADBEGIN, OnDownloadBegin) // 下载时调用,无视Ajax SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_PROGRESSCHANGE, OnNavigateProgress) // 进程相关 SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_COMMANDSTATECHANGE, OnCommandStateChange) // 前进后退 SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_TITLECHANGE, OnTitleChange) // 标题栏改变时调用 SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_STATUSTEXTCHANGE, OnStatusTextChange) // 状态栏改变时调用 */ SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_BEFORENAVIGATE2, OnBeforeNavigate2) // 网页打开之前时调用 SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete) // 网页打开完毕时调用 END_SINK_MAP() // DWebBrowserEvents2 private: CComPtr<IWebBrowser2> m_spWebBrowser; BOOL m_fAdvised; long m_nVersion; HWND m_hwndDlg; int GetIEVersion(); HWND GetMenuParentIE8(); void CreateDlg(); void DestroyDlg(); static INT_PTR CALLBACK CMyRock::DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static CMyRock* m_pMyRock; }; CMyRock* CMyRock::m_pMyRock = 0; OBJECT_ENTRY_AUTO(__uuidof(MyRock), CMyRock) MyRock.cpp // MyRock.cpp : Implementation of CMyRock #include "stdafx.h" #include "MyRock.h" // CMyRock STDMETHODIMP CMyRock::SetSite(IUnknown* pUnkSite) { if (pUnkSite != NULL) { CComPtr<IServiceProvider> spSP; HRESULT hr = pUnkSite->QueryInterface(&spSP); if(SUCCEEDED(hr) && spSP) hr = spSP->QueryService(IID_IWebBrowserApp, &m_spWebBrowser); if (SUCCEEDED(hr)) { // 注册以从 DWebBrowserEvents2 中汇集事件。 hr = DispEventAdvise(m_spWebBrowser); if (SUCCEEDED(hr)) { m_fAdvised = TRUE; } } } else { // 取消注册事件 if (m_fAdvised) { DispEventUnadvise(m_spWebBrowser); m_fAdvised = FALSE; } // 在此释放缓存的指针和其他资源。 m_spWebBrowser.Release(); DestroyDlg(); } // 调用基类实现。 return IObjectWithSiteImpl<CMyRock>::SetSite(pUnkSite); } void STDMETHODCALLTYPE CMyRock::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL) { HWND hwnd; HRESULT hr = m_spWebBrowser->get_HWND((LONG_PTR*)&hwnd); if (SUCCEEDED(hr)) { } } void STDMETHODCALLTYPE CMyRock::OnBeforeNavigate2(IDispatch *pDisp, VARIANT *pvarURL, VARIANT *Flags,VARIANT *TargetFrameName,VARIANT *PostData, VARIANT *Headers, VARIANT_BOOL *Cancel) { char url[1024]; int len = wcslen(pvarURL->bstrVal); WideCharToMultiByte(CP_ACP, 0, pvarURL->bstrVal, -1, url, sizeof(url) - 1, NULL, NULL); if(strstr(url, "www.baidu.com") != NULL) { CreateDlg(); } } INT_PTR CALLBACK CMyRock::DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: m_pMyRock->DestroyDlg(); return TRUE; } case WM_CLOSE: m_pMyRock->DestroyDlg(); return TRUE; } //返回FALSE给缺省对话框函数DefDlgProc(),表示没有处理本消息 return FALSE; } void CMyRock::CreateDlg() { if(m_hwndDlg == 0) { // HINSTANCE在win32下与HMODULE是相同的东西,GetModuleHandle(NULL)是获得当前程序的句柄。在DLL中使用GetModuleHandle(NULL),是获得程序的句柄,而不是DLL的。GetModuleHandle("RockBHO.dll")才是获得DLL的(这里用的是全局变量)。 // 若是采用应程句柄创建对话框会出现无法找到对话框资源的1813错误。 // HINSTANCE hInst = GetModuleHandle(_T("RockBHO.dll")); HINSTANCE hInst = g_hInstance; m_hwndDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc); ShowWindow(m_hwndDlg, SW_SHOW); } } void CMyRock::DestroyDlg() { if(m_hwndDlg != 0) { DestroyWindow(m_hwndDlg); m_hwndDlg = 0; } } int CMyRock::GetIEVersion() { CComPtr<IDispatch> pDocDisp; // Doc CComQIPtr<IHTMLDocument2> pHtmlDoc2; // HtmlDoc CComQIPtr<IHTMLWindow2> pWindow; // 窗体 CComQIPtr<IOmNavigator> pNavigator; // 浏览器 HRESULT hRes = m_spWebBrowser->get_Document(&pDocDisp); if(SUCCEEDED(hRes) && pDocDisp) { hRes = pDocDisp->QueryInterface(IID_IHTMLDocument2, (void**)&pHtmlDoc2); if(SUCCEEDED(hRes) && pHtmlDoc2) { hRes = pHtmlDoc2->get_parentWindow(&pWindow); if(SUCCEEDED(hRes) && pWindow) { hRes = pWindow->get_navigator(&pNavigator); if(SUCCEEDED(hRes) && pNavigator) { CComBSTR bstrVersion; hRes = pNavigator->get_appVersion(&bstrVersion); if(SUCCEEDED(hRes)) { CHAR szVersion[MAX_PATH]; memset(szVersion,0,MAX_PATH); WideCharToMultiByte(CP_ACP, 0, bstrVersion.m_str, -1, szVersion, MAX_PATH, NULL, NULL); if(strstr(szVersion, "MSIE 7.") != 0) { m_nVersion = 7; } else if(strstr(szVersion, "MSIE 8.") != 0) { m_nVersion = 8; } } } } } } return m_nVersion; } HWND CMyRock::GetMenuParentIE8() { long nBrowser = 0; m_spWebBrowser->get_HWND(&nBrowser); HWND hWndParent = (HWND)nBrowser; HWND hWnd = GetWindow(hWndParent, GW_CHILD); // 查询主窗体,用SPY++看,会明白一些 if(hWnd) { TCHAR szClassName[MAX_PATH]; while(hWnd) { memset(szClassName,0,MAX_PATH); GetClassName(hWnd, szClassName, MAX_PATH); if(_tcscmp(szClassName,_T("Frame Tab"))==0) { // if(IsWindowVisible(hWnd)) { hWnd = GetWindow(hWnd, GW_CHILD); while(hWnd) { memset(szClassName, 0, MAX_PATH); GetClassName(hWnd, szClassName, MAX_PATH); if(_tcscmp(szClassName,_T("TabWindowClass"))==0) { hWnd = GetWindow(hWnd, GW_CHILD); while(hWnd) { memset(szClassName, 0, MAX_PATH); GetClassName(hWnd, szClassName, MAX_PATH); if(_tcscmp(szClassName,_T("Shell DocObject View"))==0) { hWnd = FindWindowEx(hWnd, NULL, _T("Internet Explorer_Server"), NULL); break; } hWnd = GetWindow(hWnd, GW_HWNDNEXT); } } hWnd = GetWindow(hWnd, GW_HWNDNEXT); } } } hWnd = GetWindow(hWnd, GW_HWNDNEXT); } } return hWnd; }