[小插曲]VC学习——基于MFC的模拟时钟程序
2016-12-14 11:02
405 查看
一、程序窗口设计步骤
(1)用
(2)编辑项目的菜单资源,在主框架窗口的主菜单
(3)利用
(4)利用
(5)使用Developer Studio菜单的Insert / Resource…选项调出Insert Source对话框,为项目添加新的对话框资源。在对话框属性中,修改对话框名为“时间设定”。在对话框中增加用来输入年、月、日、时、分、秒的编辑框控件。
通过控件属性,将年、月、日、时、分、秒等编辑控件的ID改为
(6)利用ClassWizard自动建立对话框类。进入ClassWizard后,弹出一个对话框询问是否要为该对话框模板建立类。按下“OK”按钮,会弹出New Class对话框,在Name栏填写对话框类的名称
(7) 利用ClassWizard为对话框类添加与各控件对应的数据成员。选择MemberVariables选项卡,确保Class Name项为对话框CSetTimeDlg类,然后在选项卡下方的窗口中选择各控件的ID并按下“Add Variable…”按钮,为其添加对应成员变量。
控制ID 变量类型 变量名 变量范围
IDC_YEAR int m_Year 0~3000
IDC_MONTH int m_Month 1~12
IDC_DAY int m_Day 1~31
IDC_HOUR int m_Hour 0~23
IDC_MINUTE int m_Minute 0~59
IDC_SECOND int m_Second 0~59
最后一列为变量取值范围。
(8)编辑工程的图标资源,在Resource View选项窗口中修改Icon结点所包含的主框架图标(IDR_MAINFRAME)。此步非必须。
(9)完成以上工作后,即可修改程序框架,添加必要的代码。
二、主要源代码:
按以下步骤向视图类(CClockView)添加下列数据成员及成员函数。
(1) 添加表示年、月、日、时、分、秒的变量。
(2) 添加秒表的计数变量。
(3) 添加时钟的画笔及画刷变量。
(4) 添加时钟控制变量。
(5) 添加秒表的两个按钮位置变量。
(6) 添加两个函数,计算时钟各指针位置。
(7) 在视图类构造函数中增加初始化语句,之前加上头文件
请注意将表示时间的整数转换为CString字符串类型的方法以及秒表的显示方法。另外,watch计数器以1/100秒为计数单位,每达到100则秒数加1。
按照下列步骤增加时钟控制代码:
修改Onstart和OnStop函数,设置时钟运动消息。按比正常时钟快20倍的假定,50ms产生一个消息。本程序采用和正常时间同步,即1000ms产生一个消息, 其代码为:
添加时间设置对话框代码。
首先在ClockView. cpp文件头部添加下列语句:
在时间设定对话框类的构造函数中,做如下修改,将初始日期设为当前时间,之前要加上头文件
编译,连接,运行程序。
运行结果:
(1)用
AppWizard生成一个名为
Clock的单文档(SDI)程序框架。为了简化应用程序,在第四步时去掉
Docking toolbar和
Initial status bar选择项(不删除也可),其他各选项均可用缺省设置。
(2)编辑项目的菜单资源,在主框架窗口的主菜单
(IDR_MAINFRAME)中添加一个名为“时钟控制”的下拉菜单。在“时钟控制”菜单中添加三个菜单选项“启动时钟”、“停止时钟”和“时间设置”。并在菜单属性项中设定“启动时钟”菜单的ID标号为
ID_START,“停止时钟”菜单的ID标号为
ID_STOP,“时间设置”菜单的ID标号为
ID_SETTIME。为了简化菜单,可删除系统原有的“文件”、“编辑”菜单项。
(3)利用
ClassWizard为视图类添加菜单命令处理函数。进入
ClassWizard的
Message Maps选项卡,选择
Class Name项为
CClockView类,在Object IDs列表框中分别选择新添加的菜单选项的ID,在Messages列表框中选择COMMAND,按下Add Function按钮添加成员函数。
ClassWizard会为“启动时钟”、“停止时钟”和“时间设置”菜单选项添加相应的消息响应函数
OnStart ( )、OnStop ( )和OnSettime ( )。
(4)利用
ClassWizard为视图类添加定时器和鼠标消息处理函数。进入ClassWizard的Message Maps选项卡,选择Class Name项为
CClockView类,在Messages列表框中分别选择定时器消息
WM_TIMER和鼠标消息
WM_LBUTIONDOWN,按下Add Function按钮添加成员函数。ClassWizard会添加相应的定时器和鼠标消息响应函数
OnTimer和
OnLButtonDown。
(5)使用Developer Studio菜单的Insert / Resource…选项调出Insert Source对话框,为项目添加新的对话框资源。在对话框属性中,修改对话框名为“时间设定”。在对话框中增加用来输入年、月、日、时、分、秒的编辑框控件。
通过控件属性,将年、月、日、时、分、秒等编辑控件的ID改为
IDC_YEAR、IDC_MONTH、IDC_DAY、IDC_HOUR、IDC_MINUTE和IDC_SECOND。
(6)利用ClassWizard自动建立对话框类。进入ClassWizard后,弹出一个对话框询问是否要为该对话框模板建立类。按下“OK”按钮,会弹出New Class对话框,在Name栏填写对话框类的名称
CSetTimeDlg后按“OK”按钮,即可为对话框创建一个对应的类。
(7) 利用ClassWizard为对话框类添加与各控件对应的数据成员。选择MemberVariables选项卡,确保Class Name项为对话框CSetTimeDlg类,然后在选项卡下方的窗口中选择各控件的ID并按下“Add Variable…”按钮,为其添加对应成员变量。
控制ID 变量类型 变量名 变量范围
IDC_YEAR int m_Year 0~3000
IDC_MONTH int m_Month 1~12
IDC_DAY int m_Day 1~31
IDC_HOUR int m_Hour 0~23
IDC_MINUTE int m_Minute 0~59
IDC_SECOND int m_Second 0~59
最后一列为变量取值范围。
(8)编辑工程的图标资源,在Resource View选项窗口中修改Icon结点所包含的主框架图标(IDR_MAINFRAME)。此步非必须。
(9)完成以上工作后,即可修改程序框架,添加必要的代码。
二、主要源代码:
按以下步骤向视图类(CClockView)添加下列数据成员及成员函数。
(1) 添加表示年、月、日、时、分、秒的变量。
int year; int month; int day; int hour; int minute; int second;
(2) 添加秒表的计数变量。
int watch;
(3) 添加时钟的画笔及画刷变量。
CPen m_HouPen, m_MinPen, m_SecPen; // 各种针的画笔 CBrush m_MarkBrush; // 表盘标记的画刷
(4) 添加时钟控制变量。
CPoint m_Center; // 表的中心 double m_Radius; // 表的半径 CPoint m_Hour [2], m_OldHour [2]; // 时针当前及前一次位置 CPoint m_Minute [2], m_OldMin [2]; // 分针当前及前一次位置 CPoint m_Second [2], m_OldSec [2]; // 秒针当前及前一次位置
(5) 添加秒表的两个按钮位置变量。
CRect m_WatchStart; CRect m_WatchStop;
(6) 添加两个函数,计算时钟各指针位置。
void SetClock (int hour, int minute, int second); CPoint GetPoint (int nLenth, int nValue);
(7) 在视图类构造函数中增加初始化语句,之前加上头文件
#include<ctime> CClockView::CClockView() { // 设定时间 char time[32]; SYSTEMTIME st; GetLocalTime(&st); day = st.wDay; hour = st.wHour; minute = st.wMinute; month = st.wMonth; second = st.wSecond; year = st.wYear; // 设定画笔/画刷 m_HouPen. CreatePen (PS_SOLID, 5, RGB (255, 0, 0) ); // 时针画笔 m_MinPen. CreatePen (PS_SOLID, 3, RGB (0, 0, 250) ); // 分针画笔 m_SecPen. CreatePen (PS_SOLID, 1, RGB (0, 0, 0) ); // 秒针画笔 m_MarkBrush. CreateSolidBrush (RGB (250, 250, 0) ); // 设定表心位置 m_Center. x = 200; m_Center. y = 200; // 设定时钟半径 m_Radius = 200; // 计算指针位置 SetClock (hour, minute, second); // 设定秒表计数器及按钮位置 watch = 0; m_WatchStart = CRect (480, 310, 560, 340); // 启动钮 m_WatchStop = CRect (590, 310, 670, 340); // 停止钮 } 编写指针位置计算函数SetClock和GetPoint。首先在ClockView. cpp文件头部添加下面两行代码,以便进行数学计算。 #include "math.h" #define PI 3.14159265 然后添加下列代码: //计算各个指针位置的函数 void CClockView::SetClock(int hour, int minute, int second) { hour=hour*5; hour=hour+minute/12; // 保存时针原位置 m_OldHour [0] = m_Hour[0]; m_OldHour [1] = m_Hour[1]; // 计算时针当前位置 m_Hour[0]= GetPoint(int(m_Radius/2),hour); m_Hour[1]= GetPoint(7,hour + 30); // 保存分针原位置 m_OldMin[0]= m_Minute[0]; m_OldMin[1]= m_Minute[1]; // 计算分针当前位置 m_Minute[0]=GetPoint(int(m_Radius*7/10), minute); m_Minute[1]=GetPoint(10, minute+30); // 保存秒针原位置 m_OldSec [0] = m_Second [0]; m_OldSec [1] = m_Second [1]; // 计算秒针当前位置 m_Second [0]= GetPoint (int(m_Radius * 8/10), second); m_Second [1] = GetPoint (30, second + 30); } // 计算以表心为原点的指针的端点位置 CPoint CClockView ::GetPoint (int nLenth, int nValue) { CPoint p; double angle = nValue* PI /30-PI/2; p.x = m_Center.x + (int) (nLenth * cos(angle)); p.y = m_Center.y + (int) (nLenth * sin(angle)); return p; } 绘制表盘上的标记、时针、分针和秒针,并显示数字时钟及秒表,在OnDraw函数中添加下面代码: void CClockView::OnDraw(CDC* pDC) { CClockDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // 绘制表盘上的标记 pDC->SelectObject(m_MarkBrush); int k=0; for(int i=0;i<60;i++) { CPoint pt=GetPoint(175,i); if (i%5==0) { //显示表盘上的数字 CString str[12]={"12","1","2","3","4","5","6","7","8","9","10","11"}; pDC->TextOut(pt.x-5,pt.y-5,str[k]); k++; }else { //显示数字之间的圆圈 pDC->Ellipse(pt.x-2,pt.y-2,pt.x+2,pt.y+2); } } // 画时针 pDC->SelectObject (m_HouPen); if (m_OldHour[0]!= m_Hour[0]) { // 用白色覆盖原位置时针 pDC->SetROP2(R2_WHITE); pDC->MoveTo(m_OldHour [0] ); pDC->LineTo(m_OldHour [1] ); pDC->SetROP2(R2_COPYPEN); //时针绘制 pDC->MoveTo(m_Hour[0]); pDC->LineTo(m_Hour[1]); } else { // 时针绘制 pDC->MoveTo(m_Hour[0]); pDC->LineTo(m_Hour[1]); } // 画分针 pDC->SelectObject (m_MinPen); if (m_OldMin[0]!=m_Minute[0]) { // 用白色覆盖原位置分针 pDC->SetROP2(R2_WHITE); pDC->MoveTo(m_OldMin[0]); pDC->LineTo(m_OldMin[1]); pDC->SetROP2(R2_COPYPEN); // 分针绘制 pDC->MoveTo(m_Minute[0]); pDC->LineTo(m_Minute[1]); } else { // 分针绘制 pDC->MoveTo(m_Minute[0]); pDC->LineTo(m_Minute[1]); } // 用白色覆盖原位置秒针 pDC->SelectObject(m_SecPen); pDC->SetROP2(R2_WHITE); pDC->MoveTo(m_OldSec[0]); pDC->LineTo(m_OldSec[1]); pDC->SetROP2(R2_COPYPEN); // 秒针绘制 pDC->MoveTo(m_Second[0]); pDC->LineTo(m_Second[1]); // 数字时钟显示 pDC->SelectStockObject(WHITE_BRUSH); pDC->Rectangle(450,30,700,180); pDC->TextOut(535,20,"当前时间"); CString m_Date,m_Time; m_Date.Format ("% 4d年%4d月%4d日",year,month,day); pDC->TextOut(510,70,m_Date); m_Time.Format("%4d点%4d分%4d秒",hour,minute,second); pDC->TextOut(510,100,m_Time); // 秒表显示 pDC->Rectangle(450,220,700,370); pDC->TextOut(545,200,"秒 表"); int minSec= watch%100; int Sec=(watch/100)%60; int Min=(watch/100)/60; m_Time.Format("% 02d: % 02d: % 02d",Min,Sec,minSec); pDC->TextOut(535,260,m_Time); pDC->Rectangle(&m_WatchStart); pDC->Rectangle(&m_WatchStop); pDC->TextOut(m_WatchStart.left + 18,m_WatchStart.top + 5,"启动"); pDC->TextOut(m_WatchStop.left + 18,m_WatchStop.top + 5,"停止"); }
请注意将表示时间的整数转换为CString字符串类型的方法以及秒表的显示方法。另外,watch计数器以1/100秒为计数单位,每达到100则秒数加1。
按照下列步骤增加时钟控制代码:
修改Onstart和OnStop函数,设置时钟运动消息。按比正常时钟快20倍的假定,50ms产生一个消息。本程序采用和正常时间同步,即1000ms产生一个消息, 其代码为:
void CClockView::OnStart() { SetTimer (1, 1000, NULL); } void CClockView::OnStop() { KillTimer (1); } 修改OnTimer函数,正确计算并处理年、月、日、时、分、秒等变量的联动变化 ,其代码为: void CClockView::OnTimer(UINT nIDEvent) { if (nIDEvent == 1) { second++; // 秒增加 if (second>59) { second=0; minute++; // 分增加 } if (minute>59) { minute= 0; hour++; // 小时增加 } if (hour>23) { hour=0; day++; // 日增加 } switch(month) { case 1: // 大月 case 3: case 5: case 7: case 8: case 10: case 12: if (day>31) { day= 1; month++; // 月增加 } break; case 4: // 小月 case 6: case 9: case 11: if (day>30) { day=1; month++; // 月增加 } break; case 2: if (year%4 ==0 && day>29) // 润二月 { day=1; month++; // 月增加 } if (year%4!=0 && day>28) // 二月 { day=1; month++; } break; } if (month > 12) { // 年增加 year++; month=1; } SetClock (hour, minute, second); Invalidate (false); } // 秒表定时器消息处理 if (nIDEvent == 2) { watch++; Invalidate (false); } CView::OnTimer(nIDEvent); }
添加时间设置对话框代码。
首先在ClockView. cpp文件头部添加下列语句:
#include “SetTimeDlg. h”
在时间设定对话框类的构造函数中,做如下修改,将初始日期设为当前时间,之前要加上头文件
#include<ctime> CSetTimeDlg::CSetTimeDlg(CWnd* pParent /*=NULL*/) : CDialog(CSetTimeDlg::IDD, pParent) { //||AFX_DATA_INIT(CSetTimeDlg) char time[32]; SYSTEMTIME st; GetLocalTime(&st); m_Day = st.wDay; m_Hour = st.wHour; m_Minute = st.wMinute; m_Month = st.wMonth; m_Second = st.wSecond; m_Year = st.wYear;// ||AFX_DATA_INIT } 最后,在OnSettime函数中添加代码如下: void CClockView::OnSettime() { CSetTimeDlg SetDlg; if (SetDlg.DoModal ()==IDOK) { year=SetDlg.m_Year; month= SetDlg.m_Month; day= SetDlg.m_Day; hour=SetDlg.m_Hour; minute=SetDlg.m_Minute; second=SetDlg.m_Second; } // 计算各指针位置 SetClock (hour,minute,second); Invalidate (true); } 按以下步骤设计秒表控制程序: 在OnLButtonDown函数中增加下列内容,以便响应单击秒表启动、停止框所发出的消息: void CClockView::OnLButtonDown(UINT nFlags, CPoint point) { if (m_WatchStart.PtInRect(point)) { watch=0; SetTimer(2,10,NULL); } if (m_WatchStop.PtInRect(point)) { KillTimer (2); } CView::OnLButtonDown(nFlags, point); }
编译,连接,运行程序。
运行结果:
相关文章推荐
- 孙鑫VC学习笔记:第十五讲 编写一个基于MFC对话框的聊天程序
- 孙鑫VC学习笔记:第十五讲 (四) 编写一个基于MFC对话框的聊天程序
- 孙鑫VC学习笔记:第十五讲 编写一个基于MFC对话框的聊天程序
- 接触VC之三:MFC基于对话框程序
- VC++的学习(基于VS2008)——windows程序内部运行机制
- 基于VC 6.0 开发的MFC程序如何在文件资源管理器中浏览并选中操作文件
- VC++学习(3):MFC框架程序剖析
- JAVA学习第六十课 — UDP协议 &基于多线程模拟简单的QQ聊天程序
- OpenCV学习笔记(25)基于MFC和OpenCV的摄像机定标与立体匹配测试程序(20140505更新)
- (他山之石)MFC学习之路(一)VC MFC程序,在About对话框中获取并显示程序的版本号
- WinForm学习(1) --简单的模拟时钟程序
- WinForm学习 --简单的模拟时钟程序
- OpenCV学习笔记(25)基于MFC和OpenCV的摄像机定标与立体匹配测试程序(20140505更新)
- 基于QT的时钟模拟程序
- 基于MFC+VC平台下开发程序问题及技巧综合
- MFC学习笔记——状态栏(基于对话框的MFC程序)
- OpenCV学习笔记(25)基于MFC和OpenCV的摄像机定标与立体匹配测试程序(20140505更新)
- VS2012 MFC 单文档 模拟时钟日历程序
- MFC三层模式标准版V1.5版演示源码(VC++代码生成,VC非托管代码,基于对话框程序)
- 孙鑫VC++视频学习笔记之2: MFC程序框架的剖析