早就想写这篇文章了,一直苦于没有时间。这么好的周末我自然不会浪费,于是上来侃2句了,希望对初学者有益。 UpdateData这个函数相信大家已经了解。带有1个参数。如果参数为TRUE,表示将控件中的内容“输入”给它的关联变量。如果是FALSE,表示将关联变量的内容输入到控件中。 一 UpdateData(FALSE) 假设现在已经有一个编辑框了,并且设置了一个关联变量m_stredit。好,现在我想初始化它,让对话框一运行的时候,编辑框中就有字符了。常见的做法如下: BOOL Cmydlg::OnInitDialog() { CDialog::OnInitDialog(); ........ m_stredit="hello,world!"; UpdateData(FALSE); ............. } 结果自然正确。后来还见过这种写法,在构造函数中初始化关联变量: Cmydlg::Cmydlg(CWnd* pParent /*=NULL*/) : CDialog(Cmydlg::IDD, pParent){ //{{AFX_DATA_INIT(CJianyanDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_stredit="hello,world!"; } 其他什么代码也没写。奇怪,也能运行。我并没有调用UpdateData(FALSE)啊?在哪儿调用了?一行行的检查自然让我把注意力集中在了: CDialog::OnInitDialog(); 这个基类的函数到底干了些什么勾当?我要搞明白。方法是这样的: 菜单栏,编辑,在文件中查找,输入这个函数(CDialog::OnInitDialog()),还要注意设置一下查找的路径,结果如下: BOOL CDialog::OnInitDialog(){ // execute dialog RT_DLGINIT resource BOOL bDlgInit; if (m_lpDialogInit != NULL) bDlgInit = ExecuteDlgInit(m_lpDialogInit); else bDlgInit = ExecuteDlgInit(m_lpszTemplateName); if (!bDlgInit) { TRACE0("Warning: ExecuteDlgInit failed during dialog init.\n"); EndDialog(-1); return FALSE; } // transfer data into the dialog from member variables if (!UpdateData(FALSE)) { TRACE0("Warning: UpdateData failed during dialog init.\n"); EndDialog(-1); return FALSE; } // enable/disable help button automatically CWnd* pHelpButton = GetDlgItem(ID_HELP); if (pHelpButton != NULL) pHelpButton->ShowWindow(AfxHelpEnabled() ? SW_SHOW : SW_HIDE); return TRUE; // set focus to first one} 捡最重要的看了。确实调用了UpdateData(FALSE),猜对了! 知道了这些,那么我显然也可以把这样初始化: BOOL Cmydlg::OnInitDialog() { m_stredit="hello,world!"; CDialog::OnInitDialog(); ........ // m_stredit="hello,world!"; //UpdateData(FALSE); ............. } 果然成功! 二 UpdateData(TRUE) 再来假设一个这样的程序。现在有一个SDI和对话框,单击一个菜单项弹出对话框。在编辑框输入字符串,然后“确定”结束,要求在视图中显示。很简单: void CMyView::Onrange() //响应菜单消息{ Cmydlg dlg; if(dlg.DoModal()==IDOK) { m_str=dlg.m_stredit;//m_str是视类中的成员变量 Invalidate(); //调用OnDraw函数显示,略去 }} 此时你可能有这种疑问,要不要UpdateData(TRUE) 啊,在哪里调用啊? 我们知道模太对话框用DoModal来显示,直到窗口结束,也就是调用了CDialog::EndDialog(),得到它的返回值,IDOK或者是IDCANCEL。此时DoModal()返回值如果是IDOK,表示执行了CDialog::OnOK(),也就是单击了“确定”按钮。那你自然会想到: void Cmydlg ::OnOK() { UpdateData(TRUE); CDialog::OnOK(); } 这样当然没有错误。但是很可惜这是错误的,我们来查看一下CDialog::OnOK的源代码: void CDialog::OnOK(){ if (!UpdateData(TRUE)) { TRACE0("UpdateData failed during dialog termination.\n"); // the UpdateData routine will set focus to correct item return; } EndDialog(IDOK);} 啊,原来CDialog::OnOK自身就会调用UpdateData,我们又多此一举了!实际上这就是有些书上所写的:“确定”,它会保存信息,而“取消”则不会,其实奥秘在这里啊! 三 .DoModal(); 如二的例子,现在弹出对话框后,我想初始化,当然可以像实例1一样在OnInitDialog中去做或者是在构造函数中,不过还有另一种方法哦: void CMyView::Onrange() //响应菜单消息{ Cmydlg dlg; dlg.m_stredit="hehe!"; if(dlg.DoModal()==IDOK) { m_str=dlg.m_stredit;//m_str是视类中的成员变量 Invalidate(); //调用OnDraw函数显示,略去 }} 运行一下,确实可以,为什么只有一句dlg.m_stredit="hehe!";就可以了呢?在哪里莫非又调用了UpdateData了? 原因在于调用了domodal以后,程序就去调用对话框的派生类中的OnInitDialog,然后又调用基类的,又回到实例1了,呵呵! 原来一切尽在其中!

评论