CGdiObject说明
CGdiObject类是一个为各种windows图形设备接口(GDI)对象(比如位图,区域,画刷,画笔,调试板,字体等)提供的基类。
class CGdiObject : public CObject
我们不会直接构造一个CGdiObject对象,而是使用某一个派生类如CPen或CBrush创建。
CGdiObject::DeleteObject
#include <afxwin.h>
BOOL DeleteObject( );
返回值:如果GDI对象被成功删除,则返回非零值,否则为0。
说明:通过释放内部附加的GDI对象占有的系统存储来删除它们。
与CGdiObject对象有关的存储不受此调用的影响,受析构调用的影响。
如果CGdiObject对象正被选入设备上下文中,则应用不可对此对象调用DeleteObject.
当一个模式画刷被删除时,与之先关联的位图不被删除。位图资源对象必须被独立删除。
CGdiObject的子类:
类 句柄类型
CPen HPEN
CBrush HBRUSH
CFont HFONT
CBitmap HBITMAP
CPalette HPALETTE
CRgn HRGN
这些类在调用其Create函数来创建的话后必须调用DeleteObject( );
关于上述说法的证据查找:
CObject的析构函数是纯虚函数;virtual ~CObject() = 0;
CGdiObject直接派生于CObject,其中有BOOL CGdiObject::DelectObject()方法用于释放资源。但是为保证资源释放成功GDI对象必须不被DC选中,所以使用GDI对象后应该将其选出DC。
有人说:“CBrush,CPen,CFont,CBitmap都是从CGdiObject类派生的,CGdiObject的析构函数中会调用DeleteObject,所以在对象销毁前自己用代码DeleteObject是多余的。”还有人说,“用CPen::CreatePen()来初始化的才需要”??
MSDN中相关的的说明:
对于CPen的说明
When an application no longer requires a given pen, it should call the CGdiObject::DeleteObject member function or destroy the CPen object so the resource is no longer in use. An application should not delete a pen when the pen is selected in a device context.
我的理解是:“在程序中,类似CPen这样的对象在不用的时候应该手动调用CGdiObject::DeleteObject来释放资源。”
以此,合理的做法如下:
void CRingView::OnDraw(CDC* pDC)
{
CRingDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
PointArray& pointArray = pDoc->GetPointArray();
ColorArray& colorArray = pDoc->GetColorArray();
int iSize = (int)pointArray.GetSize();
for (int iIndex = 0; iIndex<iSize; ++iIndex)
{
CPoint point = pointArray[iIndex];
COLORREF color = colorArray[iIndex];
CPen pen(PS_SOLID,0,BLACK);
CBrush brush(color);
//将临时的CPen和CBrush选入DC,通过返回值保存原来的GDI对象
CPen* pOldPen = pDC->SelectObject(&pen);
CBrush* pOldBrush = pDC->SelectObject(&brush);
//使用含有pen和brush的DC进行画图
pDC->Ellipse(point.x-RADIUS,point.y-RADIUS,point.x+RADIUS,point.y+RADIUS);
//重新载入原来的GDI对象使得临时GDI对象不再被引用而可以销毁
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
//调用DeleteObject释放pen和brush的资源
pen.DeleteObject();
brush.DeleteObject();
}
}
最后一点:为了避免临时资源的频繁创建和释放,可以改成全局资源,在程序销毁时统一释放。