《用VC++制作-模拟时钟应用程序.docx》由会员分享,可在线阅读,更多相关《用VC++制作-模拟时钟应用程序.docx(23页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、案例五 模拟时钟应用程序以实例为背景学习基于MFCWINDOWS应用程序设计,编写一个模拟时钟程序,此程序在屏幕左边有一个指针式钟面,右方有两个矩形框,上面以数字方式显示日期和时间,该时间应与指针显示时间一致,下方矩形框作为秒表。用菜单项选择项或按钮设置时间和秒表。时间不必与机器系统时间一样,可任意设置。模拟时钟示意图1 编程要求1为该程序设计一个美观大方图标。2程序界面设计合理,色彩得体大方,显示正确。3时针、分针和秒针形象美观,即使各指针重合也可识别。4各指针运动规律正确。为便于演示,时钟速度应比实际时间快20倍,即1小时相当于3分钟。5数字式时钟时间显示与指针式时钟显示一致。6按下设置时
2、间按钮或菜单项可弹出一对话框,用于设置当前时间和日期。7按下秒表控制按钮后,秒表显示窗中显示从0开场时间,单位为百分之一秒。再次按下秒表控制按钮后计时停顿,该窗口显示累计时间。2 问题分析此题主要涉及到知识点有:时钟指针运动算法、屏幕重绘方法、定时器消息、鼠标消息、菜单命令、对话框、画笔/画刷、显示文字等。指针运动算法和屏幕重绘方法是本程序主要难点所在。不管何种指针,每次转动均以/30弧度一秒角度为根本单位,且都以表盘中心为转动圆心。计算指针端点x, y公式如下:x =圆心x坐标 + 指针长度 * cos (指针方向角)y =圆心y坐标 + 指针长度 * sin (指针方向角)注意,指针长度是
3、指自圆心至指针一个端点长度是整个指针一局部,由于指针可能跨越圆心,因此一个指针需要计算两个端点。三个指针运动是相关联,秒针转一圈引起分针运动一格,分针转一圈引起时针运动一格,因此应该使用一个定时器消息来处理指针运动。假设用三个定时器消息分别处理时针、分针和秒针运动,就会使问题复杂化且不易实现三个指针联动正确规律。采用一个定时器消息可以很容易实现指针联动算法。由于屏幕重绘速度很快50 ms一次,如果采用全屏删除式重绘那么闪烁十清楚显,显示效果不佳。本程序采用非删除式重绘,假定指针将要移动一格,那么先采用背风光这里是白色重绘原来指针以删除原来位置指针,再采用指针颜色在当前位置绘制指针;如果指针没有
4、动,那么直接绘制指针。另外,秒表需要采用单独定时器消息控制。3 实现步骤1用AppWizard生成一个名为Clock单文档SDI程序框架。为了简化应用程序,在第四步时去掉Docking toolbar和Initial status bar选择项,其他各选项均可用缺省设置。2编辑工程菜单资源,在主框架窗口主菜单IDR_MAINFRAME中添加一个名为“时钟控制下拉菜单。在“时钟控制菜单中添加三个菜单项选择项“启动时钟、“停顿时钟和“时间设置。并在菜单属性项中设定“启动时钟菜单ID标号为ID_START,“停顿时钟菜单ID标号为ID_STOP,“时间设置菜单ID标号为ID_SETTIME。为了简化
5、菜单,可删除系统原有“文件、“编辑菜单项。3利用ClassWizard为视图类添加菜单命令处理函数。进入ClassWizardMessage Maps选项卡,选择Class Name项为CClockView类,在Object IDs列表框中分别选择新添加菜单项选择项ID,在Messages列表框中选择COMMAND,按下Add Function按钮添加成员函数。ClassWizard会为“启动时钟、“停顿时钟和“时间设置菜单项选择项添加相应消息响应函数OnStart ( )、OnStop ( )和OnSettime ( )。4利用ClassWizard为视图类添加定时器和鼠标消息处理函数。进入
6、ClassWizardMessage Maps选项卡,选择Class Name项为 CClockView类,在Messages列表框中分别选择定时器消息WM_TIMER和鼠标消息WM_LBUTIONDOWN,按下Add Function按钮添加成员函数。ClassWizard会添加相应定时器和鼠标消息响应函数OnTimer和OnLButtonDown。5使用Developer Studio菜单Insert / Resource选项调出Insert Source对话框,为工程添加新对话框资源。在对话框属性中,修改对话框名为“时间设定。在对话框中增加用来输入年、月、日、时、分、秒编辑框控件,如以下
7、图所示。对话框通过控件属性,将年、月、日、时、分、秒等编辑控件ID改为IDC_YEAR、IDC_MONTH、IDC_DAY、IDC_HOUR、IDC_MINUTE和IDC_SECOND。6设计好这个对话框模板后,利用ClassWizard自动建立对话框类。进入ClassWizard后,它会发现已建立对话框模板资源,并弹出一个对话框询问是否要为该对话框模板建立类。按下“OK按钮,会弹出New Class对话框,在Name栏填写对话框类名称CSetTimeDlg后按“OK按钮,即可为对话框创立一个对应类。7 利用ClassWizard为对话框类添加与各控件对应数据成员。选择MemberVariab
8、les选项卡,确保Class Name项为对话框CSetTimeDlg类,然后在选项卡下方窗口中选择各控件ID并按下“Add Variable按钮,为其添加对应成员变量,如表所示。表11.4 编辑控件属性Control IDsVariable TypeMember variable nameVariable RangeIDC_YEARintm_Year03000IDC_MONTHintm_Month112IDC_DAYimtm_Day131IDC_HOURimtm_Hour023IDC_MINUTEintm_Minute059IDC_SECONDintm_Second059最后一列为变量取值范
9、围。8编辑工程图标资源,在Resource View选项窗口中修改Icon结点所包含主框架图标IDR_MAINFRAME,修改标准图标32像素32像素及小图标16像素16像素,从而为该程序设计一个美观大方图标。9完成以上工作后,即可修改程序框架,添加必要代码。4 程序清单按以下步骤向视图类CClockView添加以下数据成员及成员函数。(1) 添加表示年、月、日、时、分、秒变量。int year;int month;int day;int hour;int minute;int second;(2) 添加秒表计数变量。int watch;(3) 添加时钟画笔及画刷变量。CPen m_HouPe
10、n, 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)
11、 添加两个函数,计算时钟各指针位置。void SetClock (int hour, int minute, int second);CPoint GetPoint (int nLenth, int nValue);(7) 在视图类构造函数中增加初始化语句:然后添加以下代码:绘制表盘上标记、时针、分针和秒针,并显示数字时钟及秒表:在OnDraw函数中添加下面代码:/ 用白色覆盖原位置时针请注意将表示时间整数转换为CString字符串类型方法以及秒表显示方法。另外,watch计数器以1/100秒为计数单位,每到达100那么秒数加1。u 按照以下步骤增加时钟控制代码: 修改Onstart和OnSt
12、op函数,设置时钟运动消息。按比正常时钟快20倍假定,50ms产生一个消息。 其代码为: 修改OnTimer函数,正确计算并处理年、月、日、时、分、秒等变量联动变化 ,其代码为: 添加时间设置对话框代码。首先在ClockView. cpp文件头部添加以下语句:#include “SetTimeDlg. H在时间设定对话框类构造函数中,做如下修改,将初始日期设为2010-7-10:最后,在OnSettime函数中添加代码如下:至此,除秒表外,时钟局部程序设计完成。u 按以下步骤设计秒表控制程序:在OnLButtonDown函数中增加以下内容,以便响应单击秒表启动、停顿框所发出消息:程序运行:以下
13、图显示了模拟时钟运行情况。“启动和“停顿框控制秒表,时钟用菜单控制。此题采用标准SDI程序构造,完全利用视图类实现了这一程序。利用定时器消息控制时钟运动是本程序出发点。利用一个定时器控制时钟,易于实现指针联动规律。计算指针位置利用了坐标变换和三角函数知识。本程序一个较难处理地方是屏幕重绘,由于完全在OnDraw函数中实现,因此限制较多。本程序采取了先覆盖,再重绘方法。模拟时钟示意图本程序由于完全在OnDraw函数中实现,因此屏幕重绘较为麻烦。如果在OnDarw函数中采用“异或屏幕重绘方式,在程序窗口最大、最小化及移出屏幕时,会显示异常。解决这一问题较理想方式是在定时器处理函数OnTimer中采用“异或方式直接重绘屏幕,而不采用调用Invalidate ( )函数方式;同时在OnDraw函数中显示指针最后状态,以便处理程序窗口最大、最小化及移出屏幕情况。在OnTimer函数中直接重绘屏幕需要使用OClientDC类,具体用法与OnDraw函数中pDC对象根本一致。另外,本程序数字时钟没有显示星期和农历,读者可尝试添加进去。
限制150内