233 lines
5.5 KiB
C++
233 lines
5.5 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CBitmapImgCtx
|
|
//
|
|
// Implement IImgCtx for drawing out of a bitmap
|
|
//
|
|
// WARNING: Incomplete implementation -- just barely enough to keep
|
|
// listview happy. Should not be exposed to anyone other than listview.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "ctlspriv.h"
|
|
#include <iimgctx.h>
|
|
|
|
class CBitmapImgCtx : public IImgCtx
|
|
{
|
|
public:
|
|
// *** IUnknown methods ***
|
|
STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppv);
|
|
STDMETHODIMP_(ULONG) AddRef(void);
|
|
STDMETHODIMP_(ULONG) Release(void);
|
|
|
|
// *** IImgCtx methods ***
|
|
STDMETHODIMP Load(LPCWSTR pszUrl, DWORD dwFlags);
|
|
STDMETHODIMP SelectChanges(ULONG ulChgOn, ULONG ulChgOff, BOOL fSignal);
|
|
STDMETHODIMP SetCallback(PFNIMGCTXCALLBACK pfn, void * pvPrivateData);
|
|
STDMETHODIMP Disconnect();
|
|
|
|
STDMETHODIMP GetUpdateRects(LPRECT prc, LPRECT prcImg, LPLONG pcrc);
|
|
STDMETHODIMP GetStateInfo(PULONG pulState, LPSIZE psize, BOOL fClearChanges);
|
|
STDMETHODIMP GetPalette(HPALETTE *phpal);
|
|
|
|
STDMETHODIMP Draw(HDC hdc, LPRECT prcBounds);
|
|
STDMETHODIMP Tile(HDC hdc, LPPOINT pptBackOrg, LPRECT prcClip, LPSIZE psize);
|
|
STDMETHODIMP StretchBlt(HDC hdc, int dstX, int dstY, int dstXE, int dstYE, int srcX, int srcY, int srcXE, int srcYE, DWORD dwROP);
|
|
|
|
public:
|
|
CBitmapImgCtx() : _cRef(1) { }
|
|
BOOL Initialize(HBITMAP hbm);
|
|
|
|
protected:
|
|
~CBitmapImgCtx()
|
|
{
|
|
if (_hbr) DeleteObject(_hbr);
|
|
}
|
|
|
|
// Keep _cRef as first member so we can coalesce
|
|
// with ILVRange's IUnknown implementation
|
|
int _cRef;
|
|
|
|
HBRUSH _hbr; // Bitmap pattern brush
|
|
SIZE _sizBmp; // Size of original bitmap
|
|
|
|
PFNIMGCTXCALLBACK _pfnCallback;
|
|
LPVOID _pvRefCallback;
|
|
};
|
|
|
|
STDAPI_(IImgCtx *) CBitmapImgCtx_Create(HBITMAP hbm)
|
|
{
|
|
CBitmapImgCtx *pbic = new CBitmapImgCtx();
|
|
if (pbic && !pbic->Initialize(hbm))
|
|
{
|
|
pbic->Release();
|
|
pbic = NULL;
|
|
}
|
|
return pbic;
|
|
}
|
|
|
|
// CBitmapImgCtx::Initialize
|
|
|
|
BOOL CBitmapImgCtx::Initialize(HBITMAP hbm)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
|
|
_hbr = CreatePatternBrush(hbm);
|
|
if (_hbr)
|
|
{
|
|
BITMAP bm;
|
|
if (GetObject(hbm, sizeof(bm), &bm))
|
|
{
|
|
_sizBmp.cx = bm.bmWidth;
|
|
_sizBmp.cy = bm.bmHeight;
|
|
fSuccess = TRUE;
|
|
}
|
|
}
|
|
return fSuccess;
|
|
}
|
|
|
|
// IUnknown::QueryInterface
|
|
|
|
HRESULT CBitmapImgCtx::QueryInterface(REFIID iid, void **ppv)
|
|
{
|
|
if (IsEqualIID(iid, IID_IImgCtx) || IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppv = SAFECAST(this, IImgCtx *);
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
_cRef++;
|
|
return NOERROR;
|
|
}
|
|
|
|
// IUnknown::AddRef
|
|
|
|
ULONG CBitmapImgCtx::AddRef()
|
|
{
|
|
return ++_cRef;
|
|
}
|
|
|
|
// IUnknown::Release
|
|
|
|
ULONG CBitmapImgCtx::Release()
|
|
{
|
|
if (--_cRef)
|
|
return _cRef;
|
|
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
// IImgCtx::Load
|
|
|
|
HRESULT CBitmapImgCtx::Load(LPCWSTR pszUrl, DWORD dwFlags)
|
|
{
|
|
ASSERT(0); // Listview should never call this
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
// IImgCtx::SelectChanges
|
|
|
|
HRESULT CBitmapImgCtx::SelectChanges(ULONG ulChgOn, ULONG ulChgOff, BOOL fSignal)
|
|
{
|
|
// Listview always calls with exactly these parameters
|
|
ASSERT(ulChgOn == IMGCHG_COMPLETE);
|
|
ASSERT(ulChgOff == 0);
|
|
ASSERT(fSignal == TRUE);
|
|
|
|
// Listview always calls after setting the callback
|
|
ASSERT(_pfnCallback);
|
|
|
|
_pfnCallback(this, _pvRefCallback);
|
|
return S_OK;
|
|
}
|
|
|
|
// IImgCtx::SetCallback
|
|
|
|
HRESULT CBitmapImgCtx::SetCallback(PFNIMGCTXCALLBACK pfn, void * pvPrivateData)
|
|
{
|
|
_pfnCallback = pfn;
|
|
_pvRefCallback = pvPrivateData;
|
|
return S_OK;
|
|
}
|
|
|
|
// IImgCtx::Disconnect
|
|
|
|
HRESULT CBitmapImgCtx::Disconnect()
|
|
{
|
|
ASSERT(0); // Listview should never call this
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
// IImgCtx::GetUpdateRects
|
|
|
|
HRESULT CBitmapImgCtx::GetUpdateRects(LPRECT prc, LPRECT prcImg, LPLONG pcrc)
|
|
{
|
|
ASSERT(0); // Listview should never call this
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
// IImgCtx::GetStateInfo
|
|
|
|
HRESULT CBitmapImgCtx::GetStateInfo(PULONG pulState, LPSIZE psize, BOOL fClearChanges)
|
|
{
|
|
*pulState = IMGCHG_COMPLETE;
|
|
*psize = _sizBmp;
|
|
return S_OK;
|
|
}
|
|
|
|
// IImgCtx::GetPalette
|
|
|
|
HRESULT CBitmapImgCtx::GetPalette(HPALETTE *phpal)
|
|
{
|
|
*phpal = NULL;
|
|
return S_OK;
|
|
}
|
|
|
|
// IImgCtx::Draw
|
|
//
|
|
// Drawing is a special case of tiling where only one tile's worth
|
|
// gets drawn. Listview (our only caller) is careful never to ask
|
|
// for more than one tile's worth, so we can just forward straight
|
|
// to IImgCtx::Tile().
|
|
|
|
HRESULT CBitmapImgCtx::Draw(HDC hdc, LPRECT prcBounds)
|
|
{
|
|
POINT pt = { prcBounds->left, prcBounds->top };
|
|
|
|
ASSERT(prcBounds->right - prcBounds->left <= _sizBmp.cx);
|
|
ASSERT(prcBounds->bottom - prcBounds->top <= _sizBmp.cy);
|
|
|
|
return Tile(hdc, &pt, prcBounds, NULL);
|
|
}
|
|
|
|
// IImgCtx::Tile
|
|
|
|
HRESULT CBitmapImgCtx::Tile(HDC hdc, LPPOINT pptBackOrg, LPRECT prcClip, LPSIZE psize)
|
|
{
|
|
ASSERT(psize == NULL); // Listview always passes NULL
|
|
|
|
POINT pt;
|
|
if (SetBrushOrgEx(hdc, pptBackOrg->x, pptBackOrg->y, &pt))
|
|
{
|
|
FillRect(hdc, prcClip, _hbr);
|
|
SetBrushOrgEx(hdc, pt.x, pt.y, NULL);
|
|
}
|
|
|
|
// Nobody checks the return value
|
|
return S_OK;
|
|
}
|
|
|
|
// IImgCtx::StretchBlt
|
|
|
|
HRESULT CBitmapImgCtx::StretchBlt(HDC hdc, int dstX, int dstY, int dstXE, int dstYE, int srcX, int srcY, int srcXE, int srcYE, DWORD dwROP)
|
|
{
|
|
ASSERT(0); // Listview should never call this
|
|
return E_NOTIMPL;
|
|
}
|