分享

总结 GdiObject::DeleteObject()的使用 - TobyLin的学习之...

 chensirDSP 2010-06-06
看完了Microsoft Visual C++ windows applications by example 第一个例子,做下总结。

今天的感想:(1)CObject很好很强大。(2)MSDN上的解释是很好的,不过貌似英文转成中文再加上自己的理解就完全不对了。-_-! (3) GDI容易资源泄漏,以后得看看GDI+

//*********************************************************************

1.       在《Microsoft Visual C++ windows applications by example pdf128页的例子(在RingView.cpp中为View添加消息映射和处理)中:

光标必须指在MESSAGEMAP代码段(BEGIN_MESSAGE_MAPEND_MESSAGE_MAP之间),代码属性窗口才会出现“消息”选项。

 

2.       虚拟键码VK_PRIOR对应的是PAGEUP而不是向上方向键, (向上键是VK_UP)。同样VK_NEXT对应的是PAGEDOWN

 

3.       Ring程序中使用的是MDI,在编辑Menu资源时有IDR_MAINFRAMEIDR_RINGTYPE两个默认的MENU,其中IDR_RINGTYPE才是ringview对应的子窗口所对应的menu,应该修改这个menu。如果在IDR_MAINFRAME上修改是不对的。

 

4.       资源编辑器中的toolbar的按钮图标之间的分隔符:最后一个按钮图标是新建按钮图标的位置(类似于MENU编辑器),选中那个按钮图标后即可用画笔等工具对图标进行修改。将按钮图标用鼠标左键向右拖动大约半个图标的距离即可在图表前面添加一个分隔符,向左拖动则可将原有分隔符去掉。

 

5.       Menu item前面的小圆点(radio)是通过响应该menu itemUPDATE_COMMAND_UI事件进行设置的,通过回调函数参数*pCmdUI调用SetRadio方法:pCmdUI->SetRadioBOOL

 

6.       为按钮添加消息处理函数的两种方法:(1)在资源编辑器中右键对应的按钮选择“添加消息处理函数”,选择消息处理函数所在的类(如doc类)。 2)手动在MESSAGEMAP代码段的代码属性中添加对特定的按钮资源IDCOMMAND消息的响应。

 

7.       创建了CPenCBrushCGdiObject对象后绘画时应将其选入DC

pDC->selectobject(&pen);

pDC->selectobject(&brush);

如果想用空画笔或空画刷则选中NULL_BRUSH(相当于HOLLOW——BRUSH)NULL_PEN

 

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来释放资源。”

MSDN对于CGdiObject::DeleteObject()的说明:

CGdiObject::DeleteObject() Deletes the attached Windows GDI object from memory by freeing all system storage associated with the Windows GDI object. The storage associated with the CGdiObject object is not affected by this call. An application should not call DeleteObject on a CGdiObject object that is currently selected into a device context.

When a pattern brush is deleted, the bitmap associated with the brush is not deleted. The bitmap must be deleted independently.

 我的理解:该函数作用是释放资源,但是不会改变资源内存的内容。不要在资源被选入DC时调用。

 

以此,合理的做法如下:

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);

      //将临时的CPenCBrush选入DC通过返回值保存原来的GDI对象

      CPen* pOldPen = pDC->SelectObject(&pen);

      CBrush* pOldBrush = pDC->SelectObject(&brush);

      //使用含有penbrushDC进行画图

      pDC->Ellipse(point.x-RADIUS,point.y-RADIUS,point.x+RADIUS,point.y+RADIUS);

      //重新载入原来的GDI对象使得临时GDI对象不再被引用而可以销毁

      pDC->SelectObject(pOldPen);

      pDC->SelectObject(pOldBrush);

      //调用DeleteObject释放penbrush的资源

      pen.DeleteObject();

      brush.DeleteObject();

   }

}

 

最后一点:为了避免临时资源的频繁创建和释放,可以改成全局资源,在程序销毁时统一释放

 PS: 去VC目录里翻了下MFC源代码WinGDI.cpp,当中只有DeleteObject的定义,并没有析构函数的定义。AFXWIN.H中也仅仅是有声明没定义。貌似MFC的源码是半开源的?有人能找到~CGdiObject()的函数体吗?Help!!!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多