赞
踩
GetDC — ReleaseDC
GetWindowDC — ReleaseDC
CreateDC — DeleteDC
1、HDC GetDC(HWND hWnd)
int ReleaseDC(HWND hWnd,
HDC hDC);
2、HDC GetWindowDC(HWND hWnd);
int ReleaseDC(HWND hWnd,
HDC hDC);
通过GetDC与GetWindowDC获取HDC,使用完毕之后均需ReleaseDC,否则会有资源泄露
GetDC与GetWindowDC的区别是:
GetDC获取的是客户区的DC
GetWindowDC获取的是the device context (DC) for the entire window,包括非客户区
怎样获取整个屏幕的DC?
GetDC(NULL)
GetWindowDC(NULL)
CDC:
class CDC : public CObject
{
public:
HDC m_hDC;
public:
BOOL Attach(HDC hDC);
HDC Detach();
static CDC* PASCAL FromHandle(HDC hDC);
static void PASCAL DeleteTempMap();
}
CDC::~CDC()
{
if (m_hDC != NULL)
::DeleteDC(Detach());
}
很显然,在析构函数中先Detach()了,再DeleteDC了
Attach在于将HDC与CDC的对象关联起来,并且在Map表中创建一条记录
BOOL CDC::Attach(HDC hDC)
{
if (hDC == NULL)
{
return FALSE;
}
m_hDC = hDC;
CHandleMap* pMap = afxMapHDC(TRUE); // create map if not exist
pMap->SetPermanent(m_hDC, this);
return TRUE;
}
Detach在于将HDC与CDC的对象去除关联,当然会在Map表中删除这条记录
HDC CDC::Detach()
{
HDC hDC = m_hDC;
if (hDC != NULL)
{
CHandleMap* pMap = afxMapHDC(); // don't create if not exist
if (pMap != NULL)
pMap->RemoveHandle(m_hDC);
}
m_hDC = NULL;
return hDC;
}
在CDC<>HDC的Map表中查找hDC对应的CDC
CDC* PASCAL CDC::FromHandle(HDC hDC)
{
CHandleMap* pMap = afxMapHDC(TRUE); //create map if not exist
CDC* pDC = (CDC*)pMap->FromHandle(hDC);
return pDC;
}
Note:如果在CDC<>HDC的Map表中没有找到hDC相关的记录,系统会创建一个临时的CDC.
此时,不用我们delete了,系统会用空闲线程处理.不必深究,知道就可以了.
由于CDC的析构函数调用的是DeleteDC,所以CDC一般用来接收CreateDC得到的HDC.
或者也可以这样用,先Attach不是用CreateDC获取的HDC,再Detach,这样就不会DeleteDC了.
CClientDC的析构函数调用的是ReleaseDC
CPaintDC的析构函数调用的是EndPaint
Called automatically by the CWinApp idle-time handler, DeleteTempMap deletes any temporary CDC objects created by FromHandle,
but does not destroy the device context handles (hDCs) temporarily associated with the CDC objects.
CPen* SelectObject(
CPen* pPen
);
CBrush* SelectObject(
CBrush* pBrush
);
...
CPen* CDC::SelectObject(CPen* pPen)
{
HGDIOBJ hOldObj = NULL;
if (m_hDC != m_hAttribDC)
hOldObj = ::SelectObject(m_hDC, pPen->GetSafeHandle());
if (m_hAttribDC != NULL)
hOldObj = ::SelectObject(m_hAttribDC, pPen->GetSafeHandle());
return (CPen*)CGdiObject::FromHandle(hOldObj);
}

SelectObject返回的CPen*为CGdiObject::FromHandle获取的
假若这里通过CGdiObject::FromHandle得到的是临时创建的CPen*
由于CGdiObject::DeleteTempMap也不会DeleteObject掉临时CGdiObject关联的HGDIOBJECT
所以,这种机制才保证了代码的正确性:
CDC dc;
dc.CreateDC(...)
CPen pen;
pen.CreatePen(...)
CPen* pOldPen = dc.SelectObject(&pen);
...
dc.SelectObject(pOldPen);
CClientDC:
class CClientDC : public CDC
{
protected:
HWND m_hWnd;
}
CClientDC::CClientDC(CWnd* pWnd)
{
Attach(::GetDC(m_hWnd = pWnd->GetSafeHwnd()));
}
CClientDC::~CClientDC()
{
::ReleaseDC(m_hWnd, Detach());
}
CCientDC dc(this);
dc.执行操作
CPaintDC:
class CPaintDC : public CDC
{
protected:
HWND m_hWnd;
}
CPaintDC::CPaintDC(CWnd* pWnd)
{
Attach(::BeginPaint(m_hWnd = pWnd->m_hWnd, &m_ps));
}
CPaintDC::~CPaintDC()
{
::EndPaint(m_hWnd, &m_ps);
Detach();
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。