Windows GDI:CDC使用总结

来源:互联网 发布:linux大学时候开发 编辑:程序博客网 时间:2024/05/29 04:38

一、DC函数的配对使用

GetDC — ReleaseDC
GetWindowDC — ReleaseDC
CreateDC — DeleteDC

二、GetDC与GetWindowDC

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

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();}

1、先看一下析构函数

CDC::~CDC(){if (m_hDC != NULL)::DeleteDC(Detach());}

很显然,在析构函数中先Detach()了,再DeleteDC了

2、再看一下Attach与Detach

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

3、CDC* FromHandle(HDC 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-&gt;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

4、DeleteTempMap

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.

5、CDC::SelectObject()

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-&gt;GetSafeHandle());    if (m_hAttribDC != NULL)        hOldObj = ::SelectObject(m_hAttribDC, pPen-&gt;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(&amp;pen);...dc.SelectObject(pOldPen);

三、CClientDC

CClientDC:

class CClientDC : public CDC{protected:    HWND m_hWnd;}

1、先看一下构造与析构函数

CClientDC::CClientDC(CWnd* pWnd){    Attach(::GetDC(m_hWnd = pWnd-&gt;GetSafeHwnd()));}CClientDC::~CClientDC(){    ::ReleaseDC(m_hWnd, Detach());}

2、CClientDC在MFC对话框中的常用用法

CCientDC dc(this);
dc.执行操作

四、CPaintDC

CPaintDC:

class CPaintDC : public CDC{protected:    HWND m_hWnd;}

1、先看一下构造与析构函数

CPaintDC::CPaintDC(CWnd* pWnd){    Attach(::BeginPaint(m_hWnd = pWnd-&gt;m_hWnd, &amp;m_ps));}CPaintDC::~CPaintDC(){    ::EndPaint(m_hWnd, &amp;m_ps);    Detach();}
0 0
原创粉丝点击