/*
* $Header: $
*
* $History: $
*/
#include "stdafx.h"
#include <exdispid.h>
#include "CreateHTMLImage.h"
#include "FileSpec.h"
#include "BitmapDC.h"
IMPLEMENT_DYNCREATE(CCreateHTMLImage, CWnd)
BEGIN_EVENTSINK_MAP(CCreateHTMLImage, CWnd)
ON_EVENT(CHtmlView, CHILDBROWSER, DISPID_DOCUMENTCOMPLETE, DocumentComplete, VTS_DISPATCH VTS_PVARIANT)
END_EVENTSINK_MAP()
LPCTSTR CCreateHTMLImage::m_ImageFormats[] =
{
"image/bmp",
"image/jpeg",
"image/gif",
"image/tiff",
"image/png"
};
// CCreateHTMLImage
CCreateHTMLImage::CCreateHTMLImage() : CWnd()
{
SetSaveImageFormat(eJPG);
}
CCreateHTMLImage::~CCreateHTMLImage()
{
}
BOOL CCreateHTMLImage::SetSaveImageFormat(eOutputImageFormat format)
{
USES_CONVERSION;
ASSERT(format >= 0 && format < eImgSize);
return GetEncoderClsid(A2W(m_ImageFormats[format]), &m_encoderClsid) != -1;
}
BOOL CCreateHTMLImage::CreateControlSite(COleControlContainer* pContainer, COleControlSite** ppSite, UINT /* nID */, REFCLSID /* clsid */)
{
ASSERT(ppSite != NULL);
*ppSite = new CHTMLImageControlSite(pContainer);
return TRUE;
}
// CCreateHTMLImage member functions
BOOL CCreateHTMLImage::Create(CWnd *pParent)
{
ASSERT(GetSafeHwnd() == HWND(NULL));
ASSERT(pParent);
ASSERT_KINDOF(CWnd, pParent);
ASSERT(IsWindow(pParent->GetSafeHwnd()));
CRect rect;
if (!CWnd::Create(NULL, NULL, WS_CHILD, rect, pParent, 0, NULL))
return FALSE;
// Window style must include WS_VISIBLE even though we never see the window. Otherwise the WebBrowser
// seems not to load documents.
if (!m_pBrowserWnd.CreateControl(CLSID_WebBrowser, _T(""), WS_VISIBLE | WS_CHILD, rect, this, CHILDBROWSER))
{
DestroyWindow();
return FALSE;
}
// cache the dispinterface
LPUNKNOWN lpUnk = m_pBrowserWnd.GetControlUnknown();
HRESULT hr = lpUnk->QueryInterface(IID_IWebBrowser2, (void**) &m_pBrowser);
if (!SUCCEEDED(hr))
{
m_pBrowser = NULL;
m_pBrowserWnd.DestroyWindow();
DestroyWindow();
return FALSE;
}
return TRUE;
}
BOOL CCreateHTMLImage::CreateImage(LPCTSTR szSrcFilename, LPCTSTR szDestFilename, CSize srcSize, CSize outputSize)
{
ASSERT(GetSafeHwnd());
ASSERT(IsWindow(GetSafeHwnd()));
ASSERT(szSrcFilename);
ASSERT(AfxIsValidString(szSrcFilename));
ASSERT(szDestFilename);
ASSERT(AfxIsValidString(szDestFilename));
CRect rect(CPoint(0, 0), srcSize);
// The WebBrowswer window size must be set to our srcSize
// else it won't render everything
MoveWindow(&rect);
m_pBrowserWnd.MoveWindow(&rect);
COleVariant vUrl(szSrcFilename, VT_BSTR),
vFlags(long(navNoHistory | navNoReadFromCache | navNoWriteToCache), VT_I4),
vNull(LPCTSTR(NULL), VT_BSTR);
COleSafeArray vPostData;
if (m_pBrowser->Navigate2(&vUrl, &vFlags, &vNull, &vPostData, &vNull) == S_OK)
// We have to pump messages to ensure the event handler (DocumentComplete)
// is called.
RunModalLoop();
else
return FALSE;
// We only get here when DocumentComplete has been called, which calls EndModalLoop
// and causes RunModalLoop to exit.
IDispatch *pDoc = (IDispatch *) NULL;
HRESULT hr = m_pBrowser->get_Document(&pDoc);
if (FAILED(hr))
return FALSE;
return CreateImage((IHTMLDocument2 *) pDoc, szDestFilename, srcSize, outputSize);
}
BOOL CCreateHTMLImage::CreateImage(IHTMLDocument2 *pDoc, LPCTSTR szDestFilename, CSize srcSize, CSize outputSize)
{
USES_CONVERSION;
ASSERT(szDestFilename);
ASSERT(AfxIsValidString(szDestFilename));
ASSERT(pDoc);
// Get our interfaces before we create anything else
IHTMLElement *pElement = (IHTMLElement *) NULL;
IHTMLElementRender *pRender = (IHTMLElementRender *) NULL;
// Let's be paranoid...
if (pDoc == (IHTMLDocument2 *) NULL)
return FALSE;
pDoc->get_body(&pElement);
if (pElement == (IHTMLElement *) NULL)
return FALSE;
pElement->QueryInterface(IID_IHTMLElementRender, (void **) &pRender);
if (pRender == (IHTMLElementRender *) NULL)
return FALSE;
CFileSpec fsDest(szDestFilename);
CBitmapDC destDC(srcSize.cx, srcSize.cy);
pRender->DrawToDC(destDC);
CBitmap *pBM = destDC.Close();
Bitmap *gdiBMP = Bitmap::FromHBITMAP(HBITMAP(pBM->GetSafeHandle()), NULL);
Image *gdiThumb = gdiBMP->GetThumbnailImage(outputSize.cx, outputSize.cy);
gdiThumb->Save(A2W(fsDest.GetFullSpec()), &m_encoderClsid);
delete gdiBMP;
delete gdiThumb;
delete pBM;
return TRUE;
}
void CCreateHTMLImage::DocumentComplete(LPDISPATCH pDisp, VARIANT* URL)
{
UNUSED_ALWAYS(pDisp);
UNUSED_ALWAYS(URL);
TRACE("CCreateHTMLImage::DocumentComplete\n");
EndModalLoop(0);
}
int CCreateHTMLImage::GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if(size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j = 0; j < num; ++j)
{
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}
//////////////////////////////////////////////////////////////////////
// Implementation of the CHTMLImageControlSite class, including the
// IDocHostUIHandler implementation
BEGIN_INTERFACE_MAP(CHTMLImageControlSite, COleControlSite)
INTERFACE_PART(CHTMLImageControlSite, IID_IDocHostUIHandler, DocHostUIHandler)
END_INTERFACE_MAP()
CHTMLImageControlSite::CHTMLImageControlSite(COleControlContainer* pContainer) : COleControlSite(pContainer)
{
}
// IUnknown methods
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::QueryInterface(REFIID riid, void **ppvObj)
{
METHOD_PROLOGUE_EX_(CHTMLImageControlSite, DocHostUIHandler)
return pThis->ExternalQueryInterface(&riid, ppvObj);
}
STDMETHODIMP_(ULONG) CHTMLImageControlSite::XDocHostUIHandler::AddRef()
{
METHOD_PROLOGUE_EX_(CHTMLImageControlSite, DocHostUIHandler)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CHTMLImageControlSite::XDocHostUIHandler::Release()
{
METHOD_PROLOGUE_EX_(CHTMLImageControlSite, DocHostUIHandler)
return pThis->ExternalRelease();
}
// IDocHostUIHandler methods
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::ShowContextMenu(DWORD /*dwID*/, POINT * /*ppt*/, IUnknown * /*pcmdtReserved*/, IDispatch * /*pdispReserved*/)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::GetHostInfo(DOCHOSTUIINFO *pInfo)
{
pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_SCROLL_NO;
return S_OK;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::ShowUI(DWORD /*dwID*/, IOleInPlaceActiveObject * /*pActiveObject*/, IOleCommandTarget * /*pCommandTarget*/, IOleInPlaceFrame * /*pFrame*/, IOleInPlaceUIWindow * /*pDoc*/)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::HideUI(void)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::UpdateUI(void)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::EnableModeless(BOOL /*fEnable*/)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::OnDocWindowActivate(BOOL /*fActivate*/)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::OnFrameWindowActivate(BOOL /*fActivate*/)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::ResizeBorder(LPCRECT /*prcBorder*/, IOleInPlaceUIWindow * /*pUIWindow*/, BOOL /*fRameWindow*/)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::TranslateAccelerator(LPMSG /*lpMsg*/, const GUID * /*pguidCmdGroup*/, DWORD /*nCmdID*/)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::GetOptionKeyPath(LPOLESTR * /*pchKey*/, DWORD /*dw*/)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::GetDropTarget(IDropTarget * /*pDropTarget*/, IDropTarget ** /*ppDropTarget*/)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::GetExternal(IDispatch ** /*ppDispatch*/)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::TranslateUrl(DWORD /*dwTranslate*/, OLECHAR * /*pchURLIn*/, OLECHAR ** /*ppchURLOut*/)
{
return S_FALSE;
}
STDMETHODIMP CHTMLImageControlSite::XDocHostUIHandler::FilterDataObject(IDataObject * /*pDO*/, IDataObject ** /*ppDORet*/)
{
return S_FALSE;
}