早就想写这篇文章了,一直苦于没有时间。这么好的周末我自然不会浪费,于是上来侃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了,呵呵!
原来一切尽在其中!
评论