/*
* $Header: /home/dscott/nasty/memory/autogdi.cpp,v 1.1 2001/11/06 21:48:50 dscott Exp $
* $NoKeywords: $
*/
#include
#include
DeviceContext::DeviceContext()
: type_(memory)
, hWnd_(0)
, hDC_(::CreateCompatibleDC(0))
, pPaint_(0)
{
}
/**
* Ctor, takes a window context
* Intended usage:
* DeviceContext dc(hWnd, ::GetDC(hWnd));
* DeviceContext dc(hWnd, ::GetWindowDC(hWnd));
* hWnd can be null when retrieving the DC of the screen.
*/
DeviceContext::DeviceContext(HWND hWnd, HDC hDC)
: type_(window), hWnd_(hWnd), hDC_(hDC), pPaint_(0)
{
ASSERT(::IsWindow(hWnd));
}
DeviceContext::DeviceContext(HWND hWnd /*, HRGN hRgn, DWORD flags */)
: type_(window)
, hWnd_(hWnd)
// , hDC_(::GetDCEx(hWnd, hRgn, flags))
, hDC_(::GetDC(hWnd))
, pPaint_(0)
{
ASSERT(::IsWindow(hWnd));
}
/**
* Ctor, to be used instead of ::BeginPaint()
*/
DeviceContext::DeviceContext(HWND hWnd, PAINTSTRUCT& ps)
: type_(paint), hWnd_(hWnd), hDC_(0), pPaint_(&ps)
{
ASSERT(::IsWindow(hWnd_));
hDC_ = ::BeginPaint(hWnd, pPaint_);
}
/**
* Ctor, creates a memory devices context compatible with that.hDC_
*/
DeviceContext::DeviceContext(const DeviceContext& that)
: type_(memory)
, hDC_(::CreateCompatibleDC(that.hDC_))
, hWnd_(0)
, pPaint_(0)
{
}
/**
* Dtor, unselects and destroys all objects currently selected
* into the context, then releases the context depending on how
* it was created
*/
DeviceContext::~DeviceContext()
{
if (!IsValid())
{
return;
}
// restore originals
std::map::const_iterator i(orgSelected_.begin());
for (; i != orgSelected_.end(); ++i)
{
ASSERT(i->second);
::SelectObject(hDC_, i->second);
}
switch (type_)
{
case memory:
::DeleteDC(hDC_);
break;
case window:
::ReleaseDC(hWnd_, hDC_);
break;
case paint:
ASSERT(pPaint_);
ASSERT(::IsWindow(hWnd_));
::EndPaint(hWnd_, pPaint_);
break;
default: ASSERT(false);
}
}
/**
* Selects an object into the device context. Returns false if
* it fails, clients may call GetLastError() to get the error code
*/
HGDIOBJ DeviceContext::SelectObject(gdi_handle& h)
{
ASSERT(IsValid()); // clients must check for a valid DeviceContext
ASSERT(h.get());
DWORD objType(::GetObjectType(h.get()));
// ASSERT(objType <= maxObjType);
HGDIOBJ hOld(::SelectObject(hDC_, h.get()));
// MSDN: "If an error occurs and the selected object is not a
// region, the return value is NULL. Otherwise, it is GDI_ERROR."
if (!hOld || (objType == OBJ_REGION && hOld == HGDI_ERROR))
{
return 0;
}
ASSERT(objType == ::GetObjectType(hOld));
ASSERT(objType > 0);
--objType; // base to zero
if (orgSelected_[objType] == 0)
{
orgSelected_[objType] = hOld;
}
ResetPtr(curSelected_[objType], new gdi_handle(h));
return hOld;
}
/**
*
*/
bool DeviceContext::CreateCompatibleBitmap(const DeviceContext& src,
int width,
int height)
{
ASSERT(IsValid());
ASSERT(src.IsValid());
HBITMAP hBmp(::CreateCompatibleBitmap(src.hDC_, width, height));
if (!hBmp)
{
return false;
}
gdi_handle bmp(hBmp);
SelectObject(bmp);
return true;
}
/**
*
*/
bool DeviceContext::CopyBitmapFrom( const DeviceContext& src,
const RECT& rcSrc,
const RECT& rcDest,
DWORD rop)
{
ASSERT(IsValid());
ASSERT(src.IsValid());
ASSERT(&src != this);
ASSERT(rcDest.left >= 0);
ASSERT(rcDest.top >= 0);
ASSERT(rcDest.right >= 0);
ASSERT(rcDest.bottom >= 0);
int width(rcDest.right - rcDest.left);
int height(rcDest.bottom - rcDest.top);
return ::BitBlt(hDC_,
rcDest.left,
rcDest.top,
width,
height,
src.hDC_,
rcSrc.left,
rcSrc.top,
rop) != 0;
}
/**
*
*/
void DeviceContext::CreateDIBSection(
const BITMAPINFO* pbi,
UINT usage,
void** ppvBits,
HANDLE hSection,
DWORD offset,
gdi_handle& bmp) const
{
ASSERT(pbi);
ASSERT(ppvBits);
ASSERT(IsValid());
bmp.reset(::CreateDIBSection(hDC_,
pbi, usage, ppvBits, hSection, offset));
}
/**
*
*/
int DeviceContext::SetDIBits(const gdi_handle& bmp,
UINT uStartScan, // starting scan line
UINT cScanLines, // number of scan
lines
const void* lpvBits, // array of bitmap
bits
const BITMAPINFO *lpbmi, // address of struct
with
// bitmap data
UINT fuColorUse)
{
ASSERT(bmp.get());
ASSERT(lpvBits);
ASSERT(lpbmi);
ASSERT(IsValid());
return ::SetDIBits(hDC_, static_cast(bmp.get()),
uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse);
}
/**
*
*/
int DeviceContext::FillRect(const RECT& rc, HBRUSH hBrush)
{
ASSERT(IsValid());
return ::FillRect(hDC_, &rc, hBrush);
}
/**
*
*/
bool DeviceContext::PatBlt(
int nXLeft, // x-coord. of upper-left corner of rect. to be
filled
int nYLeft, // y-coord. of upper-left corner of rect. to be
filled
int nWidth, // width of rectangle to be filled
int nHeight, // height of rectangle to be filled
DWORD dwRop) // raster operation code
{
ASSERT(IsValid());
return ::PatBlt(hDC_, nXLeft, nYLeft, nWidth, nHeight, dwRop) != 0;
}