当我们用VC创建一个对话框后,在对话框中加入一些控件,且这些控件都有关联的控件变量,同时我们想在对话框中的OnInitDialog()中做一些控件的初始显示工作。
这里以时间控件为例,在对话框中增加一个Date time picker控件,其关联的控件变量是CDateTimeCtrl m_dtDateTime。
然后我们想在OnInitDialog()中设置我们自定义的时间,比如“2014/11/17 11:11:11”,这时候我们的代码可能如下:
BOOL CDlgDragConfirm::OnInitDialog()
{
CString sBeginTime = _T("2014/11/17 11:11:11");
int nYear,nMonth,nDay,nHour,nMin,nSec;
char* pszBeginTime=NULL;
pszBeginTime = sBeginTime.GetBuffer(sBeginTime.GetLength());
sBeginTime.ReleaseBuffer();
sscanf(pszBeginTime, "%d/%d/%d %d:%d:%d ",&nYear,&nMonth,&nDay,&nHour,&nMin,&nSec);
COleDateTime dtTime;
dtTime.SetDateTime(nYear,nMonth,nDay,nHour,nMin,nSec);
m_dtDateTime.SetFormat(_T("yyyy-MM-dd HH:mm:ss"));
return CDialog::OnInitDialog();
}
这样实现看起来一点问题都没有,但当你运行程序时,会报错。然后我们把代码换成如下:
BOOL CDlgDragConfirm::OnInitDialog()
{
CString sBeginTime = _T("2014/11/17 11:11:11");
int nYear,nMonth,nDay,nHour,nMin,nSec;
char* pszBeginTime=NULL;
pszBeginTime = sBeginTime.GetBuffer(sBeginTime.GetLength());
sBeginTime.ReleaseBuffer();
CDateTimeCtrl* pdt = (CDateTimeCtrl*)GetDlgItem(IDC_DATETIMEPICKER_BEGINTIME);
sscanf(pszBeginTime, "%d/%d/%d %d:%d:%d ",&nYear,&nMonth,&nDay,&nHour,&nMin,&nSec);
COleDateTime dtTime;
dtTime.SetDateTime(nYear,nMonth,nDay,nHour,nMin,nSec);
pdt->SetFormat(_T("yyyy-MM-dd HH:mm:ss"));
return CDialog::OnInitDialog();
}
我们仅仅是把控件变量换成了控件指针,程序就没有问题了。
究其原因,是我们在使用控件变量的时候没有注意到,控件变量与控件的关联存在一个特定的时机。
我们想让控件变量生效,需要在对话框的父类进行初始化后,才能使用,也就是在
CDialog::OnInitDialog();执行之后才能直接使用控件变量,要不能只能使用控件指针(这一点上我犯了很多次,但是终究不知道为什么,现在知道了)。
容易出现误用可能是因为,对话框父类的初始化放在了继承类初始化函数的最后,
return CDialog::OnInitDialog();所以我们无意中就直接使用了控件变量。
但是在CFormView的子类中一般不会,因为CFormView的继承类的初始化函数的第一条语句就是调用父类的初始化函数。如下:
void CFormDragPlan::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
InitView();//这里会使用到控件变量
}
所以我们一般在CFormView的子类中不会遇到上述报错的问题,但是在对话框子类中,经常遇到。