用MFC制作一个倒计时小程序
1.思路:
1)初始步骤1:新建一个工程,选择MFC AppWizard(exe),工程名命名为CdTimer,选择基于对话框形式的应用程序,将此主对话框用于显示剩余的时间,对话框ID命名为IDD_CDTIMER_DIALOG;并在此对话框上添加三个edit控件和两个static控件,分别用于显示时钟数、分钟数、秒数以及两个间隔符“:”,在三个对话框上各关联一个Cstring型的对象;
2)初始步骤2:添加一个对话框资源,使用默认的ID号IDD_DIALOG1,打开ClassWizard,按提示添加一个新类CSetCountDownDlg,将用于设置倒计时数,同样的在此对话框上添加一个edit控件,用于显示设置的时间,如50分钟倒计时就设置为00:50:00,并在此控件上也关联一个CString型的对象;
3)想达到的功能:双击运行应用程序后,右键弹出对话框IDD_DIALOG1设置倒计时,按回车键设置完毕;左键单击主对话框,倒计时开始;左键双击主对话框,到计时暂停;右键单击主对话框,重新设置;按回车键退出。
2.具体实现:
用的的函数主要有:
a.CString 的成员函数Format、Left、Mid、Right、Find;
b.计数器相关SetTimer、KillTimer;
c.字符串转化atoi;
d.对话框或控件等窗口相关的函数DoModal、SetDlgItemText、UpdateData;
e.消息响应函数OnCreate、OnRButtonDown、OnLButtonDown、OnLButtonDblClk、OnTimer、OnOK。
主要的实现过程:
- 右键单击弹出设置倒计时对话框IDD_DIALOG1,按规定输入数据后回车,程序进入CSetCountDownDlg的重载的OnOk函数,读取输入于对话框IDD_DIALOG1的编辑框(编辑框关联的变量为m_strSetCountDownTime)相应位置的数据,并赋值给CSetCountDownDlg的int型成员变量m_settedHour、m_settedSecond、m_settedMinute,主要代码及程序运行截图如下所示:
void CSetCountDownDlg::OnOK()
{
UpdateData(TRUE);
// 获取设置的小时数
m_settedHour = atoi(m_strSetCountDownTime.Left(m_strSetCountDownTime.Find(":")));
// 获取设置的分钟数
m_settedMinute = atoi(m_strSetCountDownTime.Mid(m_strSetCountDownTime.Find(":")+1,
m_strSetCountDownTime.ReverseFind(':') - m_strSetCountDownTime.Find(':')));
// 获取设置的秒数
m_settedSecond = atoi(m_strSetCountDownTime.Right(m_strSetCountDownTime.Find(":")));
UpdateData(FALSE);
CDialog::OnOK();
}
- 回车后对话框IDD_DIALOG1被销毁,程序继续执行下面代码m_setCountDownDlg.DoModal();之后的部分,使得主对话框IDD_CDTIMER_DIALOG获取到已经设置的倒计时,并按规定的格式显示。例如若设置为1:45:00则显示为01:45:00. OnRButtonDown函数代码如下:
void CCdTimerDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_setCountDownDlg.DoModal();
m_strHours.Format("%d", m_setCountDownDlg.m_settedHour);
m_strMinutes.Format("%d", m_setCountDownDlg.m_settedMinute);
m_strSeconds.Format("%d", m_setCountDownDlg.m_settedSecond);
// 控制显示格式,当数值 < 10,以0作为前缀
if (atoi(m_strSeconds) < 10)
{
m_strSeconds.Format("0%d", atoi(m_strSeconds));
}
if (atoi(m_strMinutes) < 10)
{
m_strMinutes.Format("0%d", atoi(m_strMinutes));
}
if (atoi(m_strHours) < 10)
{
m_strHours.Format("0%d", atoi(m_strHours));
}
// 显示设置的时间
SetDlgItemText(IDC_HOURS, m_strHours);
SetDlgItemText(IDC_MINUTES, m_strMinutes);
SetDlgItemText(IDC_SECONDS, m_strSeconds);
m_bIsBegin = FALSE; // 重新设置时间
CDialog::OnRButtonDown(nFlags, point);
}
- 单击鼠标左键,响应ON_WM_LBUTTONDOWN消息,程序进入OnLButtonDown函数,代码如下:
void CCdTimerDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_bIsBegin = TRUE;
SetTimer(1, 1000, NULL);
CDialog::OnLButtonDown(nFlags, point);
}
- 之后进入OnTimer函数,开始计时:
void CCdTimerDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
UpdateData(TRUE);
BOOL bIsDecreased = FALSE; // 防止碰到类似01:00:00的情况使得分钟被减为58而不是59
// 倒计时程序的实现部分
if (m_bIsBegin == TRUE)
{
if (atoi(m_strSeconds) == 0)
{
if (atoi(m_strMinutes) == 0)
{
if (atoi(m_strHours) == 0)
{
return;
}
m_strHours.Format("%d", atoi(m_strHours) - 1);
m_strMinutes.Format("%d", 59);
m_strSeconds.Format("%d", 59);
bIsDecreased = TRUE; // 分钟已经减少为59
}
if (bIsDecreased == FALSE)
{
m_strMinutes.Format("%d", atoi(m_strMinutes) - 1);
m_strSeconds.Format("%d", 59);
}
}
else
{
m_strSeconds.Format("%d", atoi(m_strSeconds) - 1);
}
// 控制显示格式,当数值 < 10,以0作为前缀
if (atoi(m_strSeconds) < 10)
{
m_strSeconds.Format("0%d", atoi(m_strSeconds));
}
if (atoi(m_strMinutes) < 10)
{
m_strMinutes.Format("0%d", atoi(m_strMinutes));
}
if (atoi(m_strHours) < 10)
{
m_strHours.Format("0%d", atoi(m_strHours));
}
}
UpdateData(FALSE);
CDialog::OnTimer(nIDEvent);
}
程序运行如下所示:
- 若需要暂停,双击鼠标左键,响应ON_WM_LBUTTONDBLCLK消息,程序进入OnLButtonDblClk,暂停计时:
void CCdTimerDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
KillTimer(1); // 计时暂停
CDialog::OnLButtonDblClk(nFlags, point);
}
- 单击左键,继续计时,回车退出。
这个功能还很简单,后续将继续改进,关于这个程序及相关细节,希望得到大家的评论与指点!