c++模拟时钟实验报告.docx
- 文档编号:3884131
- 上传时间:2022-11-26
- 格式:DOCX
- 页数:27
- 大小:175.38KB
c++模拟时钟实验报告.docx
《c++模拟时钟实验报告.docx》由会员分享,可在线阅读,更多相关《c++模拟时钟实验报告.docx(27页珍藏版)》请在冰豆网上搜索。
c++模拟时钟实验报告
集中上机实习报告
指导教师:
王利
姓名:
赵蕊
学号:
2010211864
班级:
0411003
时间:
2012.5
模拟时钟程序
一.需求分析
1.题目内容:
编写一个模拟时钟程序,此程序在屏幕左方有一指针式钟面,右方有两个矩形框,上面以数字方式显示日期和时间,该时间应与指针显示的时间一致,下方的矩形框作为秒表。
用菜单选项或按钮设置时间和秒表。
时间不必与机器系统时间相同,只要可任意设置即可。
2.题目分析:
(1)模拟时钟是一种集计时器和时钟显示于一体的程序。
编写一个指针式时钟程序,此程序在屏幕左方有一个指针式钟面,右方有两个矩形框,上面以数字方式显示日期、星期和时间。
指针式的时钟表盘为圆形,并且圆周上有分布均匀的60个刻度,刻度要求显示清楚,钟面上有长度不相同的指针,即时针、分针、秒针,指针的运动要求具有规律性,且为顺时针。
数字钟显示时间的格式是年月日星期时分秒,小时为24进制,分钟和秒是60进制,指针式的时钟和数字式的时钟显示的时间同步。
按下时钟控制设置时间菜单项可弹出一对话框,用于设置当前的时间、日期和星期;按下秒表控制按钮后,秒表显示窗中显示从0开始的时间,单位为百分之一秒。
再次按下秒表控制按钮后计时停止,该窗口显示累计时间。
(2)本实验主要涉及到的知识点有:
时钟指针运动算法、屏幕重绘方法、定时器消息、鼠标消息、菜单命令、对话框、画笔/画刷、显示文字等。
指针运动算法和屏幕重绘方法是本程序主要难点所在。
3.最终效果如下图:
二.概要设计
1.程序系统模块划分
图1功能模块图
2.程序算法分析
本程序不论何种指针,每次转动均以π/30弧度(一秒的角度)为基本单位,且都以表盘中心为转动圆心。
计算指针端点(x,y)的公式如下:
x=圆心x坐标+指针长度*cos(指针方向角)
y=圆心y坐标+指针长度*sin(指针方向角)
指针长度是指自圆心至指针一个端点的长度,由于指针要跨越圆心,因此一个指针需要计算两个端点。
三个指针的运动是相关联的,秒针转一圈引起分针运动一格,分针每转12格引起时针运动一格,而因此应该使用一个定时器消息来处理指针的运动。
若用三个定时器消息分别处理时针、分针和秒针的运动,就会使问题复杂化且不易实现三个指针联动的正确规律。
采用一个定时器消息可以很容易实现指针联动算法。
由于屏幕的重绘速度快,如果采用全屏删除式重绘则闪烁十分明显,显示效果不佳。
本程序采用非删除式重绘,假定指针将要移动一格,则先采用表盘背景色(这里为浅绿色)重绘原来指针以删除原来位置的指针,再采用指针的颜色在当前位置绘制指针;如果指针没有动,则直接绘制指针。
另外,秒表需要采用单独的定时器消息控制,秒表重绘速度很快,屏幕闪烁明显,故本程序采用了双缓冲绘图。
3.系统流程图
三.详细设计
1.模块描述
(1)指针式时钟
指针式的时钟表盘为圆形,并且圆周上有分布均匀的12个数字刻度和48个较小的原点刻度,刻度显示清楚,用来表示小时、分钟和秒数。
钟面上有长度不相同的指针,即时针、分针、秒针,指针的运动具有规律性,为顺时针。
(2)数字式时钟
数字钟显示时间的格式是时分秒,小时为24进制,分钟和秒是60进制,指针式的时钟和数字式的时钟显示的时间同步,且俩时钟可以同时设置。
(3)秒表
按下秒表控制按钮后,秒表显示窗中显示从0开始的时间,单位为百分之一秒。
再次按下秒表控制按钮后计时停止,该窗口显示累计时间。
2.函数描述
(1)CPointp;
doubleangle=nvalue*PI/30;
p.x=m_Center.x+(int)(nlenth*sin(angle));
p.y=m_Center.y-(int)(nlenth*cos(angle));
returnp;
用来得到时钟刻度点和时针、分针、秒针的端点
(2)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_Radious/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_Radious*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_Radious*8/10),second);
m_Second[1]=GetPoint(30,second+30);
用来得到时针、分针、秒针的当前位置和上一时刻位置并将其保存
(3)CRectrc;
CDCdcMem;
GetClientRect(&rc);
CBitmapbmp;
dcMem.CreateCompatibleDC(pDC);
bmp.CreateCompatibleBitmap(pDC,rc.Width(),rc.Height());
CBitmap*pOldBit=dcMem.SelectObject(&bmp);
dcMem.FillSolidRect(rc,RGB(255,255,255));
………….//画图代码
pDC->BitBlt(0,0,rc.Width(),rc.Height(),&dcMem,0,0,SRCCOPY);
dcMem.DeleteDC();
bmp.DeleteObject();
利用双缓冲防止屏幕画面闪烁
四.实现环境及工具
Win7环境下
VC++6.0MFC
五.程序测试
1.对时间设置测试
按下确定后测试其设置为需要设置的时间,并正常运行。
2.对秒表测试
点下启动后它正常运行;
点下停止后它停止运行并记录当前累积时间。
再次按下启动按钮时它计时清零并重新开始计时。
3.整体3部分测试
同时运行时三部分均正常运行,并且屏幕也不闪烁。
六.心得体会
通过本次实验,对c++编程有了进一步的了解和能够更加熟练的编程,还学习了MFC的一些画图处理函数,以及一些运行机理,能够基本掌握用MFC画图,且能够实现一些基本的功能。
在本次设计的初期,只实现了小部分功能,对画图及其不了解,且对窗口设置的不合理倒是画面相当丑陋,后来通过请教同学、老师、上网查资料,最终设计出比较满意的画面。
还有,本次设计的秒表设计,由于它的刷新频率太高,导致屏幕闪烁严重,画面看起来很不舒畅,后面经查资料发现双缓冲技术能够解决这一问题,也将这个问题成功解决。
觉得本次设计中的采用不同的计时器来控制不同的模块效果比较好,对每一模块进行独立的控制很短单,而且思路清晰。
总之在本次实验中我学到了很多知识,而且培养了自己的自学能力,逼着自己进行查阅大量的资料。
在本次实验中自己对程序一直修改,一直增加功能和改善画面,大大的提高了自己的动手能力。
附:
源代码及详细注释(由于使用的MFC向导形成工程只附部分核心代码)
在
中加
public:
intyear;
intmonth;
intday;
inthour;
intsecond;
intminute;
intwatch;
intwday;
CPenm_HouPen,m_NoHouPen,m_MinPen,m_NoMinPen,m_SecPen,m_NoSecPen,m_circle,m_RectPen;
HBRUSHm_HurkBrush,m_CircleBrush,m_RecBrush,m_RectBrush,m_RectBrush1,m_RectBrush2;
CPointm_Center;
doublem_Radious;
CPointm_Hour[2],m_OldHour[2];
CPointm_Minute[2],m_OldMin[2];
CPointm_Second[2],m_OldSec[2];
CRectm_WatchStart;
CRectm_WatchStop;
voidSetClock(inthour,intminute,intsecond);
CPointGetPoint(intnlenth,intnvalue);
#include"stdafx.h"
#include"Clock.h"
#definePI3.14159265
#include
#include"SetTimeDlg.h"
#include"ClockDoc.h"
#include"ClockView.h"
#include
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
中初始化设置变量
/////////////////////////////////////////////////////////////////////////////
//CSetTimeDlgdialog
CSetTimeDlg:
:
CSetTimeDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CSetTimeDlg:
:
IDD,pParent)
{
//{{AFX_DATA_INIT(CSetTimeDlg)
longnow=time(NULL);
tmlocal=*localtime(&now);
m_Day=local.tm_mday;;
m_Hour=local.tm_hour;
m_Minute=local.tm_min;
m_Month=local.tm_mon+1;
m_Second=local.tm_sec;
m_Year=local.tm_year+1900;
m_Wday=local.tm_wday;
//}}AFX_DATA_INIT
}
voidCSetTimeDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSetTimeDlg)
DDX_Text(pDX,ID_DAY,m_Day);
DDV_MinMaxInt(pDX,m_Day,1,31);
DDX_Text(pDX,ID_HOUR,m_Hour);
DDV_MinMaxInt(pDX,m_Hour,0,23);
DDX_Text(pDX,ID_MINUTE,m_Minute);
DDV_MinMaxInt(pDX,m_Minute,0,59);
DDX_Text(pDX,ID_MONTH,m_Month);
DDV_MinMaxInt(pDX,m_Month,1,12);
DDX_Text(pDX,ID_SECOND,m_Second);
DDV_MinMaxInt(pDX,m_Second,0,59);
DDX_Text(pDX,ID_YEAR,m_Year);
DDV_MinMaxInt(pDX,m_Year,0,3000);
DDX_Text(pDX,ID_WDAY,m_Wday);
DDV_MinMaxInt(pDX,m_Wday,0,6);
//}}AFX_DATA_MAP
}
/////////////////////////////////////////////////////////////////////////////
//CClockView
IMPLEMENT_DYNCREATE(CClockView,CView)
BEGIN_MESSAGE_MAP(CClockView,CView)
//{{AFX_MSG_MAP(CClockView)
ON_COMMAND(ID_START,OnStart)
ON_COMMAND(ID_STOP,OnStop)
ON_COMMAND(ID_STETIME,OnStetime)
ON_WM_TIMER()
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
//Standardprintingcommands
ON_COMMAND(ID_FILE_PRINT,CView:
:
OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT,CView:
:
OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW,CView:
:
OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CClockViewconstruction/destruction
CClockView:
:
CClockView()
{//初始化时间为系统时间
longnow=time(NULL);
tmlocal=*localtime(&now);
year=local.tm_year+1900;
month=local.tm_mon+1;
day=local.tm_mday;
minute=local.tm_min;
hour=local.tm_hour;
second=local.tm_sec;
wday=local.tm_wday;
//创建画笔、画刷
m_HouPen.CreatePen(PS_SOLID,5,RGB(255,50,0));
m_NoHouPen.CreatePen(PS_SOLID,5,RGB(204,255,102));
m_MinPen.CreatePen(PS_SOLID,3,RGB(0,0,255));
m_NoMinPen.CreatePen(PS_SOLID,3,RGB(204,255,102));
m_SecPen.CreatePen(PS_SOLID,1,RGB(0,0,0));
m_NoSecPen.CreatePen(PS_SOLID,1,RGB(204,255,102));
m_circle.CreatePen(PS_SOLID,2,RGB(0,0,0));
m_RectPen.CreatePen(PS_SOLID,3,RGB(204,102,0));
m_HurkBrush=CreateSolidBrush(RGB(255,0,0));
m_CircleBrush=CreateSolidBrush(RGB(204,255,102));
m_RecBrush=CreateSolidBrush(RGB(255,255,51));
m_RectBrush=CreateSolidBrush(RGB(102,51,0));
m_RectBrush1=CreateSolidBrush(RGB(255,51,0));
m_RectBrush2=CreateSolidBrush(RGB(0,102,204));
m_Center.x=200;
m_Center.y=200;
m_Radious=185;
SetClock(hour,minute,second);
watch=0;
m_WatchStart=CRect(480,310,560,340);
m_WatchStop=CRect(590,310,670,340);
//TODO:
addconstructioncodehere
}
CClockView:
:
~CClockView()
{
}
voidCClockView:
:
SetClock(inthour,intminute,intsecond)
{
hour=hour*5;//时针每过1小时转5*PI/3
hour=hour+minute/12;//时针每过12分钟转PI/3
//保存时钟原位置
m_OldHour[0]=m_Hour[0];
m_OldHour[1]=m_Hour[1];
//计算时针当前位置
m_Hour[0]=GetPoint(int(m_Radious/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_Radious*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_Radious*8/10),second);
m_Second[1]=GetPoint(30,second+30);
}
CPointCClockView:
:
GetPoint(intnlenth,intnvalue)
{//用来计算指针的俩端点的位置和表盘上刻度的位置
CPointp;
doubleangle=nvalue*PI/30;
p.x=m_Center.x+(int)(nlenth*sin(angle));
p.y=m_Center.y-(int)(nlenth*cos(angle));
returnp;
}
BOOLCClockView:
:
PreCreateWindow(CREATESTRUCT&cs)
{
//TODO:
ModifytheWindowclassorstylesherebymodifying
//theCREATESTRUCTcs
returnCView:
:
PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
//CClockViewdrawing
//*********画表***********//
voidCClockView:
:
OnDraw(CDC*pDC)
{
SetTimer(1,1000,NULL);
CClockDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
CRectrc;
CDCdcMem;
GetClientRect(&rc);
CBitmapbmp;//内存中承载临时图象的位图
dcMem.CreateCompatibleDC(pDC);//依附窗口DC创建兼容内存DC
//创建兼容位图(必须用pDC创建,否则画出的图形变成黑色)
bmp.CreateCompatibleBitmap(pDC,rc.Width(),rc.Height());
CBitmap*pOldBit=dcMem.SelectObject(&bmp);//按原来背景填充客户区,不然会是黑色
dcMem.FillSolidRect(rc,RGB(255,255,255));
//画图,添加你要画图的代码,不过用dcMem画,而不是pDc
//画表盘最外面的大圆并填充颜色
dcMem.SelectObject(m_circle);
dcMem.Ellipse(m_Center.x-195,m_Center.y-195,m_Center.x+195,m_Center.y+195);
dcMem.SelectObject(m_CircleBrush);
dcMem.Ellipse(m_Center.x-195,m_Center.y-195,m_Center.x+195,m_Center.y+195);
//画60个刻度
for(inti=0;i<60;i++)
{
CPointpt=GetPoint(m_Radious,i);
dcMem.SelectObject(m_SecPen);
//画小时刻度
if(i%5==0)
{
CStringm_Number;
dcMem.SetBkMode(TRANSPARENT);//将textout背景透明
m_Number.Format("%2d",(i/5==0?
12:
i/5));
dcMem.TextOut(pt.x-7,pt.y-7,m_Number);
}//画小时之间的刻度
else
{
dcMem.SelectObject(m_HurkBrush);
dcMem.Ellipse(pt.x-2,pt.y-2,pt.x+2,pt.y+2);
}
}
//画时针
if(m_OldHour[0]!
=m_Hour[0])
{//用表盘背景色覆盖原来的时针
dcMem.SelectObject(m_NoHouPen);
dcMem.MoveTo(m_OldHour[0]);
dcMem.LineTo(m_OldHour[1]);
//时针绘制
dcMem.SelectObject(m_HouPen);
dcMem.MoveTo(m_Hour[0]);
dcMem.LineTo(m_Hour[1]);
}
else
{
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- c+ 模拟 时钟 实验 报告