在Windows编程中,我们经常要对控件进行状态切换。例如,根据复选框的状态进行其余控件状态的变换:
CButton m_chkDate; // 与一个Check Box复选框控件关联
CDateTimeCtrl m_dateFrom; // 与一个日期控件关联
CDateTimeCtrl m_dateTo; // 与一个日期控件关联
CDateTimeCtrl m_dateFrom; // 与一个日期控件关联
CDateTimeCtrl m_dateTo; // 与一个日期控件关联
现在要达到的效果是:在用户选中复选框时,将两个日期控件激活;而当取消选中复选框时,两个日期控件不可用。普通的程序员会使用if…else来实现:
// 日期复选框事件相应函数
void CRentDlg::OnCheckDate()
{
//根据复选框的选中状态,分两种情况进行设置
if (m_chkDate.GetCheck())
{
m_dateFrom.EnableWindow(true);
m_dateTo.EnableWindow(true);
}
else
{
m_dateFrom.EnableWindow(false);
m_dateTo.EnableWindow(false);
}
}
void CRentDlg::OnCheckDate()
{
//根据复选框的选中状态,分两种情况进行设置
if (m_chkDate.GetCheck())
{
m_dateFrom.EnableWindow(true);
m_dateTo.EnableWindow(true);
}
else
{
m_dateFrom.EnableWindow(false);
m_dateTo.EnableWindow(false);
}
}
这种实现方式可以很好地运行,但是这是一种非常糟糕的代码。
通常,一个控件只有两种状态(非0即1),所以我们完全可以设立一个状态标志,利用该状态标志去改变不同控件的状态,代码如下所示:
// 日期复选框事件相应函数
void CRentDlg::OnCheckDate()
{
bool bState = ((m_chkDate.GetCheck() == BST_CHECKED) ? true : false); // 获取复选框状态
m_dateFrom.EnableWindow(bState); // 与状态标志一致
m_dateTo.EnableWindow(bState);
}
void CRentDlg::OnCheckDate()
{
bool bState = ((m_chkDate.GetCheck() == BST_CHECKED) ? true : false); // 获取复选框状态
m_dateFrom.EnableWindow(bState); // 与状态标志一致
m_dateTo.EnableWindow(bState);
}
在上面的代码中,如果要使m_dataTo控件的状态与m_dateFrom的状态相反,可以这样写:
m_dateTo.EnableWindow(!bState); // 对状态标志取反
查看了一下MSDN,发现CButton的GetCheck()方法会返回三种状态,分别是:
#define BST_UNCHECKED 0x0000
#define BST_CHECKED 0x0001
#define BST_INDETERMINATE 0x0002
所以在获取复选框状态时以下代码虽然在大多数情况下没有问题,但是其逻辑是不严密的:
bool bState = m_chkDate.GetCheck();