程序退出的后,出现一个警告:Warning: calling DestroyWindow in CWnd::~CWnd; OnDestroy or PostNcDestroy in derived class will not be called._CrtDbgReport: String too long or IO Error程序“[2716] DemoDockableForm.exe: 本机”已退出,返回值为 0 (0x0)。
网上一般说,这个缘故是 窗口对象没有销毁,就销毁c++对象导致的,,但是我的内存没有泄露啊!!!首先说说用到的类:CMyDialog------------CDockableForm----------------------CDialog销毁依然是非模式的销毁方式。。这里非常特殊, CMyDilaog放在一个 面板上, CMyDialog去掉了边框 不存在什么 OK ,INCANCEL 按钮的!!你懂的, 当面板销毁的时候,才销毁 对话框。。面板销毁的时刻是在 程序结束的时候销毁。所以如果想 正确销毁对话框,那么可以在 面板的 OnDestroy中顺便销毁 对话框即可!!问题有些复杂, 大家帮忙看看啊
// CMyDialog 对话框, CDockableForm是基类class CMyDialog : public CDockableForm
{
............protected:
virtual void PostNcDestroy(); //我已经override了PostNcDestroy!! 按照常规,还应该在OnClose中调用DesrtoyWindow,当时我已经去掉了 OK,CANCEL, 边框也去掉了
...................
};void CMyDialog::PostNcDestroy()
{
CDockableForm::PostNcDestroy();
delete this; //销毁对话框
}
需要看基类:CDockableForm的,可以看以下,代码如下(不看可以跳过)
//辅助类
class CDockablePaneAsContainer : public CDockablePane
{
public:
CDockablePaneAsContainer(CDialog* pDialog) : m_pDialog(pDialog) { }private:
CDialog* m_pDialog;
public:
DECLARE_MESSAGE_MAP()
afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnDestroy(); //销毁面板,在这个里面销毁对话框};
//基类对话框类,这个是基类,基类
class CDockableForm : public CDialog
{
public:
CDockableForm(UINT nIDTemplate); BOOL Create(LPCTSTR lpszCaption, CWnd* pParentWnd, const RECT& rect, BOOL bHasGripper, UINT nID, DWORD dwStyle, DWORD dwTabbedStyle = AFX_CBRS_REGULAR_TABS, DWORD dwControlBarStyle = AFX_DEFAULT_DOCKING_PANE_STYLE, CCreateContext* pContext = NULL); CDockablePane& GetDockablePane() { return m_wndPane; } virtual ~CDockableForm(){}private:
CDockablePaneAsContainer m_wndPane;};
//这里是关键!!!!!!!!!! 说明,DesroyWindow是虚函数,会调用void CDockablePaneAsContainer::OnDestroy()
{
CDockablePane::OnDestroy(); // TODO: 在此处添加消息处理程序代码
m_pDialog->DestroyWindow(); // 销毁对话框
}
CDockableForm::CDockableForm(UINT nIDTemplate)
: CDialog(nIDTemplate, &m_wndPane)
, m_wndPane(this)
{
}
CDockableForm中的面板对象 ,不是有个指针:CDialog* m_pDialog;吗???? 在构造函数中已经使其执向 CDockableForm了!!!!!!
问题比较复杂,大家帮忙看看 谢谢了啊
网上一般说,这个缘故是 窗口对象没有销毁,就销毁c++对象导致的,,但是我的内存没有泄露啊!!!首先说说用到的类:CMyDialog------------CDockableForm----------------------CDialog销毁依然是非模式的销毁方式。。这里非常特殊, CMyDilaog放在一个 面板上, CMyDialog去掉了边框 不存在什么 OK ,INCANCEL 按钮的!!你懂的, 当面板销毁的时候,才销毁 对话框。。面板销毁的时刻是在 程序结束的时候销毁。所以如果想 正确销毁对话框,那么可以在 面板的 OnDestroy中顺便销毁 对话框即可!!问题有些复杂, 大家帮忙看看啊
// CMyDialog 对话框, CDockableForm是基类class CMyDialog : public CDockableForm
{
............protected:
virtual void PostNcDestroy(); //我已经override了PostNcDestroy!! 按照常规,还应该在OnClose中调用DesrtoyWindow,当时我已经去掉了 OK,CANCEL, 边框也去掉了
...................
};void CMyDialog::PostNcDestroy()
{
CDockableForm::PostNcDestroy();
delete this; //销毁对话框
}
需要看基类:CDockableForm的,可以看以下,代码如下(不看可以跳过)
//辅助类
class CDockablePaneAsContainer : public CDockablePane
{
public:
CDockablePaneAsContainer(CDialog* pDialog) : m_pDialog(pDialog) { }private:
CDialog* m_pDialog;
public:
DECLARE_MESSAGE_MAP()
afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnDestroy(); //销毁面板,在这个里面销毁对话框};
//基类对话框类,这个是基类,基类
class CDockableForm : public CDialog
{
public:
CDockableForm(UINT nIDTemplate); BOOL Create(LPCTSTR lpszCaption, CWnd* pParentWnd, const RECT& rect, BOOL bHasGripper, UINT nID, DWORD dwStyle, DWORD dwTabbedStyle = AFX_CBRS_REGULAR_TABS, DWORD dwControlBarStyle = AFX_DEFAULT_DOCKING_PANE_STYLE, CCreateContext* pContext = NULL); CDockablePane& GetDockablePane() { return m_wndPane; } virtual ~CDockableForm(){}private:
CDockablePaneAsContainer m_wndPane;};
//这里是关键!!!!!!!!!! 说明,DesroyWindow是虚函数,会调用void CDockablePaneAsContainer::OnDestroy()
{
CDockablePane::OnDestroy(); // TODO: 在此处添加消息处理程序代码
m_pDialog->DestroyWindow(); // 销毁对话框
}
CDockableForm::CDockableForm(UINT nIDTemplate)
: CDialog(nIDTemplate, &m_wndPane)
, m_wndPane(this)
{
}
CDockableForm中的面板对象 ,不是有个指针:CDialog* m_pDialog;吗???? 在构造函数中已经使其执向 CDockableForm了!!!!!!
问题比较复杂,大家帮忙看看 谢谢了啊
解决方案 »
- 关于Ado2.5的_stream使用问题,求救?
- 如何将list control中的16进制数据保存为bin文件
- 请教大家一个msn文件传输的问题
- CString::SpanExcluding()的问题,十分不解
- ★怎么检测SOCKET的缓冲区是否有数据到达?
- 线程是否可以操作父进程的窗口控件?
- 请问,怎样取鼠标的坐标?急!谢!
- 关于如何导入DLL中的类的实际问题,高手才能进!
- 标准win3如果我处理了WM_SYSCOMMAND消息,点菜单就什么都弹不出来了,什么原因
- 将ASCII码数赋予CString.
- 客户与服务器端的聊天室, 请问一个关于vc++的网络编程问题?
- 悬赏 30000分 求高手指点
而且别夸线程删除,因为MFC对象作用域仅仅在线程中有效,如果是多线程,想深入理解,跟MFC的删除流程,和GOOGLE TLS
非模创建是new出来,销毁时,delete,没有问题啊。
delete后hwnd就是null了,自动回收safe_deletw()跳过。
CDockableForm中的面板对象 ,不是有个指针:CDialog* m_pDialog;吗???? 在构造函数中已经使其执向 CDockableForm了!!!!!!m_pDialog应该要指向CMyDialog吧?
我不知道,不过我设置过断点当m_pDialog->DestroyWindow后, 会掉入CMyDialog::PostNCDestroy中???
我问个问题:对于 基类, 子类 他们的地址一样否???我认为是一样的,,不过子类多了一部分数据成员,对吧???m_pDialog是一个CDialog型指针DestroyWindow是一个 虚函数。m_pDialog->DestroyWindow 调用的是谁??????哪一个类的????这里让我混乱的原因在于: c++ 中的类,和窗口类。。窗口显然只有一个, 但是有父类, 派生类。从窗口的角度来看,必然 销毁的是: 对话框, 因为只有一个对话框啊???
从 c++来看, m_pDialog是一个基类的基类指针。。但是 对于终极派生类CMyDialog来说,它 并没有override:DestroyWindow。所以肯定是调用了CDialog::DestroyWindow!!!!也就是 ,窗口肯定被销毁了。可是为什么还会有警告呢????
6楼疑问:m_pDialog指针 指着谁 ? CMyDialog?? CDockableForm?? CDialog??还是三个类的地址其实是一样的!!!
你是在CDockablePaneAsContainer中创建的嘛
直接在这里销毁,同时把指针置空就ok了,这个逻辑也清晰按照下面的试试void CDockablePaneAsContainer::OnDestroy()
{
CDockablePane::OnDestroy(); // TODO: 在此处添加消息处理程序代码
if (m_pDialog!=NULL)
{
m_pDialog->DestroyWindow(); // 销毁对话框
delete m_pDialog;
m_pDialog = NULL;
}
}// 这个就不用重载了,去掉
void CMyDialog::PostNcDestroy()
{
CDockableForm::PostNcDestroy();
delete this; //销毁对话框
}
=》你想表达的是子类对象中基类中的内容吧,基类中的Member Data作为一个整体存放在子类的内存空间中,子类的Start Address对应的可能就是基类在子类中的地址,也有可能不一样,具体要看各厂商的Compiler设计,目前C1是这样的,但是对于virtual继承的,c1也不一样。m_pDialog是一个CDialog型指针。(前提你调用的是虚函数)
=》所以你把该指针指向哪个派生类,那么到时候就会调用哪个派生类的对应函数,这就是所谓的多态.
第二个问题:你也看到了 m_pDialog 指针 某个东西的时候,仅仅是在构造函数里面!!!所以这个造成 我很难分析,是否是多态大家都知道,多态一般是这样用的:A *p;p=&b;p->虚函数
现在的情况不一样!!! 具体看 构造函数:CDockableForm::CDockableForm(UINT nIDTemplate)
: CDialog(nIDTemplate, &m_wndPane)
, m_wndPane(this)
{
}
当 终极派生类构造的时候,就会调用 CDockableForm的构造函数,,CDockableForm的构造函数又会调用CDialog构造函数,CDialog 构造函数完毕之后回到CDockableForm的构造函数,最后回到CMyDialog的构造函数然后 去初始化 它所包含的成员对象:m_wndPane!!!
m_wndPane中包含了 CMyDialog的指针m_pDialog!!!!问题对于我来说,有些复杂吃力请赐教,,,,,1.我分析的对不对? 2.m_pDialog
最终只着谁? 问什么指着它??
void CDockablePaneAsContainer::OnDestroy()
{
CDockablePane::OnDestroy(); if(m_pDialog->GetSafeHwnd())
{
// m_pDialog->DestroyWindow(); //delete m_pDialog; //m_pDialog=NULL; ::SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_MYMESSAGE,0,0);
}
//加代码,发送消息给主窗口,让其销毁:CMyDialog,注意,实验证明:m_pDialog只是指着CDockableForm!!!!!
}
让 主窗口去销毁对话框
CDockablePaneAsContainer::OnDestroy()只是销毁面板容器LRESULT CMainFrame::OnMyMessage(WPARAM wParam,LPARAM lParam)
{
// pdlg->DestroyWindow(); delete pdlg; pdlg=NULL; return 1; }
CMyDialog::~CMyDialog()
{ if(GetSafeHwnd())
OnDestroy();
}
代码dubug发现,可以运行到:
if(GetSafeHwnd())
OnDestroy();
tmd 还提示 继承类没有调用OnDestroy
受不了 了
.h#pragma once
#include "afxwin.h"class CDockablePaneAsContainer : public CDockablePane
{
public:
CDockablePaneAsContainer(CDialog* pDialog) : m_pDialog(pDialog) { }private:
CDialog* m_pDialog;public:
DECLARE_MESSAGE_MAP()
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnDestroy();
};class CDockableForm : public CDialog
{
public:
CDockableForm(UINT nIDTemplate); virtual BOOL Create(LPCTSTR lpszCaption, CWnd* pParentWnd, const RECT& rect, BOOL bHasGripper, UINT nID, DWORD dwStyle, DWORD dwTabbedStyle = AFX_CBRS_REGULAR_TABS, DWORD dwControlBarStyle = AFX_DEFAULT_DOCKING_PANE_STYLE, CCreateContext* pContext = NULL); CDockablePane& GetDockablePane() { return m_wndPane; }private:
CDockablePaneAsContainer m_wndPane;
};.cpp#include "StdAfx.h"
#include "DockableForm.h"
BEGIN_MESSAGE_MAP(CDockablePaneAsContainer, CDockablePane)
ON_WM_SIZE()
ON_WM_DESTROY()
END_MESSAGE_MAP()void CDockablePaneAsContainer::OnSize(UINT nType, int cx, int cy)
{
CDockablePane::OnSize(nType, cx, cy); // TODO: 在此处添加消息处理程序代码
if (m_pDialog->GetSafeHwnd())
{
CRect rc;
GetClientRect(rc);
m_pDialog->MoveWindow(rc);
}
}void CDockablePaneAsContainer::OnDestroy()
{
CDockablePane::OnDestroy(); // TODO: 在此处添加消息处理程序代码
m_pDialog->DestroyWindow();
}CDockableForm::CDockableForm(UINT nIDTemplate)
: CDialog(nIDTemplate, &m_wndPane)
, m_wndPane(this)
{
}BOOL CDockableForm::Create(LPCTSTR lpszCaption, CWnd *pParentWnd, const RECT &rect, BOOL bHasGripper, UINT nID, DWORD dwStyle, DWORD dwTabbedStyle, DWORD dwControlBarStyle, CCreateContext *pContext)
{
m_wndPane.Create(lpszCaption, pParentWnd, rect, bHasGripper, nID, dwStyle, dwTabbedStyle, dwControlBarStyle, pContext);
CDialog::Create(m_nIDHelp, &m_wndPane);
SetParent(&m_wndPane);
ShowWindow(SW_SHOW);
return TRUE;
}
直接在PostNCDestroy中delete this,这个我比较少这样用,不知道对话框这样delete会不会还会调用他的destroywindow来销毁这个对话框。一般都是哪里new出来,哪里delete,哪里create哪里destroywindow,这样可以减少一些错误
至于你说不知道面板对象不知会不会进入销毁,这个从逻辑上说一定要有才行的,没有的话肯定也是哪里出问题了,不行的话就在其他地方显式的调用咯。我看你的对话框指针是别的地方传过来的。你就在传进来的那个地方销毁就可以了
原来我就经常碰到重复销毁出错的情况,这样规范一下后就比较少了你可以各种方法都调试一下,找准原因,找到一个适合你自己的
希望有人对继承这一块把握深刻的人, 帮忙解答一下,,,这个指针,真不好分析。。 比书上那些复杂多了多态一般是这样用的:A *p;p=&b;p->虚函数
现在的情况不一样!!! 具体看 构造函数:CDockableForm::CDockableForm(UINT nIDTemplate)
: CDialog(nIDTemplate, &m_wndPane)
, m_wndPane(this)
{
}
当 终极派生类构造的时候,就会调用 CDockableForm的构造函数,,CDockableForm的构造函数又会调用CDialog构造函数,CDialog 构造函数完毕之后回到CDockableForm的构造函数,最后回到CMyDialog的构造函数然后 去初始化 它所包含的成员对象:m_wndPane!!!
m_wndPane中包含了 CMyDialog的指针m_pDialog!!!!问题对于我来说,有些复杂吃力请赐教,,,,,1.我分析的对不对? 2.m_pDialog
最终只着谁? 问什么指着它??
会了验证 一些网友的意见,或者自己无形中产生的一些概念吧我尝试过,在父类中 PostNcDestroy是正确的。三个类,继承路线即:CBDialog----CADialog--------CMyDialog--------CDialog现在 大家说说, 创建非模式对话框,用的是:CBDialog类,但是却在其直接基类CADialog中进行了PostNCDestroy,DestroyWindow。。销毁非模式对话框, 我是没有发现有什么问题,但是有几个c++中的继承概念不清
看代码://MyDialog.h
class CMyDialog : public CDialog
{
// Construction
public:
CMyDialog(UINT,CWnd* pParent = NULL);
UINT id; //对话框id
.......................
};构造函数:
CMyDialog::CMyDialog(UINT ID,CWnd* pParent /*=NULL*/)
: CDialog(ID, pParent),id(ID)
{}
看代码://ADialog.h#include"MyDialog.h"class CADialog : public CMyDialog
{
// Construction
public:
CADialog(UINT ID,CWnd* pParent = NULL); // standard constructor protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual void PostNcDestroy();
protected: afx_msg void OnClose();
DECLARE_MESSAGE_MAP()
};看 CBDialog的基类的 重要代码:
void CADialog::OnClose()
{
// TODO: Add your message handler code here and/or call default
//CDialog::OnClose();
DestroyWindow();
}void CADialog::PostNcDestroy()
{
CDialog::PostNcDestroy();delete this;}
//BDialog.h
#include "ADialog.h"class CBDialog : public CADialog
{
public:
CBDialog(CWnd* pParent = NULL); // standard constructor
enum { IDD =IDD_DIALOG1};
...........
};
CBDialog这个类对应这个一个对话框,当对话框销毁的时候, 代码运行到CBDialog::PostNcDestroy中它由于继承的是CADialog, 所以代码和CADialog::PostNcDestroy() 一模一样,,大家说说看,这个this是谁??????是CADialog??? CBDialog??? 是CBDialog才对。。基类CADialog的一切public, protected,都给了派生类CBDialog。。试验证明,我的分析是对的, vc6,vs2010 都通过,没有任何异常问题出现可是为什么主帖中却出现了 那个诡异的警告呢??很可能是 面板容器 有些诡异。。在基类中调用DestroyWindow是完全可以的DestroyWindow是一个虚函数。主帖中:CMyDialog构造函数被调用的时候,它立即构造一个CDockableForm对象,,CDockableForm的构造函数,将 this传给了 它的成员对象。(初始化这个成员对象)这里的这个this 指针, 是CMyDialog的 基类的 地址。CMyDialog的地址和基类CDockableForm的 地址完全一致,至少这里是一样的
{
CDockableForm::PostNcDestroy(); //去掉这句试试
delete this; //销毁对话框
}
{
CDockableForm::PostNcDestroy();//去掉这句试试
delete this; //销毁对话框
}
那么没有 一下警告如果我把delete 对话框 移植到其他地方,立即有警告,但是内存没有泄露。比如在CMyDialog::PostNcDestroy中 //CDockableForm::PostNcDestroy();
::SendMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_MYMESSAGE,0,0);
发送一个自定义消息给 主框架让主框框中 delete 对话框但是依然会有提示只有把delete 对话框放在 析构函数中,就没有这个警告了calling DestroyWindow in CWnd::~CWnd; OnDestroy or PostNcDestroy in derived class will not be called.
我的猜测: 这个警告不用理会。 由编译器扯淡去吧
谢谢各位, 时间到,我就结贴