北邮程序设计实践实验一时钟改进实验报告.docx
《北邮程序设计实践实验一时钟改进实验报告.docx》由会员分享,可在线阅读,更多相关《北邮程序设计实践实验一时钟改进实验报告.docx(21页珍藏版)》请在冰点文库上搜索。
北邮程序设计实践实验一时钟改进实验报告
程序设计实践
实验一:
绘图程序Draw的实现之时钟改进
设
计
报
告
课题名称:
时钟改进之星轨与时钟
学生姓名:
班级:
班内序号:
学号:
日期:
一、课题概述·········································
二、系统设计··································
三、程序设计亮点展示····························
四、运行结果分析····································
五、遇到的难题与解决方法····························
六、总结···········································
参考文献·························································
一、课题概述
1.1课题目标和主要内容
主要内容:
根据所提供的时钟代码,新建派生类,利用WINDOWSAP设计和绘制图形。
目标:
以培养学生动手实践能力为目的,重点是在学习C++程序设计和数据结构的基础上,使学生从实践中学习如何综合运用C++和数据结构的相关知识解决实际应用中的问题,了解程序设计的基本思想在具体实际应用中的体现,掌握分析问题、解决问题的方法,从而提高学生的编程能力,达到编程熟练、会调试、代码书写规范的基本要求,具备简单应用程序的设计、实现能力。
平台:
Visualstudio2013API平台。
1.2系统的主要功能
1.绘制菜单一:
绘制星轨时钟,准确读出系统时间,时分秒钟都为新建图元类,代表星星,月亮,阳光;
2.绘制菜单二:
绘制成长星轨,可以看到随时间变化、成长、旋转的星星;
2.系统设计
2.1系统总体框架
2.2系统详细设计
[1]类关系图及描述
[2]程序流程图及描述
指定窗口函数(消息处理入口)
→添加菜单资源初始化窗口
→生成窗口并显示更新窗口
→UpdateWindow(hwnd);若UpdateRegion不空,则发送WM_PAINT消息
→while(GetMessage(&msg,NULL,0,0))消息循环,对用户操作进行响应
→TranslateMessage(&msg);将虚拟键消息转换成字符消息,再送入消息队列
→DispatchMessage(&msg);分发消息,将队列中消息发送到窗口处理函数
→窗口过程函数
→绘图函数
2.3关键算法分析
算法1:
窗口过程函数
[1]算法功能
当按下指定菜单,窗口需要运行相应的处理函数。
[2]算法基本思想
在API里定义了一个函数为回调函数,当系统需要向窗口发送消息时,就会调用窗口给出的回调函数WindowProc,如果WindowProc函数不处理这个消息,就可以把它转向DefWindowProc函数来处理,这是系统的默认消息处理函数。
[3]源代码
LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
函数:
WndProc(HWND,UINT,WPARAM,LPARAM)
//
//目的:
处理主窗口的消息。
//
//WM_COMMAND-处理应用程序菜单
//WM_PAINT-绘制主窗口
//WM_DESTROY-发送退出消息并返回
//
LRESULTCALLBACKWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)
{
staticintmenuId=0;
intwmId,wmEvent;
PAINTSTRUCTps;
HDChdc;
HDCmainwin_hdc;
switch(message)
{
caseWM_CREATE:
SetTimer(hWnd,1,1000,NULL);
break;
caseWM_TIMER:
InvalidateRect(hWnd,NULL,TRUE);
break;
caseWM_COMMAND:
wmId=LOWORD(wParam);
wmEvent=HIWORD(wParam);
switch(wmId)
{
caseIDM_ABOUT:
DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUTBOX),hWnd,About);
break;
caseIDM_FIG1:
menuId=IDM_FIG1;
InvalidateRect(hWnd,NULL,TRUE);
break;
caseIDM_FIG2:
menuId=IDM_FIG2;
InvalidateRect(hWnd,NULL,TRUE);
break;
caseIDM_FIG3:
menuId=IDM_FIG3;
InvalidateRect(hWnd,NULL,TRUE);
break;
caseIDM_EXIT:
DestroyWindow(hWnd);
break;
default:
returnDefWindowProc(hWnd,message,wParam,lParam);
}
break;
caseWM_PAINT:
mainwin_hdc=BeginPaint(hWnd,&ps);
if(menuId)
{
cwin.open(hWnd,mainwin_hdc);
ccc_win_main(menuId);
}
EndPaint(hWnd,&ps);
break;
caseWM_DESTROY:
KillTimer(hWnd,1);
PostQuitMessage(0);
break;
default:
returnDefWindowProc(hWnd,message,wParam,lParam);
}
return0;
}
算法2:
绘图函数(以画ellipse为例)
[1]算法功能
运行函数时,绘出相应图形。
[2]算法基本思想
设置doublex,doubley,doublera,doublerb,COLORREFmColor等变量,当运行函数时根据相应参数画出图形
在这里我新建了一个重载函数和类,多定义了COLORREFicolor变量。
oColor指的是画圆的笔的颜色,而icolor则是填充圆的画刷的颜色。
通过在voidGraphicWindow:
:
ellipse中新建笔和刷子用来绘图,最后将比和刷子的颜色恢复成预制,删除新建笔刷。
如下图所示:
[3]源代码
/*Plotsaellipse.*/
voidellipse(doublex,doubley,doublera,doublerb,COLORREFmColor);
voidellipse(doublex,doubley,doublera,doublerb,COLORREFoColor,COLORREFicolor);
voidGraphicWindow:
:
ellipse(doublex,doubley,doublera,doublerb,COLORREFoColor,COLORREFicolor)
{
HPENsave_pen=(HPEN)SelectObject(_hdc,CreatePen(PS_SOLID,1,oColor));
HBRUSHbrush=CreateSolidBrush(icolor);
HBRUSHsave_brush=(HBRUSH)SelectObject(_hdc,brush);
Ellipse(_hdc,user_to_disp_x(x-ra),user_to_disp_y(y-rb),
user_to_disp_x(x+ra),user_to_disp_y(y+rb));
SelectObject(_hdc,save_brush);
DeleteObject(brush);
SelectObject(_hdc,save_pen);
GraphicWindow&GraphicWindow:
:
operator<<(Circlec)
{
ellipse(c.get_center().get_x(),c.get_center().get_y(),c.get_radius(),c.get_radius(),c.get_ocolor(),c.get_icolor());
return*this;
}
CircleclkPlate3(org,radius-2);
pShape=&clkPlate3;
pShape->SetColor(RGB(148,0,211));//深紫罗兰色
clkPlate3.SetColoro(RGB(148,0,211));
cwin<}其他
使用了尽量减少值传递,多用引用来传递参数……有助于提高代码简洁和效率的方法。
三、程序设计亮点展示
亮点一:
新建三个图元类starsline,moonmline以及sunhline来画新的表针
新建三个图元类starsline,moonmline以及sunhline来画新的表针,表针端头都有随之转动的特殊图像
如图所示:
sunhlineStarslinemoonmline
以starsline为例,实现代码如下
/*Plotsastarsline.*/
voidStarsline(doublexfrom,doubleyfrom,doublexto,doubleyto,COLORREFmColor);
classstarsline:
publicShape
{
public:
starsline();
starsline(Pointp1,Pointp2);
Pointget_start()const;
Pointget_end()const;
COLORREFget_color()const;
virtualvoidmove(doubledx,doubledy);
virtualvoidSetColor(COLORREFmColor);
private:
Pointfrom;
Pointto;
COLORREFcolor;
};
starsline:
:
starsline()
{
}
starsline:
:
starsline(Pointp1,Pointp2)
{
from=p1,to=p2;
}
Pointstarsline:
:
get_start()const
{
returnfrom;
}
Pointstarsline:
:
get_end()const
{
returnto;
}
COLORREFstarsline:
:
get_color()const
{
returncolor;
}
voidstarsline:
:
move(doubledx,doubledy)
{
from.move(dx,dy);
to.move(dx,dy);
}
voidstarsline:
:
SetColor(COLORREFmColor)
{
color=mColor;
}
voidGraphicWindow:
:
Starsline(doublexfrom,doubleyfrom,doublexto,doubleyto,COLORREFmColor)
{
doublec=(yfrom-yto)/sqrt((xfrom-xto)*(xfrom-xto)+(yfrom-yto)*(yfrom-yto));
doublep=acos(c);
doublex[6],y[6];
for(inti=0;i<6;i++)
{
x[i]=0.7*sin(p+i*PI/3)+xto;//利用弧度定义六芒星的六个顶点
y[i]=0.7*cos(p+i*PI/3)+yto;
}
SelectObject(_hdc,CreatePen(PS_SOLID,1,mColor));//设置画笔,用笔分别连接六芒星对应顶点画出星星
MoveToEx(_hdc,user_to_disp_x(xfrom),user_to_disp_y(yfrom),0);
LineTo(_hdc,user_to_disp_x(xto),user_to_disp_y(yto));
MoveToEx(_hdc,user_to_disp_x(x[0]),user_to_disp_y(y[0]),0);
LineTo(_hdc,user_to_disp_x(x[2]),user_to_disp_y(y[2]));
MoveToEx(_hdc,user_to_disp_x(x[2]),user_to_disp_y(y[2]),0);
LineTo(_hdc,user_to_disp_x(x[4]),user_to_disp_y(y[4]));
MoveToEx(_hdc,user_to_disp_x(x[4]),user_to_disp_y(y[4]),0);
LineTo(_hdc,user_to_disp_x(x[0]),user_to_disp_y(y[0]));
MoveToEx(_hdc,user_to_disp_x(x[1]),user_to_disp_y(y[1]),0);
LineTo(_hdc,user_to_disp_x(x[3]),user_to_disp_y(y[3]));
MoveToEx(_hdc,user_to_disp_x(x[3]),user_to_disp_y(y[3]),0);
LineTo(_hdc,user_to_disp_x(x[5]),user_to_disp_y(y[5]));
MoveToEx(_hdc,user_to_disp_x(x[5]),user_to_disp_y(y[5]),0);
LineTo(_hdc,user_to_disp_x(x[1]),user_to_disp_y(y[1]));
}
GraphicWindow&GraphicWindow:
:
operator<<(starslinea)
{
Starsline(a.get_start().get_x(),a.get_start().get_y(),a.get_end().get_x(),a.get_end().get_y(),a.get_color());
return*this;
}
starslinesLine(org,sEnd);sLine.SetColor((RGB(255,255,255)));
moonmlinemLine(org,mEnd);
sunhlinehLine(org,hEnd);hLine.SetColor((RGB(255,255,255)));
cwin<亮点二:
利用弧度绘制六芒星
通过一个循环找到围绕指针端点等间隔分布的六个点,再调用系统函数连线。
围绕夜空转动的五彩星星则是调用了系统时间来改变星星的位置和色彩
实现代码如下:
doublec=(yfrom-yto)/sqrt((xfrom-xto)*(xfrom-xto)+(yfrom-yto)*(yfrom-yto));
doublep=acos(c);
doublex[4],y[4];
for(inti=0;i<4;i++)
{
x[i]=0.7*sin(p+i*PI/2)+xto;//利用弧度定义
y[i]=0.7*cos(p+i*PI/2)+yto;
}
MoveToEx(_hdc,user_to_disp_x(x[0]),user_to_disp_y(y[0]),0);
LineTo(_hdc,user_to_disp_x(x[1]),user_to_disp_y(y[1]));
MoveToEx(_hdc,user_to_disp_x(x[1]),user_to_disp_y(y[1]),0);
LineTo(_hdc,user_to_disp_x(x[2]),user_to_disp_y(y[2]));
MoveToEx(_hdc,user_to_disp_x(x[2]),user_to_disp_y(y[2]),0);
LineTo(_hdc,user_to_disp_x(x[3]),user_to_disp_y(y[3]));
MoveToEx(_hdc,user_to_disp_x(x[3]),user_to_disp_y(y[3]),0);
LineTo(_hdc,user_to_disp_x(x[0]),user_to_disp_y(y[0]));
MoveToEx(_hdc,user_to_disp_x(x[1]),user_to_disp_y(y[1]),0);
LineTo(_hdc,user_to_disp_x(x[3]),user_to_disp_y(y[3]));
MoveToEx(_hdc,user_to_disp_x(x[0]),user_to_disp_y(y[0]),0);
LineTo(_hdc,user_to_disp_x(x[2]),user_to_disp_y(y[2]));
亮点三:
利用系统时间绘制围绕表盘缩进的星光
//调用系统时间,利用point类在表盘里面画星轨
radius=6-local.tm_sec%6;
for(i=0;i<12;i++)
{
x=0.9*radius*sin(PI*i/6);
y=0.9*radius*cos(PI*i/6);
PointmPoint(x,y);
pShape=&mPoint;
pShape->SetColor((RGB(255,255,255)));
cwin<}
亮点四:
利用系统时间和Point,Line,Starsline类绘制变化的星轨
//画星星
Pointorg(0,0);
doublex[8],y[8];
doublel;
l=9-local.tm_sec%9;
x[0]=0;
y[0]=l;
for(inti=1;i<8;i++)
{
x[i]=l*sin(/*PI/2+*/i*PI/4);//利用弧度定义六芒星的六个顶点
y[i]=l*cos(/*PI/2*/i*PI/4);
}
其中l是随时间以9为周期变化的数值,然后再调用相应的类绘图
四、运行结果分析
运行效果:
XQY的绘图设计菜单栏一:
【月黑见渔灯,孤光一点萤】星轨时钟
时钟调用了系统时间,分针秒针时针分别指向对应的位置,秒针尽头一颗六芒星随之转动,分针尽头一轮弯月随之转动,时针尽头则是一个小小的铅垂牵引着它。
同时,在渐变的紫色调表盘上有均匀分布的星光,随时间一圈一圈闪现在不同颜色的表盘上。
浅紫色的夜空背景下,还有一颗颜色按七原色赤橙黄绿青蓝紫变化的星星围绕表盘转动。
XQY的绘图设计菜单栏二:
【微微风簇浪,散作满河星】成长星轨
夜空背景下,一颗象牙白的多角星星正在一步一步绽放她的光芒,时间每过去一秒,这个星星就要彻底地变化一次形状。
而每一个角的顶点,又幻化成无数小小六芒星。
一颗五彩的星星围绕成长的星轨转动
五、遇到的难题与解决方法
难题一:
如何填充渐变表盘的颜色?
解决方式是在ellipse函数中预置一个笔刷,就可以根据颜色填充了,不过要注意最后要让笔刷复位
难题二:
如何画出随时间变化的星光?
见亮点三
难题三:
如何画弧线图类月亮?
上网搜索后找到画弧线的系统函数Arc,根据端点坐标计算出所需参数即可
难题四:
如何使动态星星的颜色发生周期性变化?
利用ifelse语句判断时间与7取余的值,每次设置一个不同颜色
六、总结
本次课题相对上次的课题难度加大不少,特别是要运用以前从未接触的WindowsAPI平台,还需要复习大一学习的c++内容,查阅不少资料。
在同学们一次又一次的讨论摸索下,渐渐摸索出来了一步有一步。
通过这次API的编程,让我又学会了一种新的编译办法。
相比之下,觉得API界面比控制台界面更加美观大方。
在学习编程过程中,锻炼了自己独立思考和解决问题的能力得,也会影响到以后各科的学习,甚至是终生有益。
五、参考文献
[1]徐惠民等,C++高级语言程序设计案例与实践辅导,北京:
人民邮电出版社,2012
[2]徐雅静等,数据结构与stl,北京:
北京邮电大学,2011
[3]徐惠名等,C++高级语言程序设计,北京,人民邮电出版社,2012