非模态对话框内存释放问题

转自:http://blog.csdn.net/bao_qibiao/article/details/4504647

分类: VC   4220人阅读  评论(0)  收藏  举报

对于一个非模态子对话框的内存释放,一般的处理方法是在OnClose() 函数中添加DestroyWindow() ,然后在PostNcDestroy() 中delete this 。

 

当我们为了使得生成的非模态子对话框最小化的时候在任务栏上显示出来,创建的时候就要以桌面为父窗口,如下:

pdlg->Create( IDD_DIALOG_CHILD, GetDesktopWindow() );

 

这种情况下,如果你先关闭非模态子对话框,再关闭主对话框是没有问题的。但当你关闭主对话框的时候,如果这时还有前面说的非模态子对话框存在,那么就会造成内存泄露。原因是此时pdlg并没有接收到任何关闭的消息。

我们的解决方法是在父窗口中保存一个非模态子对话框的指针pdlgCopy,这个指针在pdlg存在的情况下要赋值,在pdlg销毁的情况下要清零。然后在主对话框关闭的时候检查这个指针,如果不为空,则释放。

 

现在又有新的问题,如果你在pdlg里面的操作分配了内存,但是你是在pdlg的PostNcDestroy() 中释放的话,那么还是会有内存泄露,因为在父窗口中删除那个非模态对话框指针的时候,只会进pDlg的析构函数,而不进PostNcDestroy()。 所以要么你在析构函数中释放内存,要么你在父窗口中调用pdlgCopy->DestroyWindow()。前者要注意此时this指针和对象句柄都已为NULL,而且你的子控件中的内存释放是否依赖于WM_DESTROY,后者方法要注意你本来DestroyWindow()中就有把pdlgCopy置为NULL的操作,如果对话框指针多了要用模板保存,还要注意迭代器失效的问题。

 

 

为什么pdlg接收不到任何关闭的消息?

关于窗口的parent和owner的区别:

  下面是MSDN中的解释:   
  http://support.microsoft.com/default.aspx?scid=kb;en-us;84190   
    
  SUMMARY   
  In   the   Windows   environment,   the   following   two   relationships   can   exist   between   windows:     
    
  Owner-owned   relationship.   The   owner-owned   relationship   determines   which   other   windows   are   automatically   destroyed   when   a   window   is   destroyed.   When   window   A   is   destroyed,   Windows   automatically   destroys   all   the   windows   that   are   owned   by   A.       
    
  Parent-child   relationship.   The   parent-child   relationship   determines   where   a   window   can   be   drawn   on   the   screen.   A   child   window   (that   is,   a   window   that   has   a   parent)   is   confined   to   its   parent   window's   client   area.     
    
  This   article   discusses   these   relationships   and   some   Windows   functions   that   provide   owner   and   parent   information   for   a   specified   window.

 

下面这个例子证明“The   owner-owned   relationship   determines   which   other   windows   are   automatically   destroyed   when   a   window   is   destroyed. ”仿佛是错误的。

 

[cpp]  view plain copy
  1. // 能收到关闭消息  
  2. void CStaticMultiDlg::OnButtonCreate()   
  3. {  
  4.     // TODO: Add your control notification handler code here  
  5.     CDialogChild *pDlg = new CDialogChild;  
  6.     pDlg->Create( IDD_DIALOG_CHILD, NULL);  
  7.     pDlg->ShowWindow( SW_SHOW);  
  8.     CWnd *pParent = pDlg->GetParent();       //  pParent 0x00000000 {CWnd hWnd=???}  
  9.     CWnd *pOwner = pDlg->GetOwner();     //  pOwner  0x00000000 {CWnd hWnd=???}  
  10. }  
  11. // 能收到关闭消息  
  12. void CStaticMultiDlg::OnButtonCreate()   
  13. {  
  14.     // TODO: Add your control notification handler code here  
  15.     CDialogChild *pDlg = new CDialogChild;  
  16.     pDlg->Create( IDD_DIALOG_CHILD, this);  
  17.     pDlg->ShowWindow( SW_SHOW);  
  18.     CWnd *pParent = pDlg->GetParent();       //  pParent 0x00000000 {CWnd hWnd=???}  
  19.     CWnd *pOwner = pDlg->GetOwner();     //  pOwner  0x00000000 {CWnd hWnd=???}  
  20. }  
  21.   
  22. // 收不到关闭消息  
  23. void CStaticMultiDlg::OnButtonCreate()   
  24. {  
  25.     // TODO: Add your control notification handler code here  
  26.     CDialogChild *pDlg = new CDialogChild;  
  27.     pDlg->Create( IDD_DIALOG_CHILD, GetDesktopWindow());  
  28.     pDlg->SetParent(GetDesktopWindow());  
  29.     pDlg->ShowWindow( SW_SHOW);  
  30.     CWnd *pDes = GetDesktopWindow();        //  pDes    0x00373458 {CTempWnd hWnd=0x00010010}  
  31.     CWnd *pParent = pDlg->GetParent();       //  pParent 0x00000000 {CWnd hWnd=???}  
  32.     CWnd *pOwner = pDlg->GetOwner();     //  pOwner  0x00000000 {CWnd hWnd=???}  
  33. }  
  34. // 收不到关闭消息  
  35. void CStaticMultiDlg::OnButtonCreate()   
  36. {  
  37.     // TODO: Add your control notification handler code here  
  38.     CDialogChild *pDlg = new CDialogChild;  
  39.     pDlg->Create( IDD_DIALOG_CHILD, GetDesktopWindow());  
  40.     pDlg->SetOwner(this);  
  41.     pDlg->ShowWindow( SW_SHOW);  
  42.     CWnd *pDes = GetDesktopWindow();        //  pDes    0x00373458 {CTempWnd hWnd=0x00010010}  
  43.     CWnd *pParent = pDlg->GetParent();       //  pParent 0x00000000 {CWnd hWnd=???}  
  44.     CWnd *pOwner = pDlg->GetOwner();     //  pOwner  0x0012fdf4 {CStaticMultiDlg hWnd=0x001004f2} == this  
  45. }  
  46. // 这种情况下程序会假死  
  47. void CStaticMultiDlg::OnButtonCreate()   
  48. {  
  49.     // TODO: Add your control notification handler code here  
  50.     CDialogChild *pDlg = new CDialogChild;  
  51.     pDlg->Create( IDD_DIALOG_CHILD, GetDesktopWindow());  
  52.     pDlg->SetParent(this);  
  53.     pDlg->SetOwner(this);  
  54.     pDlg->ShowWindow( SW_SHOW);  
  55.     CWnd *pDes = GetDesktopWindow();        //  pDes    0x00373458 {CTempWnd hWnd=0x00010010}  
  56.     CWnd *pParent = pDlg->GetParent();       //  pParent 0x00000000 {CWnd hWnd=???}  
  57.     CWnd *pOwner = pDlg->GetOwner();     //  pOwner  0x0012fdf4 {CStaticMultiDlg hWnd=0x001004f2} == this  
  58. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值