DC知识总结

15 篇文章 0 订阅
10 篇文章 2 订阅

一、 ::GetDC 与 ::ReleaseDC

函数原型:
HDC GetDC(HWND hWnd);
int ReleaseDC(HWND hWnd, HDC hDC);

GetDC获取窗口客户区域的设备环境。每次获取一个设备环境时都会用默认属性对它进行初始化。
GetDC与ReleaseDC一定要配对使用,否则GetDC没有ReleaseDC会有资源泄露。
GetDC获取的设备环境变量由Windows系统管理,数量是有限的,Windows开辟一个固定大小的空间存储某一数量的设备环境变量,GetDC会占用一个设备环境变量,只有ReleaseDC了,才能释放了这个环境变量的位置,也才能被后续的程序使用。

对应的CWnd::GetDC 与CWnd::ReleaseDC也需要配对使用。
我们可以看下CWnd::GetDC与CWnd::ReleaseDC的源码

CDC* CWnd::GetDC()
{ return CDC::FromHandle(::GetDC(m_hWnd)); }

int CWnd::ReleaseDC(CDC* pDC)
{ return ::ReleaseDC(m_hWnd, pDC->m_hDC); }

注意:
我们可以对同一个窗口多次调用GetDC获取设备环境句柄,当然每次的句柄值都是不一样的,因为虽然它们是同一个窗口的设备环境变量,但我们可以多次调用获得多个,并且设置每个环境句柄拥有不同的属性值。必须要理解这个。

二、 CDC::FromHandle

先看下源码

CDC* PASCAL CDC::FromHandle(HDC hDC)
{
    CHandleMap* pMap = afxMapHDC(TRUE); //create map if not exist
    ASSERT(pMap != NULL);
    CDC* pDC = (CDC*)pMap->FromHandle(hDC);
    ASSERT(pDC == NULL || pDC->m_hDC == hDC);
    return pDC;
}

可以看出,程序会从CHandleMap中去寻找和hDC对应的CDC。
MFC程序存在一个全局的CHandleMap变量,它记录程序中和HDC相关联的CDC之间的映射关系。

class CHandleMap
{
private:
    CMapPtrToPtr m_permanentMap;
    CMapPtrToPtr m_temporaryMap;
};

pMap->FromHandle(hDC)
会先从m_permanentMap中去查找和hDC关联的CDC对象,也就是说先查询看看有没有CDC对象和hDC关联。
如果有则返回该CDC对象的指针。
如果没有则在m_temporaryMap中去查找,如果有则返回该CDC对象的指针,如果没有,则会自动创建一个临时的CDC对象和hDC关联,并在m_temporaryMap中记录映射关系,并返回该CDC对象的句柄。

m_permanentMap和m_temporaryMap有什么区别呢?
一个是临时的映射map对象,一个是永久的映射map对象。
可以这么理解,临时的映射map对象中存储的CDC的指针,该CDC对象是由程序框架创建的,在程序空闲时会自动释放,不用用户自己释放。
而永久的映射map对象中存储的CDC的指针,该CDC对象是由用户自己创建的,需要用户自己释放。当CDC对象是由用户new的时候,一定要调用delete,当然如果CDC对象创建在栈上,在生存周期结束时会自动调用析构函数。

三、 CDC::Attach 与 CDC::Detach

先看下源码:

BOOL CDC::Attach(HDC hDC)
{
    m_hDC = hDC;
    CHandleMap* pMap = afxMapHDC(TRUE); // create map if not exist
    pMap->SetPermanent(m_hDC, this);

    return TRUE;
}

HDC CDC::Detach()
{
    HDC hDC = m_hDC;
    CHandleMap* pMap = afxMapHDC(); // don't create if not exist
    if (pMap != NULL)
        pMap->RemoveHandle(m_hDC);

    m_hDC = NULL;
    return hDC;
}

可以看出,Attach用于实现HDC和CDC之间的映射关系。Detach用于解除HDC和CDC之间的映射关系。
都是对CHandleMap中的m_permanentMap进行操作。

class CHandleMap
{
private:
    CMapPtrToPtr m_permanentMap;
    CMapPtrToPtr m_temporaryMap;
};

四、 CDC::~CDC()

先看下源码:

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

看以看出,在析构时会释放HDC资源。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值