Windows2003-3790/inetcore/connectionwizard/icwutil/gifcon.cpp
2020-09-30 16:53:55 +02:00

487 lines
13 KiB
C++

// 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;
}