现在要在应用程序创建ACITVEX控件,用ATL现成的就可以了,非常简单。但之前我在没有ATL的环境下需要实现一个IE控件去访问网页,并对网页截图,非常头痛,网上资料很少。后来经过多次实验,终于搞定。贴代码。
snapshotmaker.h
#ifndef __NG_SNAPSHOMAKER_H__
#define __NG_SNAPSHOMAKER_H__
#include <string>
#include "conn.h"
#include "method/method.h"
enum
{
E_SANPSHOT_OK = 0,
E_SANPSHOT_ERR,
};
class CSnapshotMaker : public IBrowserConnCallBack
{
public:
CSnapshotMaker(std::wstring& strURL, std::wstring& strFilePath, HWND hMsgWnd) ;
~CSnapshotMaker();
static void SetMsgWnd(HWND hMsgWnd);
bool StartMake();
void SetCallback(Method<void(CSnapshotMaker*, int)> fnCallBack);
static LONG APIENTRY MsgWindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
bool CreateMessageWindow();
virtual void OnDocumentComplete(BSTR pURL);
virtual void OnNavigateError();
virtual CComPtr<IWebBrowser2> GetWebBrowser();
std::wstring& GetURL() { return m_strURL;}
std::wstring& GetFilePath(){return m_strFilePath;}
HWND GetMsgWnd(){return m_hMsgWnd;}
int GetDebugRef();
public:
std::wstring m_strURL;
std::wstring m_strFilePath;
HWND m_hMsgWnd;
HWND m_hWindow;
CComPtr<IWebBrowser2> m_pWebBrowse ;
CComPtr<IOleObject> iOleObject;
CCon m_conn;
Method<void(CSnapshotMaker*, int)> m_fnCallBack;
long m_lScrollWidth ;
long m_lScrollHeight ;
int m_debugRef;
};
#endif
snapshotmaker.cpp
#include "stdafx.h"
#include "ngsnapshotmaker.h"
#include <windows.h>
#include "Image\Include\ximage.h"
#include <mshtmdid.h >
#define CHECK_HR_RET_IF_FALSE(x) \
if (FAILED(x)) {return false;}
#define TIMER_ID 1
#if 0
#define CHECK_REF(x, T) \
{ T* pUnkown = (T*)x; \
pUnkown->AddRef(); \
m_debugRef = pUnkown->Release(); \
}
#else
#define CHECK_REF(x,T)
#endif
class CControlContainer:public IOleClientSite,public IOleInPlaceSite, public IServiceProvider,
public IOleContainer,
public IOleControlSite,
public IDocHostUIHandler,
public IDispatch
{
public:
HWND m_hWnd;
ULONG m_refCnt;
public:
STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
{
if(iid == IID_IUnknown)
{
*ppv = static_cast<IOleInPlaceSite*>(this);
}
else if(iid == IID_IOleClientSite)
{
*ppv = static_cast<IOleClientSite*>(this);
}
else if(iid == IID_IOleWindow)
{
*ppv = static_cast<IOleWindow*>(this);
}
else if(iid == IID_IOleInPlaceSite)
{
*ppv = static_cast<IOleInPlaceSite*>(this);
}
else if(iid == IID_IDocHostUIHandler)
{
*ppv = static_cast<IDocHostUIHandler*>(this);
}
else if(iid == IID_IDispatch)
{
*ppv = static_cast<IDispatch*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
virtual /* [local] */ HRESULT STDMETHODCALLTYPE QueryService(
/* [in] */ REFGUID guidService,
/* [in] */ REFIID riid,
/* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
{
return S_FALSE;
}
STDMETHODIMP_(ULONG) AddRef()
{
return ++m_refCnt;
}
STDMETHODIMP_(ULONG) Release()
{
--m_refCnt;
int nTmp = m_refCnt;
if(m_refCnt == 0) // 因为在对象已经销毁后再引用这个对象的数据将是非法的
delete this;
return nTmp;
}
CControlContainer(HWND hWnd)
{
m_hWnd = hWnd;
m_refCnt = 1;
}
~CControlContainer()
{
}
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
{
return S_OK;
}
STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
return S_OK;
}
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgdispid)
{
return S_OK;
}
STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
switch (dispidMember)
{
case DISPID_AMBIENT_DLCONTROL:
pvarResult->vt = VT_I4;
// 不准弹框,只要图像,不下ACTIVEX,不运行ACTX,不要JAVAAPPLET,不要JS
pvarResult->lVal = DLCTL_SILENT|DLCTL_DLIMAGES| DLCTL_NO_DLACTIVEXCTLS | DLCTL_NO_RUNACTIVEXCTLS
|DLCTL_NO_JAVA|DLCTL_NO_SCRIPTS;
break;
default:
return DISP_E_MEMBERNOTFOUND;
}
return S_OK;
}
//IOleControlSite
STDMETHOD(SaveObject())
{
return E_NOTIMPL;
}
STDMETHOD(GetMoniker(DWORD,DWORD,IMoniker**))
{
return E_NOTIMPL;
}
STDMETHOD(GetContainer(IOleContainer **ppContainer))
{
return E_NOINTERFACE;
}
STDMETHOD(ShowObject())
{
return S_OK;
}
STDMETHOD(OnShowWindow(BOOL bShow))
{
return S_OK;
}
STDMETHOD(RequestNewObjectLayout())
{
return E_NOTIMPL;
}
//IOleWindow
STDMETHOD(GetWindow(HWND * pHwnd))
{
*pHwnd = m_hWnd;
return S_OK;
}
STDMETHOD(ContextSensitiveHelp(BOOL bEnterMode))
{
return S_OK;
}
//IOleInPlaceSite
STDMETHOD(CanInPlaceActivate())
{
return S_OK;
}
STDMETHOD(OnInPlaceActivate())
{
return S_OK;
}
STDMETHOD(OnUIActivate())
{
return S_OK;
}
STDMETHOD(GetWindowContext(/* [out] */ IOleInPlaceFrame **ppFrame,
/* [out] */ IOleInPlaceUIWindow **ppDoc,
/* [out] */ LPRECT lprcPosRect,
/* [out] */ LPRECT lprcClipRect,
/* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo))
{
return E_NOTIMPL;
}
STDMETHOD(Scroll(SIZE scrollSize))
{
return S_OK;
}
STDMETHOD(OnUIDeactivate(BOOL bUndoable))
{
return S_OK;
}
STDMETHOD(OnInPlaceDeactivate())
{
return S_OK;
}
STDMETHOD(DiscardUndoState())
{
return S_OK;
}
STDMETHOD(DeactivateAndUndo())
{
return S_OK;
}
STDMETHOD(OnPosRectChange(LPCRECT lprcPosRect))
{
return S_OK;
}
//IOleContainer
virtual HRESULT __stdcall ParseDisplayName(IBindCtx *pbc,LPOLESTR pszDisplayName,ULONG *pchEaten,IMoniker **ppmkOut)
{
return E_NOTIMPL;
}
virtual HRESULT __stdcall EnumObjects(DWORD grfFlags, IEnumUnknown **ppenum)
{
return E_NOTIMPL;
}
virtual HRESULT __stdcall LockContainer(BOOL flock)
{
return E_NOTIMPL;
}
//IOleControlSite
virtual HRESULT __stdcall OnControlInfoChanged(void)
{
return S_OK;
}
virtual HRESULT __stdcall LockInPlaceActive(BOOL fLock)
{
return E_NOTIMPL;
}
virtual HRESULT __stdcall GetExtendedControl(IDispatch** ppDisp)
{
return E_NOTIMPL;
}
virtual HRESULT __stdcall TransformCoords(POINTL* pPtlHimetric ,POINTF* pPtfContainer ,DWORD dwFlags)
{
return S_OK;
}
virtual HRESULT __stdcall TranslateAccelerator(LPMSG pMsg ,DWORD grfModifiers)
{
return S_OK;
}
virtual HRESULT __stdcall OnFocus(BOOL fGotFocus)
{
return S_OK;
}
virtual HRESULT __stdcall ShowPropertyFrame(void)
{
return E_NOTIMPL;
}
STDMETHOD(ShowContextMenu)(/* [in] */ DWORD dwID,
/* [in] */ POINT __RPC_FAR *ppt,
/* [in] */ IUnknown __RPC_FAR *pcmdtReserved,
/* [in] */ IDispatch __RPC_FAR *pdispReserved)
{
return S_OK;
}
STDMETHOD(GetHostInfo)(
/* [out][in] */ DOCHOSTUIINFO __RPC_FAR *pInfo)
{
pInfo->cbSize = sizeof(DOCHOSTUIINFO);
pInfo->dwFlags = DOCHOSTUIFLAG_DIALOG |
DOCHOSTUIFLAG_THEME |
DOCHOSTUIFLAG_NO3DBORDER |
DOCHOSTUIFLAG_SCROLL_NO;
return S_OK;
}
STDMETHOD(ShowUI)(
/* [in] */ DWORD dwID,
/* [in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
/* [in] */ IOleCommandTarget __RPC_FAR *pCommandTarget,
/* [in] */ IOleInPlaceFrame __RPC_FAR *pFrame,
/* [in] */ IOleInPlaceUIWindow __RPC_FAR *pDoc)
{
return S_OK;
}
STDMETHOD(HideUI)(void)
{
return S_OK;
}
STDMETHOD(UpdateUI)(void)
{
return S_OK;
}
STDMETHOD(EnableModeless)(/* [in] */ BOOL fEnable)
{
return E_NOTIMPL;
}
STDMETHOD(OnDocWindowActivate)(/* [in] */ BOOL fEnable)
{
return E_NOTIMPL;
}
STDMETHOD(OnFrameWindowActivate)(/* [in] */ BOOL fEnable)
{
return E_NOTIMPL;
}
STDMETHOD(ResizeBorder)(
/* [in] */ LPCRECT prcBorder,
/* [in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
/* [in] */ BOOL fRameWindow)
{
return E_NOTIMPL;
}
STDMETHOD(TranslateAccelerator)(
/* [in] */ LPMSG lpMsg,
/* [in] */ const GUID __RPC_FAR *pguidCmdGroup,
/* [in] */ DWORD nCmdID)
{
return S_FALSE;
}
STDMETHOD(GetOptionKeyPath)(
/* [out] */ LPOLESTR __RPC_FAR *pchKey,
/* [in] */ DWORD dw)
{
return E_NOTIMPL;
}
STDMETHOD(GetDropTarget)(
/* [in] */ IDropTarget __RPC_FAR *pDropTarget,
/* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget)
{
return E_NOTIMPL;
}
STDMETHOD(GetExternal)(
/* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch)
{
return S_OK;
}
STDMETHOD(TranslateUrl)(
/* [in] */ DWORD dwTranslate,
/* [in] */ OLECHAR __RPC_FAR *pchURLIn,
/* [out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut)
{
return E_NOTIMPL;
}
STDMETHOD(FilterDataObject)(
/* [in] */ IDataObject __RPC_FAR *pDO,
/* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDORet)
{
return E_NOTIMPL;
}
};
CSnapshotMaker::CSnapshotMaker( std::wstring& strURL, std::wstring& strFilePath, HWND hMsgWnd ):
m_strURL(strURL),
m_strFilePath(strFilePath),
m_hMsgWnd(hMsgWnd),
m_hWindow(0),
m_lScrollWidth(0),
m_lScrollHeight(0),
m_debugRef(0)
{
}
CSnapshotMaker::~CSnapshotMaker()
{
// 消毁窗口
CHECK_REF(iOleObject, IOleObject);
DestroyWindow(m_hWindow);
if (iOleObject != NULL)
{
iOleObject->Close(0);
}
CHECK_REF(iOleObject, IOleObject);
CoUninitialize();
}
bool CSnapshotMaker::StartMake()
{
CoInitialize(NULL);
if (!CreateMessageWindow())
{
return false;
}
// 设置一个二十秒到期的定时器
SetTimer(m_hWindow, reinterpret_cast<UINT_PTR>(this), 20000, NULL );
SetWindowPos(m_hWindow, HWND_TOP, 0, 0, 100, 130, SWP_HIDEWINDOW);
HRESULT hr = S_FALSE;
CComPtr<IUnknown> iUnknown = NULL;
hr = ::CoCreateInstance(CLSID_WebBrowser,
NULL,
CLSCTX_INPROC_SERVER ,
IID_IUnknown,
(void**)(&iUnknown));
CHECK_HR_RET_IF_FALSE(hr);
hr = iUnknown->QueryInterface(IID_IOleObject, (void**)(&iOleObject));
CHECK_HR_RET_IF_FALSE(hr);
//CControlContainer是实现了IOleClientSite和IOleInPlaceSite接口的类
CControlContainer* pContainer = new CControlContainer(m_hWindow);
//调用IOleObject::SetClientSite,传入容器指针
CHECK_HR_RET_IF_FALSE(iOleObject->SetClientSite(pContainer));
CHECK_REF(iOleObject, IOleObject)
if (pContainer)
{
pContainer->Release();
}
RECT rect ;
::GetClientRect(m_hWindow, &rect);
hr = iOleObject->DoVerb(OLEIVERB_SHOW, NULL, pContainer, 0, m_hWindow, &rect);
CHECK_HR_RET_IF_FALSE(hr);
CHECK_REF(iOleObject, IOleObject)
CComPtr<IOleInPlaceObject> pInPlaceObject;
hr = iOleObject->QueryInterface(IID_IOleInPlaceObject,(void**)&pInPlaceObject);
CHECK_HR_RET_IF_FALSE(hr);
CHECK_HR_RET_IF_FALSE(pInPlaceObject->SetObjectRects(&rect,&rect));
CHECK_REF(iOleObject, IOleObject)
hr = iOleObject->QueryInterface(IID_IWebBrowser2, (void**)&m_pWebBrowse);
CHECK_HR_RET_IF_FALSE(hr);
CHECK_REF(iOleObject, IOleObject)
m_conn.ConnectEvents(this);
VARIANT vUrl;
vUrl.vt = VT_BSTR;
vUrl.bstrVal = ::SysAllocString(m_strURL.c_str());
VARIANT vFlags, vNull;
vFlags.vt = VT_I4;
vFlags.lVal = long(navNoHistory | navNoReadFromCache | navNoWriteToCache);
vNull.vt = VT_BSTR;
vNull.bstrVal = NULL;
VARIANT vPostData;
memset(&vPostData, 0, sizeof(vPostData));
vPostData.vt = VT_ARRAY;
VARIANT_BOOL varSli;
varSli = VARIANT_TRUE;
m_pWebBrowse->put_Silent(varSli);
hr = m_pWebBrowse->Navigate2(&vUrl, &vFlags, &vNull, &vPostData, &vNull);
::SysFreeString(vUrl.bstrVal);
CHECK_HR_RET_IF_FALSE(hr);
CHECK_REF(iOleObject, IOleObject);
return true;
}
#define NGSNAPSHOT_FAILED (WM_USER + 0x01)
#define NGSNAPSHOT_OK (WM_USER + 0x02)
#define NGSNAPSHOT_ADJUSTSCREEN (WM_USER + 0x03)
LONG APIENTRY CSnapshotMaker::MsgWindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
LONG lRet = 0;
switch(message)
{
case NGSNAPSHOT_FAILED:
{
CSnapshotMaker* pThis = reinterpret_cast<CSnapshotMaker*>(wParam);
if (pThis ==NULL )
{
break;
}
pThis->m_fnCallBack(pThis, E_SANPSHOT_ERR);
}
break;
case NGSNAPSHOT_OK:
{
}
break;
case WM_TIMER:
{
CSnapshotMaker* pThis = reinterpret_cast<CSnapshotMaker*>(wParam);
if (pThis ==NULL )
{
break;
}
KillTimer(hWnd, wParam);
pThis->m_fnCallBack(pThis, E_SANPSHOT_ERR);
}
break;
case NGSNAPSHOT_ADJUSTSCREEN:
{
CSnapshotMaker* pThis = reinterpret_cast<CSnapshotMaker*>(wParam);
if (pThis ==NULL )
{
break;
}
long lScrollWidth = pThis->m_lScrollWidth;
long lScrollHeight = pThis->m_lScrollHeight;
//调整WebBrowser大小和网页大小一致
RECT rc = { 0,0,lScrollWidth , lScrollHeight };
if (lScrollHeight >= 768)
{
lScrollHeight = 768;
}
HDC hWndDC = GetDC(hWnd);
HBITMAP hBitmap = ::CreateCompatibleBitmap(hWndDC, lScrollWidth, lScrollHeight);
HDC hBitmapDC = ::CreateCompatibleDC(hWndDC);
::SelectObject( hBitmapDC , hBitmap );
RECTL rctl = { rc.left , rc.top , rc.right , rc.bottom };
//绘画WebBrowser中的网页内容
//GetHWND()返回WebBrowser容器窗口句柄
DVASPECTINFO info;
info.cb = sizeof(info);
info.dwFlags = DVASPECTINFOFLAG_CANOPTIMIZE;
CComPtr<IViewObject> pViewObject2 ;
HRESULT hr = pThis->m_pWebBrowse->QueryInterface( IID_IViewObject , (void**)&pViewObject2 ) ;
if (FAILED(hr))
{
ReleaseDC(hWnd, hWndDC);
DeleteDC(hBitmapDC);
DeleteObject(hBitmap);
pThis->m_fnCallBack(pThis, E_SANPSHOT_ERR);
break;
}
// draw screen snapshot.
hr = pViewObject2->Draw(DVASPECT_CONTENT, 1, &info,
NULL, hWndDC, hBitmapDC, &rctl, NULL, NULL, 0) ;
if (FAILED(hr))
{
ReleaseDC(hWnd, hWndDC);
DeleteDC(hBitmapDC);
DeleteObject(hBitmap);
pThis->m_fnCallBack(pThis, E_SANPSHOT_ERR);
break;
}
CxImage xImage;
bool bRet = xImage.CreateFromHBITMAP(hBitmap);
if (bRet)
{
// 必须整点高斯模糊的效果,否则很JER丑
xImage.Resample2(208, 130, CxImage::IM_GAUSSIAN);
// 判断图像是不是全黑全白的,如果是,那就不用这个图。
// 因为有可能是全FLASH的页面,此时由于ACTX被梦用,所以FLASH渲染失败,是黑色页
// 先把图像用双线性缩小采样为3*3,如果这九个像素都是黑色,那么认为该页是黑页
CxImage xImageDownSample(xImage);
xImageDownSample.Resample2(3, 3, CxImage::IM_BILINEAR);
BOOL bAllWhite = TRUE;
BOOL bAllBlack = TRUE;
for (DWORD dwWith = 0; dwWith < xImageDownSample.GetWidth(); ++dwWith)
{
for (DWORD dwHeight = 0; dwHeight < xImageDownSample.GetHeight(); ++dwHeight)
{
RGBQUAD clr = xImageDownSample.GetPixelColor(dwHeight, dwWith);
if (clr.rgbBlue != 0 || clr.rgbGreen != 0 || clr.rgbRed != 0)
{
bAllBlack = FALSE;
}
if (clr.rgbBlue != 255 || clr.rgbGreen != 255 || clr.rgbRed != 255)
{
bAllWhite = FALSE;
}
}
}
if (!bAllBlack && !bAllWhite)
{
if(xImage.Save(pThis->m_strFilePath.c_str(), CXIMAGE_FORMAT_PNG) )
{
pThis->m_fnCallBack(pThis, E_SANPSHOT_OK);
ReleaseDC(hWnd, hWndDC);
DeleteDC(hBitmapDC);
DeleteObject(hBitmap);
break;
}
}
}
ReleaseDC(hWnd, hWndDC);
DeleteDC(hBitmapDC);
DeleteObject(hBitmap);
pThis->m_fnCallBack(pThis, E_SANPSHOT_ERR);
}
break;
default:
lRet = ::DefWindowProc(hWnd,message,wParam,lParam);
break;
}
return lRet;
}
bool CSnapshotMaker::CreateMessageWindow()
{
const TCHAR aszWindowName[] = _T("CSnapshotMaker-B4A4C9A8-DB30-4f0b-9172-773BC69E808B");
WNDCLASSEX wc = {sizeof(wc)};
wc.hInstance = GetModuleHandle(0);
wc.lpszClassName = aszWindowName;
wc.lpfnWndProc = &CSnapshotMaker::MsgWindowProc;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.cbWndExtra = sizeof(void*);
RegisterClassEx(&wc);
m_hWindow = CreateWindowEx (0, aszWindowName,
aszWindowName,
WS_POPUP,
0, 0, 0, 0,
NULL,
NULL,
wc.hInstance,
NULL
);
return (NULL != m_hWindow);
}
#define CHECK_HR_RET_IF_FAILED(hr) \
if (FAILED(hr)){::PostMessage(m_hWindow, NGSNAPSHOT_FAILED, (WPARAM)((void*)this), NULL ); return; }
void CSnapshotMaker::OnDocumentComplete( BSTR pURL )
{
CHECK_REF(iOleObject, IOleObject);
{
CComPtr<IHTMLElement> pBodyElem;
CComPtr<IHTMLDocument2> pDoc = NULL;
HRESULT hr = m_pWebBrowse->get_Document((IDispatch**)&pDoc);
CHECK_HR_RET_IF_FAILED(hr);
if (pDoc == NULL)
{
::PostMessage(m_hWindow, NGSNAPSHOT_FAILED, (WPARAM)((void*)this), NULL );
return;
}
CHECK_HR_RET_IF_FAILED(pDoc->get_body(&pBodyElem));
CHECK_REF(iOleObject, IOleObject);
CComPtr<IHTMLBodyElement> pBody ;
CHECK_HR_RET_IF_FAILED(pBodyElem->QueryInterface(IID_IHTMLBodyElement, (void**)&pBody));
CHECK_REF(iOleObject, IOleObject);
CComPtr<IViewObject> pViewObject2 ;
CHECK_HR_RET_IF_FAILED((m_pWebBrowse->QueryInterface( IID_IViewObject , (void**)&pViewObject2 ) ));
CHECK_REF(iOleObject, IOleObject);
// resize the browser component to the size of the HTML content
CComPtr<IHTMLElement2> pBodyElement2;
CHECK_HR_RET_IF_FAILED( pBodyElem->QueryInterface(IID_IHTMLElement2, (void**)&pBodyElement2) );
CHECK_REF(iOleObject, IOleObject);
CHECK_HR_RET_IF_FAILED( pBodyElement2->get_scrollWidth(&m_lScrollWidth) );
CHECK_HR_RET_IF_FAILED( pBodyElement2->get_scrollHeight(&m_lScrollHeight) );
// 判断是否是正常网页
if (m_lScrollWidth < 200 && m_lScrollHeight < 200)
{
// 非正常网页,通知失败
CHECK_HR_RET_IF_FAILED(S_FALSE);
}
SetWindowPos(m_hWindow, HWND_TOP, 0, 0, m_lScrollWidth, m_lScrollHeight, SWP_HIDEWINDOW);
::UpdateWindow(m_hWindow);
CComPtr<IOleInPlaceObject> pInPlace;
CHECK_HR_RET_IF_FAILED((m_pWebBrowse->QueryInterface( IID_IOleInPlaceObject , (void**)&pInPlace ) ));
CHECK_REF(iOleObject, IOleObject);
RECT rect ;
::GetClientRect(m_hWindow, &rect);
pInPlace->SetObjectRects(&rect, &rect);
BSTR bsScrollStyle = ::SysAllocString(L"no");
pBody->put_scroll(bsScrollStyle);
SysFreeString(bsScrollStyle);
CComPtr<IHTMLStyle> pStyle;
pBodyElem->get_style(&pStyle) ;
CHECK_REF(iOleObject, IOleObject);
BSTR bsBorderStyle = ::SysAllocString(L"no");
pStyle->put_borderStyle( bsBorderStyle);
SysFreeString(bsBorderStyle);
::PostMessage(m_hWindow, NGSNAPSHOT_ADJUSTSCREEN, WPARAM(this), NULL );
}
CHECK_REF(iOleObject, IOleObject);
}
void CSnapshotMaker::OnNavigateError()
{
::PostMessage(m_hWindow, NGSNAPSHOT_FAILED, WPARAM(this), 0 );
}
CComPtr<IWebBrowser2> CSnapshotMaker::GetWebBrowser()
{
return m_pWebBrowse;
}
int CSnapshotMaker::GetDebugRef()
{
CHECK_REF(iOleObject, IOleObject);
return m_debugRef;
}
void CSnapshotMaker::SetCallback( Method<void(CSnapshotMaker*, int)> pCallBack )
{
m_fnCallBack = pCallBack;
}
conn.h
#pragma once
#include <Unknwn.h>
class IBrowserConnCallBack
{
public:
virtual void OnDocumentComplete(BSTR pURL) = 0;
virtual void OnNavigateError() = 0;
virtual CComPtr<IWebBrowser2> GetWebBrowser() = 0;
};
class CCon:public IDispatch
{
public:
CCon();
~CCon(void);
ULONG m_refCnt;
IID m_iid;
CComPtr<IWebBrowser2> m_pIE;
IBrowserConnCallBack* m_pCallBack;
DWORD m_dwCookie;
CComPtr<IConnectionPoint> m_pConnectionPoint;
void ConnectEvents(IBrowserConnCallBack* pCallBack);
void Exit();
STDMETHOD_(ULONG,AddRef())
{
return ++m_refCnt;
}
STDMETHOD_(ULONG,Release())
{
if (--m_refCnt == 0)
{
delete this;
return 0;
}
return m_refCnt;
}
STDMETHOD(QueryInterface(REFIID riid,void **ppvObject))
{
*ppvObject = NULL;
if ( IID_IUnknown == riid)
{
*ppvObject = (IUnknown*)this;
}
else if (IID_IDispatch == riid || m_iid == riid)
{
*ppvObject = (IDispatch*)this;
}
else
{
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
//IDispatch
//IDispatch
STDMETHOD(GetTypeInfoCount(unsigned int FAR* pctinfo))
{
return E_NOTIMPL;
}
STDMETHOD(GetTypeInfo(unsigned int iTInfo,LCID lcid,ITypeInfo FAR* FAR* ppTInfo ))
{
return E_NOTIMPL;
}
STDMETHOD(GetIDsOfNames(
REFIID riid,
OLECHAR FAR* FAR* rgszNames,
unsigned int cNames,
LCID lcid,
DISPID FAR* rgDispId
))
{
return E_NOTIMPL;
}
STDMETHOD(Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS FAR* pDispParams,
VARIANT FAR* pVarResult,
EXCEPINFO FAR* pExcepInfo,
unsigned int FAR* puArgErr
));
};
conn.cpp
#include "StdAfx.h"
#include "Conn.h"
#include <ExDisp.h>
#include <ExDispid.h>
#include "oaidl.h"
CCon::CCon():m_pCallBack(0)
{
}
CCon::~CCon(void)
{
Exit();
}
void CCon::ConnectEvents(IBrowserConnCallBack* pCallBack)
{
if (!pCallBack)
{
return;
}
m_pCallBack = pCallBack;
m_pIE = m_pCallBack->GetWebBrowser();
CComPtr<IConnectionPointContainer> pCPContainer;
// Step 1: 获取连接点的指针.
//
HRESULT hr = m_pIE->QueryInterface(IID_IConnectionPointContainer,
(void**)&pCPContainer);
if (SUCCEEDED(hr))
{
// m_pConnectionPoint is defined like this:
// IConnectionPoint* m_pConnectionPoint;
// Step 2: 选找连接点.
//
hr = pCPContainer->FindConnectionPoint(DIID_DWebBrowserEvents2,
&m_pConnectionPoint);
if (SUCCEEDED(hr))
{
// Step 3: 实现连接点地事件接收
//
hr = m_pConnectionPoint->Advise(this, &m_dwCookie);
if (FAILED(hr))
{
}
}
}
}
void CCon::Exit()
{
// Step 5: Unadvise. 注意m_pConnectionPoint 应当在CCon的析构函数中释放
//
if (m_pConnectionPoint)
{
HRESULT hr = m_pConnectionPoint->Unadvise(m_dwCookie);
if (FAILED(hr))
{
}
}
}
extern void OnCallBack(IDispatch* pDispatch, BSTR val);
HRESULT __stdcall CCon::Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS FAR* pDispParams,
VARIANT FAR* pVarResult,
EXCEPINFO FAR* pExcepInfo,
unsigned int FAR* puArgErr
)
{
USES_CONVERSION;
if (!pDispParams)
return E_INVALIDARG;
switch (dispIdMember)
{
// 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_DOCUMENTCOMPLETE:
// Check the argument's type.
if (pDispParams->rgvarg[0].vt == (VT_BYREF|VT_VARIANT))
{
CComVariant varURL(*pDispParams->rgvarg[0].pvarVal);
varURL.ChangeType(VT_BSTR);
//if (varURL.bstrVal == std::wstring(L""))
//{
// break;
//}
if (pDispParams->rgvarg[1].vt == VT_DISPATCH)
{
CComPtr<IDispatch> pDispatch = pDispParams->rgvarg[1].pdispVal;
if (pDispatch )
{
CComPtr<IWebBrowser2> pWebBrowseDisp ;
pDispatch->QueryInterface(IID_IWebBrowser2,(void**)&pWebBrowseDisp);
if (pWebBrowseDisp == m_pIE)
{
m_pCallBack->OnDocumentComplete(varURL.bstrVal);
}
}
}
// strEventInfo is an object of type strstream.
}
break;
case DISPID_NAVIGATEERROR:
{
if ((pDispParams->rgvarg[4].vt == VT_DISPATCH) && (pDispParams->rgvarg[1].vt == (VT_VARIANT|VT_BYREF)))
{
//VARIANT* n = pDispParams->rgvarg[1].pvarVal;
//int k = n->intVal;
//k++;
CComPtr<IDispatch> pDispatch = pDispParams->rgvarg[4].pdispVal;
if (pDispatch )
{
CComPtr<IWebBrowser2> pWebBrowseDisp ;
pDispatch->QueryInterface(IID_IWebBrowser2,(void**)&pWebBrowseDisp);
if (pWebBrowseDisp == m_pIE)
{
// error
//return;
m_pCallBack->OnNavigateError();
}
}
}
}
break;
//拦截弹出窗口
case DISPID_NEWWINDOW2:
{
if (pDispParams->rgvarg[0].vt == (VT_BOOL|VT_BYREF))
{
*pDispParams->rgvarg[0].pboolVal = VARIANT_TRUE;
}
}
break;
// 要是遇上跳转!!!
case DISPID_BEFORENAVIGATE2:
{
//*pDispParams->rgvarg[0].pboolVal = VARIANT_TRUE;
//break;
if (pDispParams->rgvarg[5].vt == (VT_VARIANT|VT_BYREF))
{
CComVariant varURL(*pDispParams->rgvarg[5].pvarVal);
varURL.ChangeType(VT_BSTR);
OutputDebugString(varURL.bstrVal);
IDispatch* pDispatch = pDispParams->rgvarg[6].pdispVal;
if (pDispatch )
{
CComPtr<IWebBrowser2> pWebBrowseDisp;
pDispatch->QueryInterface(IID_IWebBrowser2,(void**)&pWebBrowseDisp);
if (m_pIE != pWebBrowseDisp)
{
// 取消不成功的跳转
//*pDispParams->rgvarg[0].pboolVal = VARIANT_TRUE;
break;
}
// 这是成功的跳转
}
}
}
break;
default:
break;
}
return S_OK;
}