📄 untitled-35.txt
字号:
64 MFC Windows程序设计(第 2版)
onPaint可能会创建成千上万的 GDI对象,占据着 Windows GDI的系统内存空间。很快,创建
画笔和画刷的调用会失败,应用程序的OnPaint处理程序也会莫名其妙地停止工作。
VisualC+十有一种简单的方法用来确定是否成功地删除了画笔、画刷和其他资源:只要
在调试状态下运行应用程序的调试版本即可。在应用程序终结时,没有释放的资源会显示
在调试窗口中。MFC跟踪CPen、CBrush和其他C0bject派生类的内存分配情况,并在对象没
有删除时通知您。如果从调试信息还不能确定哪些对象没有删除,则可以在包含Afxwin.h
的语句之后,添加一条语句到应用程序源代码中:
# define new DEBUG.NEW
(Appwizard生成的应用程序自动包含了这条语句。)在未释放对象的调试信息中有文件名和
行号可以帮助您准确地找到泄漏位置。
2.2.11取消对GDI对象的选定
删除由用户创建的GDI对象是重要的,而不能删除已经选人设备描述表的GDI对象也
同样不容忽视。试图用已删除的对象画图的程序代码是错误的。它没有崩溃的唯一原因在
于: Windows GDI中各处都有错误检查程序代码防止这种崩溃的发生。
遵守这条规则并不像听上去那么容易。下面的onPaint处理程序允许删除已经选人设
备描述表的画刷。知道为什么吗?
vojdCMainwindow::onPaint()
《
CPaintDC dc(this);
CBrushbrush(RGB(255, 0, 0》;
dc.Selectobject(&brush);
dc.Elliose(0,0,200,100);
Z
问题是这样的。 CPaintDC对象和 CBrush对象是在栈上创建的。由于 CBrush是第二个
被创建的,所以它的析构函数首先被调用,相关的GDI画刷在dC超出范围之前就被删除了。
通过先创建画笔后创建DC,可以解决这个问题。但是如果程序代码的健壮性依赖于栈变量
以特定顺序创建,那么这样的程序代码实际上是很糟糕的。就可维护性而言,这种程序简直
是太可怕了。
解决方法是在CPaintDC对象超出范围之前将CBrush从设备描述表中提取出来。这里
没有Unsele。tobject函数,我们可以通过选人另一个对象将当前对象从设备描述表中提出。
大部分 Windows编程人员习惯上首先保存每种对象类型首次调用 Selectobject时返回的指
针,然后用这个指针重选默认对象。还有一种同样有效的办法是将备用对象选人设备描述
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -