这个项目是win32程序,就一个目标文件。
class CEventSink :public CComObjectRootEx <CComSingleThreadModel>, public IDispatch 实现了网页接口的事件接收器。
class CMain :public CWindowImpl <CMain> 窗口主要界面,快照的实现(获得网页接口对象)。
快照实现部分:
////////////////////////////////////////////////////////////////// // Implementation of CMain::SaveSnapshot ////////////////////////////////////////////////////////////////// BOOL CMain::SaveSnapshot(void) { long bodyHeight, bodyWidth, rootHeight, rootWidth, height, width; CComPtr<IDispatch> pDispatch; // TODO: "If the document object type is not safe for scripting, // this method returns successfully but sets ppDisp to NULL. For // Internet Explorer 7 and later, the return code is S_FALSE..." //获得对象 HRESULT hr = m_pWebBrowser->get_Document(&pDispatch); if (FAILED(hr)) return true; //获得ihtml接口 CComPtr<IHTMLDocument2> spDocument; hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void**)&spDocument); if (FAILED(hr)) return true; //获得内容 CComPtr<IHTMLElement> spBody; hr = spDocument->get_body(&spBody); // Apparently with MSHTML failing to get the body is not a failure, // so if there is no HTML body to get, which may be the case with // SVG images loaded directly, this succeeds but sets spBody to the // NULL pointer, leading to a crash. I am not sure how to obtain // the sizing information for SVG documents so this errors out here. // A work around would be the make HTML host documents or wrapping // the SVG code in a XHTML document, but that may break scripts. if (FAILED(hr) || spBody == NULL) return true; //查找相关接口 CComPtr<IHTMLElement2> spBody2; hr = spBody->QueryInterface(IID_IHTMLElement2, (void**)&spBody2); if (FAILED(hr)) return true; hr = spBody2->get_scrollHeight(&bodyHeight); if (FAILED(hr)) return true; hr = spBody2->get_scrollWidth(&bodyWidth); if (FAILED(hr)) return true; CComPtr<IHTMLDocument3> spDocument3; hr = pDispatch->QueryInterface(IID_IHTMLDocument3, (void**)&spDocument3); if (FAILED(hr)) return true; // We also need to get the dimensions from the <html> due to quirks // and standards mode differences. Perhaps this should instead check // whether we are in quirks mode? How does it work with IE8? CComPtr<IHTMLElement> spHtml; hr = spDocument3->get_documentElement(&spHtml); if (FAILED(hr)) return true; CComPtr<IHTMLElement2> spHtml2; hr = spHtml->QueryInterface(IID_IHTMLElement2, (void**)&spHtml2); if (FAILED(hr)) return true; hr = spHtml2->get_scrollHeight(&rootHeight); if (FAILED(hr)) return true; hr = spHtml2->get_scrollWidth(&rootWidth); if (FAILED(hr)) return true; width = bodyWidth; height = rootHeight > bodyHeight ? rootHeight : bodyHeight; // TODO: What if width or height exceeds 32767? It seems Windows limits // the window size, and Internet Explorer does not draw what's not visible. ::MoveWindow(m_hwndWebBrowser, 0, 0, width, height, TRUE); CComPtr<IViewObject2> spViewObject; // This used to get the interface from the m_pWebBrowser but that seems // to be an undocumented feature, so we get it from the Document instead. hr = spDocument3->QueryInterface(IID_IViewObject2, (void**)&spViewObject); if (FAILED(hr)) return true; RECTL rcBounds = { 0, 0, width, height }; _TCHAR* tcsExt = _tcsrchr(m_fileName, '.'); if (tcsExt && _tcscmp(_T(".emf"), tcsExt) == 0) { USES_CONVERSION; HDC hdcMain = GetDC(); int iWidthMM = GetDeviceCaps(hdcMain, HORZSIZE); int iHeightMM = GetDeviceCaps(hdcMain, VERTSIZE); int iWidthPels = GetDeviceCaps(hdcMain, HORZRES); int iHeightPels = GetDeviceCaps(hdcMain, VERTRES); Gdiplus::RectF rcBoundsX(0, 0, (Gdiplus::REAL)width, (Gdiplus::REAL)height); rcBoundsX.Y *= iHeightMM * 100 / iHeightPels; rcBoundsX.X *= iWidthMM * 100 / iWidthPels; rcBoundsX.Width *= iWidthMM * 100 / iWidthPels; rcBoundsX.Height *= iHeightMM * 100 / iHeightPels; Gdiplus::Metafile emf(T2W(m_fileName), hdcMain, rcBoundsX, Gdiplus::MetafileFrameUnitGdi, Gdiplus::EmfTypeEmfPlusDual, L"[TODO: Description]"); //获得图片 Gdiplus::Graphics g(&emf); HDC imgDc = g.GetHDC(); // For unknown reasons Internet Explorer will sometimes // fail to draw glyphs for certain characters here even // though they are rendered in Internet Explorer itself. // On other pages, Internet Explorer will simply render // a single bitmap into the emf which isn't really what // this should do. I've no idea how to fix that however. hr = spViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, imgDc, imgDc, &rcBounds, NULL, NULL, 0); g.ReleaseHDC(imgDc); ReleaseDC(hdcMain); return false; } CImage image; // TODO: check return value; // TODO: somehow enable alpha image.Create(width, height, 24); HDC imgDc = image.GetDC(); hr = spViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, imgDc, imgDc, &rcBounds, NULL, NULL, 0); image.ReleaseDC(); //保存 if (SUCCEEDED(hr)) hr = image.Save(m_fileName); return false; }
学习的目的是成熟!~
源码下载