|
|
// GifConv.cpp : Implementation of CICWGifConvert
#include "pre.h"
#include "webvwids.h"
/////////////////////////////////////////////////////////////////////////////
// CICWGifConvert
//+----------------------------------------------------------------------------
//
// Function CICWGifConvert:CICWGifConvert
//
// Synopsis This is the constructor, nothing fancy
//
//-----------------------------------------------------------------------------
CICWGifConvert::CICWGifConvert ( CServer* pServer ) { TraceMsg(TF_CWEBVIEW, "CICWGifConvert constructor called"); m_lRefCount = 0; // Assign the pointer to the server control object.
m_pServer = pServer; }
//+----------------------------------------------------------------------------
//
// Function CICWGifConvert::QueryInterface
//
// Synopsis This is the standard QI, with support for
// IID_Unknown, IICW_Extension and IID_ICWApprentice
// (stolen from Inside COM, chapter 7)
//
//
//-----------------------------------------------------------------------------
HRESULT CICWGifConvert::QueryInterface( REFIID riid, void** ppv ) { TraceMsg(TF_CWEBVIEW, "CICWGifConvert::QueryInterface"); if (ppv == NULL) return(E_INVALIDARG);
*ppv = NULL;
// IID_IICWGifConvert
if (IID_IICWGifConvert == riid) *ppv = (void *)(IICWGifConvert *)this; // IID_IUnknown
else if (IID_IUnknown == riid) *ppv = (void *)this; else return(E_NOINTERFACE);
((LPUNKNOWN)*ppv)->AddRef();
return(S_OK); }
//+----------------------------------------------------------------------------
//
// Function CICWGifConvert::AddRef
//
// Synopsis This is the standard AddRef
//
//
//-----------------------------------------------------------------------------
ULONG CICWGifConvert::AddRef( void ) { TraceMsg(TF_CWEBVIEW, "CICWGifConvert::AddRef %d", m_lRefCount + 1); return InterlockedIncrement(&m_lRefCount) ; }
//+----------------------------------------------------------------------------
//
// Function CICWGifConvert::Release
//
// Synopsis This is the standard Release
//
//
//-----------------------------------------------------------------------------
ULONG CICWGifConvert::Release( void ) { ASSERT( m_lRefCount > 0 );
InterlockedDecrement(&m_lRefCount);
TraceMsg(TF_CWEBVIEW, "CICWGifConvert::Release %d", m_lRefCount); if( 0 == m_lRefCount ) { if (NULL != m_pServer) m_pServer->ObjectsDown(); delete this; return 0; } return( m_lRefCount ); }
void CALLBACK ImgCtx_Callback(void * pIImgCtx, void* pfDone);
HRESULT CICWGifConvert::GifToBitmap(TCHAR * pszFile, HBITMAP* phBitmap) { HRESULT hr = E_FAIL; //don't assume success
ULONG fState; SIZE sz; IImgCtx* pIImgCtx;
BSTR bstrFile = A2W(pszFile);
hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER, IID_IImgCtx, (void**)&pIImgCtx);
BOOL bCoInit = FALSE;
if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) && SUCCEEDED(CoInitialize(NULL))) { bCoInit = TRUE; hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER, IID_IImgCtx, (void**)&pIImgCtx); }
if (SUCCEEDED(hr)) { ASSERT(pIImgCtx);
hr = SynchronousDownload(pIImgCtx, bstrFile); pIImgCtx->GetStateInfo(&fState, &sz, TRUE);
if (SUCCEEDED(hr)) { ASSERT(pIImgCtx);
HDC hdcScreen = GetDC(NULL);
if (hdcScreen) { *phBitmap = CreateCompatibleBitmap(hdcScreen, sz.cx, sz.cy);
if (*phBitmap) { HDC hdcImgDst = CreateCompatibleDC(NULL); if (hdcImgDst) { HGDIOBJ hbmOld = SelectObject(hdcImgDst, *phBitmap); if (hbmOld) { hr = StretchBltImage(pIImgCtx, &sz, hdcImgDst); SelectObject(hdcImgDst, hbmOld); } DeleteDC(hdcImgDst); } } ReleaseDC(NULL, hdcScreen); } }
pIImgCtx->Release(); }
if (bCoInit) CoUninitialize();
return hr; }
HRESULT CICWGifConvert::GifToIcon(TCHAR * pszFile, UINT nIconSize, HICON* phIcon) { HRESULT hr = E_FAIL; //don't assume success
SIZE Size; if (0 != nIconSize) { Size.cx = nIconSize; Size.cy = nIconSize; } IImgCtx* pIImgCtx;
ULONG fState;
BSTR bstrFile = A2W(pszFile);
hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER, IID_IImgCtx, (void**)&pIImgCtx);
BOOL bCoInit = FALSE;
if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) && SUCCEEDED(CoInitialize(NULL))) { bCoInit = TRUE; hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER, IID_IImgCtx, (void**)&pIImgCtx); }
if (SUCCEEDED(hr)) { ASSERT(pIImgCtx);
hr = SynchronousDownload(pIImgCtx, bstrFile); if (0 == nIconSize) { pIImgCtx->GetStateInfo(&fState, &Size, TRUE); }
if (SUCCEEDED(hr)) {
*phIcon = ExtractImageIcon(&Size, pIImgCtx);
}
pIImgCtx->Release(); }
if (bCoInit) CoUninitialize();
return hr; }
HRESULT CICWGifConvert::SynchronousDownload(IImgCtx* pIImgCtx, BSTR bstrFile) { ASSERT(pIImgCtx);
HRESULT hr;
hr = pIImgCtx->Load(bstrFile, 0);
if (SUCCEEDED(hr)) { ULONG fState; SIZE sz;
pIImgCtx->GetStateInfo(&fState, &sz, TRUE);
if (!(fState & (IMGLOAD_COMPLETE | IMGLOAD_ERROR))) { BOOL fDone = FALSE;
hr = pIImgCtx->SetCallback(ImgCtx_Callback, &fDone);
if (SUCCEEDED(hr)) { hr = pIImgCtx->SelectChanges(IMGCHG_COMPLETE, 0, TRUE);
if (SUCCEEDED(hr)) { MSG msg; BOOL fMsg;
// HACK: restrict the message pump to those messages we know that URLMON and
// HACK: the imageCtx stuff needs, otherwise we will be pumping messages for
// HACK: windows we shouldn't be pumping right now...
while(!fDone ) { fMsg = PeekMessage(&msg, NULL, WM_USER + 1, WM_USER + 4, PM_REMOVE );
if (!fMsg) fMsg = PeekMessage( &msg, NULL, WM_APP + 2, WM_APP + 2, PM_REMOVE ); if (!fMsg) { // go to sleep until we get a new message....
WaitMessage(); continue; } TranslateMessage(&msg); DispatchMessage(&msg); } } } pIImgCtx->Disconnect(); } hr = pIImgCtx->GetStateInfo(&fState, &sz, TRUE);
if (SUCCEEDED(hr)) hr = (fState & IMGLOAD_COMPLETE) ? S_OK : E_FAIL; } return hr; }
HICON CICWGifConvert::ExtractImageIcon(SIZE* pSize, IImgCtx * pIImgCtx) { ASSERT(pIImgCtx);
HICON hiconRet = NULL;
HDC hdcScreen = GetDC(NULL);
if (hdcScreen) { HBITMAP hbmImage = CreateCompatibleBitmap(hdcScreen, pSize->cx, pSize->cy);
if (hbmImage) { HBITMAP hbmMask = CreateBitmap(pSize->cx, pSize->cy, 1, 1, NULL);
if (hbmMask) { SIZE sz; sz.cx = pSize->cx; sz.cy = pSize->cy;
if (SUCCEEDED(CreateImageAndMask(pIImgCtx, hdcScreen, &sz, &hbmImage, &hbmMask))) { ICONINFO ii;
ii.fIcon = TRUE; ii.hbmMask = hbmMask; ii.hbmColor = hbmImage;
hiconRet = CreateIconIndirect(&ii); } DeleteObject(hbmMask); } DeleteObject(hbmImage); } ReleaseDC(NULL, hdcScreen); } return hiconRet; }
HRESULT CICWGifConvert::CreateImageAndMask(IImgCtx * pIImgCtx, HDC hdcScreen, SIZE * pSize, HBITMAP * phbmImage, HBITMAP * phbmMask) { ASSERT(pIImgCtx); ASSERT(phbmImage); ASSERT(phbmMask);
HRESULT hr = E_FAIL;
HDC hdcImgDst = CreateCompatibleDC(NULL); if (hdcImgDst) { HGDIOBJ hbmOld = SelectObject(hdcImgDst, *phbmImage); if (hbmOld) { if (ColorFill(hdcImgDst, pSize, COLOR1)) { hr = StretchBltImage(pIImgCtx, pSize, hdcImgDst);
if (SUCCEEDED(hr)) { hr = CreateMask(pIImgCtx, hdcScreen, hdcImgDst, pSize, phbmMask); } } SelectObject(hdcImgDst, hbmOld); } DeleteDC(hdcImgDst); } return hr; }
HRESULT CICWGifConvert::StretchBltImage(IImgCtx * pIImgCtx, const SIZE * pSize, HDC hdcDst) { ASSERT(pIImgCtx); ASSERT(hdcDst);
HRESULT hr;
SIZE sz; ULONG fState;
hr = pIImgCtx->GetStateInfo(&fState, &sz, FALSE);
if (SUCCEEDED(hr)) { hr = pIImgCtx->StretchBlt(hdcDst, 0, 0, pSize->cx, pSize->cy, 0, 0, sz.cx, sz.cy, SRCCOPY); ASSERT(SUCCEEDED(hr) && "Icon extraction pIImgCtx->StretchBlt failed!"); }
return hr; }
HRESULT CICWGifConvert::CreateMask(IImgCtx * pIImgCtx, HDC hdcScreen, HDC hdc1, const SIZE * pSize, HBITMAP * phbMask) { ASSERT(hdc1); ASSERT(pSize); ASSERT(phbMask);
HRESULT hr = E_FAIL;
HDC hdc2 = CreateCompatibleDC(NULL); if (hdc2) { HBITMAP hbm2 = CreateCompatibleBitmap(hdcScreen, pSize->cx, pSize->cy); if (hbm2) { HGDIOBJ hbmOld2 = SelectObject(hdc2, hbm2); if (hbmOld2) { ColorFill(hdc2, pSize, COLOR2);
hr = StretchBltImage(pIImgCtx, pSize, hdc2);
if (SUCCEEDED(hr) && BitBlt(hdc2, 0, 0, pSize->cx, pSize->cy, hdc1, 0, 0, SRCINVERT)) { if (GetDeviceCaps(hdcScreen, BITSPIXEL) <= 8) { //
// 6 is the XOR of the index for COLOR1 and the index
// for COLOR2.
//
SetBkColor(hdc2, PALETTEINDEX(6)); } else { SetBkColor(hdc2, (COLORREF)(COLOR1 ^ COLOR2)); }
HDC hdcMask = CreateCompatibleDC(NULL); if (hdcMask) { HGDIOBJ hbmOld = SelectObject(hdcMask, *phbMask); if (hbmOld) { if (BitBlt(hdcMask, 0, 0, pSize->cx, pSize->cy, hdc2, 0, 0, SRCCOPY)) { //
// RasterOP 0x00220326 does a copy of the ~mask bits
// of hdc1 and sets everything else to 0 (Black).
//
if (BitBlt(hdc1, 0, 0, pSize->cx, pSize->cy, hdcMask, 0, 0, 0x00220326)) { hr = S_OK; } } SelectObject(hdcMask, hbmOld); } DeleteDC(hdcMask); } } SelectObject(hdc2, hbmOld2); } DeleteObject(hbm2); } DeleteDC(hdc2); } return hr; }
BOOL CICWGifConvert::ColorFill(HDC hdc, const SIZE * pSize, COLORREF clr) { ASSERT(hdc);
BOOL fRet = FALSE;
HBRUSH hbSolid = CreateSolidBrush(clr); if (hbSolid) { HGDIOBJ hbOld = SelectObject(hdc, hbSolid); if (hbOld) { PatBlt(hdc, 0, 0, pSize->cx, pSize->cy, PATCOPY); fRet = TRUE;
SelectObject(hdc, hbOld); } DeleteObject(hbSolid); } return fRet; }
void CALLBACK ImgCtx_Callback(void* pIImgCtx,void* pfDone) { ASSERT(pfDone);
*(BOOL*)pfDone = TRUE;
return; }
|