MFC Windows 程序设计->取消对GDI对象的选定
来源:互联网 发布:条件筛选数据计数 编辑:程序博客网 时间:2024/05/21 10:31
It's important to delete the GDI objects you create, but it's equally important to never delete a GDI object while it's selected into a device context. Code that attempts to paint with a deleted object is buggy code. The only reason it doesn't crash is that the Windows GDI is sprinkled with error-checking code to prevent such crashes from occurring.
Abiding by this rule isn't as easy as it sounds. The following OnPaint handler allows a brush to be deleted while it's selected into a device context. Can you figure out why?
void CMainWindow::OnPaint (){ CPaintDC dc (this); CBrush brush (RGB (255, 0, 0)); dc.SelectObject (&brush); dc.Ellipse (0, 0, 200, 100);}
Here's the problem. A CPaintDC object and a CBrush object are created on the stack. Since the CBrush is created second, its destructor gets called first. Consequently, the associated GDI brush is deleted before dc goes out of scope. You could fix this by creating the brush first and the DC second, but code whose robustness relies on stack variables being created in a particular order is bad code indeed. As far as maintainability goes, it's a nightmare.
The solution is to select the CBrush out of the device context before the CPaintDC object goes out of scope. There is no UnselectObject function, but you can select an object out of a device context by selecting in another object. Most Windows programmers make it a practice to save the pointer returned by the first call to SelectObject for each object type and then use that pointer to reselect the default object. An equally viable approach is to select stock objects into the device context to replace the objects that are currently selected in. The first of these two methods is illustrated by the following code:
The second method works like this:
The big question is why this is necessary. The simple truth is that it's not. In modern versions of Windows, there's no harm in allowing a GDI object to be deleted a split second before a device context is released, especially if you're absolutely sure that no drawing will be done in the interim. Still, cleaning up a device context by deselecting the GDI objects you selected in is a common practice in Windows programming. It's also considered good form, so it's something I'll do throughout this book.
Incidentally, GDI objects are occasionally created on the heap, like this:
CPen* pPen = new CPen (PS_SOLID, 1, RGB (255, 0, 0));CPen* pOldPen = dc.SelectObject (pPen);
At some point, the pen must be selected out of the device context and deleted. The code to do it might look like this:
dc.SelectObject (pOldPen);delete pPen;
Since the SelectObject function returns a pointer to the object selected out of the device context, it might be tempting to try to deselect the pen and delete it in one step:
delete dc.SelectObject (pOldPen);
But don't do this. It works fine with pens, but it might not work with brushes. Why? Because if you create two identical CBrushes, 32-bit Windows conserves memory by creating just one GDI brush and you'll wind up with two CBrush pointers that reference the same HBRUSH. (An HBRUSH is a handle that uniquely identifies a GDI brush, just as an HWND identifies a window and an HDC identifies a device context. A CBrush wraps an HBRUSH and stores the HBRUSH handle in its m_hObject data member.) Because CDC::SelectObject uses an internal table maintained by MFC to convert the HBRUSH handle returned by SelectObject to a CBrush pointer and because that table assumes a one-to-one mapping between HBRUSHes and CBrushes, the CBrush pointer you get back might not match the CBrush pointer returned by new. Be sure you pass delete the pointer returned by new. Then both the GDI object and the C++ object will be properly destroyed.
- MFC Windows 程序设计->取消对GDI对象的选定
- 《MFC windows程序设计》中关于GDI对象的选定
- windows程序设计(9):简单的GDI对象
- 《Windows程序设计》读书笔记------------->>GDI的简单基础<<
- windows程序设计 GDI简介
- Windows程序设计-GDI图形
- 对《Windows程序设计》的疑惑
- windows程序设计之GDI简介
- Windows程序设计:GDI映射模式
- 取消windows开机对硬盘的扫描
- MFC的GDI对象的构造与释放
- 《MFC Windows程序设计》中Accel的改进
- jquery对select的选定和获取选定值
- MFC ListControl 删除选定的多行
- 对mssql出现选定的用户拥有对象而无法删除的处理
- 《MFC Windows 程序设计》
- mfc windows 程序设计
- MFC Windows 程序设计(1)
- oracle substr()函数
- 几个c#题行,你能做出来吗。
- SSH 配置文件
- 写给销售新人:你注定要失败的8个错误
- .net 获取url的方法
- MFC Windows 程序设计->取消对GDI对象的选定
- 用putty 远程登录Ubuntu时 显示network error connection refused 解决方法 (学习记录)
- 字符串处理
- oracle调用java方法的例子(下面所有代码都是在sql/plus中写)
- WinForm 移动无边框窗体
- js_1
- UTF-8 GBK UTF8 GB2312之间的区别和关系 (转载)
- 很早以前收集的常用代码
- 用python写的一个超小型配置文件读取器