关于无模式对话框

Kernel_Don 2003-08-24 06:20:34
在《Visual C++ 技术内幕》第四版中介绍无模式对话框时,提到:
--------------------------------------------------------------------
对于无模式对话框,一定要注意不要调用CDialog::OnOK或CDialog::OnCancel
函数,也就是说必须在派生类中重载这些函数;否则,当使用Esc、回车或用
鼠标单击某按钮时,就会激发对相应基类函数的调用,进而导致调用Windows
的EndDialog函数,而EndDialog函数只适合模式对话框。对于无模式对话框,
必须调用DestroyWindow函数。
--------------------------------------------------------------------

我对这做了试验,用new...Create...ShowWindow...建立了一个无模式的对话
框,然后用CDialog::OnOK()关闭该对话框,好像一切都正常,没什么不对呀...

为什么这本经典的书上说:一定要注意不要调用CDialog::OnOK或CDialog::OnCancel
函数?
...全文
96 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
Kernel_Don 2003-08-29
  • 打赏
  • 举报
回复
回复人: flinming(flinming) ( ) 信誉:100 2003-08-27 20:25:00 得分:0


我到是没有遇到过,我都没有销毁也不会错误
CXDialog *xDlg = new CXDialog;
xDlg->Create(IDD_DIALOG1);
xDlg->ShowWindow(SW_SHOW);

/////////////////////////
这样虽然无出错提示,但每次按下按钮都new一次,会有内存泄漏...
Kernel_Don 2003-08-27
  • 打赏
  • 举报
回复
class CADlg : public CDialog
{
public:
CXDialog * xDlg;
// ...
};


CADlg::~CADlg()
{
// ...
if (xDlg->GetParent() != NULL)
xDlg->DestroyWindow();
if (xDlg != NULL)
delete xDlg;
// ...
}

BOOL CADlg::OnInitDialog()
{
//...
xDlg = new CXDialog;
//...
}

//在对话框CADlg中有两个按钮Button1和Button2
按下Button1按钮后弹出一个无模式对话框:
void CADlg::OnButton1()
{
xDlg->Create(IDD_DIALOG1, this);
xDlg->ShowWindow(SW_SHOW);
}
按下Button2按钮后消毁该无模式对话框:
void CADlg::OnButton()
{
xDlg->DestroyWindow();
}
/////////////////////////////////////////

为什么按下BUTTON1产生对话框,再按BUTTON2消毁该对话框后,第二次按下BUTTON1时会出错?
flinming 2003-08-27
  • 打赏
  • 举报
回复
上面写错了是这样
CXDialog *xDlg = new CXDialog;
xDlg->Create(IDD_DIALOG1);
xDlg->ShowWindow(SW_SHOW);
flinming 2003-08-27
  • 打赏
  • 举报
回复
我到是没有遇到过,我都没有销毁也不会错误
xDlg = new * CXDialog;
xDlg->Create(IDD_DIALOG1);
xDlg->ShowWindow(SW_SHOW);
  • 打赏
  • 举报
回复
不明白之处
请给我发短消息
不要忘记了加帖子的地址
  • 打赏
  • 举报
回复
上面的方法不安全
构造函数中
xDlg = NULL;
BOOL CADlg::OnInitDialog()
{
}不作处理

void CADlg::OnButton1()
{
if(NULL != xDlg)
return ;
xDlg = new CXDialog;
xDlg->Create(IDD_DIALOG1, this);
xDlg->ShowWindow(SW_SHOW);
}

void CADlg::OnButton()
{
if(NULL == xDlg)
return;
xDlg->DestroyWindow();
delete xDlg;
xDlg = NULL;

}



  • 打赏
  • 举报
回复
void CADlg::OnButton1()
{
xDlg = new CXDialog;
xDlg->Create(IDD_DIALOG1, this);
xDlg->ShowWindow(SW_SHOW);
}

void CADlg::OnButton()
{
xDlg->DestroyWindow();
delete xDlg;

}
yanzai8848 2003-08-24
  • 打赏
  • 举报
回复
首先必须明白所有的Win窗口使用API函数CreateWindow(或*Ex)创建, 使用DestroyWindow撤消(删除全部, 释放分配的内存)
然后看以下源代码:
1,以下说明了为什么使用delete是正确的
CDialog::~CDialog()
{
if (m_hWnd != NULL)
{
TRACE0("Warning: calling DestroyWindow in CDialog::~CDialog --\n");
TRACE0("\tOnDestroy or PostNcDestroy in derived class will not be called.\n");
DestroyWindow();
}
}

2,以下说明了为什么使用EndDialog不正确:

void CDialog::EndDialog(int nResult)
{
ASSERT(::IsWindow(m_hWnd));

if (m_nFlags & (WF_MODALLOOP|WF_CONTINUEMODAL))
EndModalLoop(nResult);

::EndDialog(m_hWnd, nResult);
}

//::EndDialog的MSDN说:
//EndDialog does not close the dialog box immediately. Instead, it sets a flag that directs the dialog box to close as soon as the current message handler returns.
bcpl 2003-08-24
  • 打赏
  • 举报
回复
这样倒是不会出错,因为你动态分配/销毁对话框对象,
但不表示这样做就是对的,ms要你别用EndDialog关闭非模态对话模式,
你就乖乖听话吧
Kernel_Don 2003-08-24
  • 打赏
  • 举报
回复
我在CADlg中:
class CADlg : public CDialog
{
public:
CXDialog * xDlg;
// ...
};

CADlg::~CADlg()
{
// ...
if (xDlg != NULL)
delete xDlg;
// ...
}

BOOL CTest030821Dlg::OnInitDialog()
{
//...
xDlg = NULL;
//...
}

//在对话框CADlg中有一按钮Button1,按下该按钮后弹出一个无模式对话框:
void CADlg::OnButton1()
{
// TODO: Add your control notification handler code here
if (xDlg != NULL)
delete xDlg;
xDlg = new CXDialog;
xDlg->Create(IDD_DIALOG1, this);
xDlg->ShowWindow(SW_SHOW);
}
/////////////////////////////////////////
//在CXDialog对话框中也有一按钮Button1,该按钮的执行代码如下:
void CXDialog::OnButton1()
{
// TODO: Add your control notification handler code here
CDialog::OnOK();
}

//按下CXDialog::Button1后该无模式对话框关闭,按下CADlg::Button1后该无模式对
话框又打开,反复操作无出错。
bcpl 2003-08-24
  • 打赏
  • 举报
回复
EndDialog并不立即销毁对话框,只有在模态对话框机制下才在后续执行中销毁,
如果在非模态对话框中调用,窗口并没有被真正销毁,如果用同一个MFC的CDialog对象再次
Create,将引发一系列的ASSERT。
  • 打赏
  • 举报
回复
void CTestDialog::OnOK()
{
CDialog::OnOK();
}
在无模式对话框中也是不行的
  • 打赏
  • 举报
回复
hehe,你关闭后再启动一次看看!会出现内存错误的!
============================================
同感
丁淇石头 2003-08-24
  • 打赏
  • 举报
回复
你做的实验一切都正常,那可能是你的实验不全面,呵呵。还是不要随便怀疑MSDN的好。
akiko 2003-08-24
  • 打赏
  • 举报
回复
MSDN上的解释,最后一句说明问题了:
If you implement the OK(Cancel) button in a modeless dialog box, you must override the OnOK(OnCancel) member function and call DestroyWindow from within it. Don’t call the base-class member function, because it calls EndDialog, which makes the dialog box invisible but does not destroy it.
西江残月 2003-08-24
  • 打赏
  • 举报
回复
hehe,你关闭后再启动一次看看!会出现内存错误的!

16,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧