非模态对话框的创建及销毁

来源:互联网 发布:广州经纬之创网络 编辑:程序博客网 时间:2024/04/30 18:27

非模态对话框的创建流程为:

   m_pDlg = new CDlgTest();
   if(m_pDlg)
   {
      BOOL ret = m_pDlg->Create(IDD_DIALOG1, this);

      if(!ret)  
         AfxMessageBox(_T("Error creating Dialog"));

      m_pDlg->ShowWindow(SW_SHOW);
   }
   else
   {
      AfxMessageBox(_T("Error Creating Dialog Object"));
   }

Create函数应该详细深入的学习一下,

virtual BOOL Create(   LPCTSTR lpszTemplateName,   CWnd* pParentWnd = NULL );virtual BOOL Create(   UINT nIDTemplate,   CWnd* pParentWnd = NULL );
lpszTemplateName

Contains a null-terminated string that is the name of a dialog-box template resource.

pParentWnd

Points to the parent window object (of typeCWnd) to which the dialog object belongs. If it is NULL, the dialog object's parent window is set to the main application window.

nIDTemplate

Contains the ID number of a dialog-box template resource

Call Create to create a modeless dialog box using a dialog-box template from a resource.

You can put the call toCreate inside the constructor or call it after the constructor is invoked.

Two forms of theCreate member function are provided for access to the dialog-box template resource by either template name or template ID number (for example, IDD_DIALOG1).

For either form, pass a pointer to the parent window object.IfpParentWnd is NULL, the dialog box will be created with its parent or owner window set to the main application window.

The Create member function returns immediately after it creates the dialog box.

Use the WS_VISIBLE style in the dialog-box template if the dialog box should appear when the parent window is created.Otherwise, you must callShowWindow.For further dialog-box styles and their application, see theDLGTEMPLATE structure in the Windows SDK and Window Styles in the MFC Reference.

如果对话框不是Visible属性,还要调用ShowWindow()函数来显示非模态对话框窗口。

Use the CWnd::DestroyWindow function to destroy a dialog box created by the Create function.如果对话框是通过Create方式创建的,要显式的调用DestroyWindow()来关闭并销毁非模态对话框。由于CWnd::DestroyWindow()会在最后调用CWnd 的PostNcDestroy(), 因此我在PostNcDestroy()中调用delete this 来删除堆上分配的空间。这样就不会有内存泄露的问题了。

 

对于一个单窗口程序,通过new创建了一个窗口对象pWnd,然后pWnd->Create。则销毁窗口的调用次序:

        1. 手工调用pWnd->DestroyWindow();

  2. DestroyWindow会发送WM_DESTROY;

  3. WM_DESTROY对应的消息处理函数是OnDestroy();

  4. DestroyWindow会发送WM_NCDESTROY;

  5. WM_NCDESTROY对应的消息处理函数是OnNcDestroy;

  6. OnNcDestroy最后会调用PostNcDestroy;

  7. PostNcDestroy经常被用户重载以提供释放内存操作。例如可以使用delete this;

  通过这种方式,窗口对象对应的窗口和窗口对象本身都被释放了。

如果含有子窗口,则调用父窗口的DestroyWindow时,它会向子窗口发送WM_DESTROY和WM_NCDESTROY消息。

一段很好的文章:(作者:闻怡洋)

  一个MFC窗口对象包括两方面的内容:一是窗口对象封装的窗口,即存放在m_hWnd成员中的HWND(窗口句柄),二是窗口对象本身是一个C++对象。要删除一个MFC窗口对象,应该先删除窗口对象封装的窗口,然后删除窗口对象本身。

  删除窗口最直接方法是调用CWnd::DestroyWindow或::DestroyWindow,前者封装了后者的功能。前者不仅会调用后者,而且会使成员m_hWnd保存的HWND无效(NULL)。如果DestroyWindow删除的是一个父窗口或拥有者窗口,则该函数会先自动删除所有的子窗口或被拥有者,然后再删除父窗口或拥有者。在一般情况下,在程序中不必直接调用DestroyWindow来删除窗口,因为MFC会自动调用DestroyWindow来删除窗口。例如,当用户退出应用程序时,会产生WM_CLOSE消息,该消息会导致MFC自动调用CWnd::DestroyWindow来删除主框架窗口,当用户在对话框内按了OK或Cancel按钮时,MFC会自动调用CWnd::DestroyWindow来删除对话框及其控件。

  窗口对象本身的删除则根据对象创建方式的不同,分为两种情况。在MFC编程中,会使用大量的窗口对象,有些窗口对象以变量的形式嵌入在别的对象内或以局部变量的形式创建在堆栈上,有些则用new操作符创建在堆中。对于一个以变量形式创建的窗口对象,程序员不必关心它的删除问题,因为该对象的生命期总是有限的,若该对象是某个对象的成员变量,它会随着父对象的消失而消失,若该对象是一个局部变量,那么它会在函数返回时被清除。

  对于一个在堆中动态创建的窗口对象,其生命期却是任意长的。初学者在学习C++编程时,对new操作符的使用往往不太踏实,因为用new在堆中创建对象,就不能忘记用delete删除对象。读者在学习MFC的例程时,可能会产生这样的疑问,为什么有些程序用new创建了一个窗口对象,却未显式的用delete来删除它呢?问题的答案就是有些MFC窗口对象具有自动清除的功能。

  如前面讲述非模态对话框时所提到的,当调用CWnd::DestroyWindow或::DestroyWindow删除一个窗口时,被删除窗口的PostNcDestroy成员函数会被调用。缺省的PostNcDestroy什么也不干,但有些MFC窗口类会覆盖该函数并在新版本的PostNcDestroy中调用delete this来删除对象,从而具有了自动清除的功能。此类窗口对象通常是用new操作符创建在堆中的,但程序员不必操心用delete操作符去删除它们,因为一旦调用DestroyWindow删除窗口,对应的窗口对象也会紧接着被删除。

  不具有自动清除功能的窗口类如下所示。这些窗口对象通常是以变量的形式创建的,无需自动清除功能。

  所有标准的Windows控件类。

  1. 从CWnd类直接派生出来的子窗口对象(如用户定制的控件)。

  2. 切分窗口类CSplitterWnd。

  3. 缺省的控制条类(包括工具条、状态条和对话条)。

        4. 模态对话框类。

  具有自动清除功能的窗口类如下所示,这些窗口对象通常是在堆中创建的。

  1. 主框架窗口类(直接或间接从CFrameWnd类派生)。

  2. 视图类(直接或间接从CView类派生)。

  读者在设计自己的派生窗口类时,可根据窗口对象的创建方法来决定是否将窗口类设计成可以自动清除的。例如,对于一个非模态对话框来说,其对象是创建在堆中的,因此应该具有自动清除功能。

  综上所述,对于MFC窗口类及其派生类来说,在程序中一般不必显式删除窗口对象。也就是说,既不必调用DestroyWindow来删除窗口对象封装的窗口,也不必显式地用delete操作符来删除窗口对象本身。只要保证非自动清除的窗口对象是以变量的形式创建的,自动清除的窗口对象是在堆中创建的,MFC的运行机制就可以保证窗口对象的彻底删除。

  如果需要手工删除窗口对象,则应该先调用相应的函数(如CWnd::DestroyWindow)删除窗口,然后再删除窗口对象.对于以变量形式创建的窗口对象,窗口对象的删除是框架自动完成的.对于在堆中动态创建了的非自动清除的窗口对象,必须在窗口被删除后,显式地调用delete来删除对象(一般在拥有者或父窗口的析构函数中进行).对于具有自动清除功能的窗口对象,只需调用CWnd::DestroyWindow即可删除窗口和窗口对象。

0 0
原创粉丝点击