MFC CDC类中的BUG及替代方案&CPaintDC、CClientDC及CWindowDC的使用

MFC CDC类中的BUG及替代方案

在MFC中,最常用的绘图类非CDC类莫属。CDC类可以完成绝大多数的绘图操作。适量的绘图用CDC类不会有什么问题,但是,绘图量一大起来,程序就经常莫名其妙的崩溃,而且除了CResourceException异常外没有更多的崩溃信息,这种情形一般是CDC类的内存泄露导致的。CDC类每Release一次就会因GDI对象未彻底回收导致的4KB的内存泄露(不要问我怎么知道的,我在写一个音频播放器时用了CDC类以每秒24帧的速度绘制它的波形图,结果十分钟就崩掉了。后面排查发现,就是这CDC对象惹的祸。而且,在微软发布的BUG清单中,就有CDC这玩意的身影)。一般在发生时,可以在任务管理器中的GDI对象中发现GDI对象数量上升,在Visual Studio的诊断会话中也会发现内存占用率的上升。在GDI对象数接近极端值时,对话框的绘制开始变得混乱,一旦GDI对象数超过极端值,程序便会崩溃。但是,办法总是有的,下面是我总结出的几种解决方法。

1、使用CDC的子类

CDC类较为常用的子类有CPaintDC、CClientDC、CWindowDC三种。为了更好地使用它们,我们要先了解他们的作用。

类名用途
CPaintDC一般用于与WM_PAINT消息对应的onPaint函数中,只能用于客户区绘图,用于维持窗口完整。相当于先调用BeginPaint进行绘图再调用EndPaint结束绘图并移除消息。CPaintDC对象一般会在onPaint函数开始时创建并于结束时自动释放,不会造成泄露。
CClientDC用于对客户区的绘图,此对象描述的是该CWnd对象的客户区,用法与CDC相同,但是会在析构时自动释放对象且不会造成泄露。
CWindowDC用于对整个窗口的绘图,此对象描述的是该CWnd对象的整窗口,用法也与CDC相同,而且也会自动释放并且不会造成泄露。

这三个类的构造函数都是CXXXDC(CWnd* pWnd),所以只管传CWnd对象过去就可以像CDC一样使用了。既然已经知道用什么,怎么用,那么就可以实践了。
(由于本人懒癌晚期,不想把代码改回有BUG的状态,所以就不上图直接上结论了)
CPaintDC类因为只能在WM_PAINT中使用,所以在其他地方根本没用。由于WM_PAINT会在窗口显示、还原、最大化时发送,所以如果要在窗口绘制时自绘某个区域则可以在该消息中使用CPaintDC对象完成。但此操作时要让系统先绘制,否则自绘图形会被系统覆盖。
CClientDC类本身就是用于客户区绘制的,所以不用想,肯定画得出来。
CWindowDC类用于整窗口绘画,包括标题栏和侧边框,所以可以用于自绘对话框等界面美化上。
注意:CPaintDC与CClientDC以客户区左上角为原点定位,而CWindowDC以屏幕左上角为原点定位,不要因为这个问题而搞上半天!

2、使用GDI+

由于我没使用过GDI+,所以无法给出什么有效的方法,只听说GDI+不会出现泄露问题,有兴趣的朋友可以学一学。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值