时钟运动
问题描述
在VC6.0的MFC中画一个钟表,有时针、分针、秒针,并实现时针、分针、秒针的运动。
最终部分静态效果图如下:
操作详细过程
1、新建
1、打开VC6.0,点击屏幕左上角“文件(F)”,选择“新建(N)… Ctrl_N”,如下图所示。
2、在弹出的对话框中,选择“工程 >> MFC AppWizard(exe)”,选择创建工程的位置并给工程命名,点击“确定”,如下图所示。
3、选择“单文档(S)”,点击“完成”,点击“确定”,如下图所示。
2、添加成员函数
4、在类视图中,鼠标选中右击,选择“Add Member Function…”,添加成员函数DrawMyClock(),DrawLine(),DrawHourPointer(),DrawMinutePointer(),DrawSecondPointer(),如下图所示。
5、在DrawMyClock()函数里画钟盘,如下图所示。
void CExercise4View::DrawMyClock(CDC *pDC, MyClock clock)
{
POINT center;
POINT bgnP1,endP2;
int r;
int ct = 0; //钟盘上的数字(0-11),初始化为0
int i;
CPen pen;
CPen *pOldPen;
center.x = clock.center.x;
center.y = clock.center.y;
r = clock.r; //画时钟外圆
pDC->Ellipse(clock.center.x - r,clock.center.y - r,clock.center.x + r,clock.center.y + r);
//画时钟圆心
pen.CreatePen(PS_SOLID,10,RGB(0,0,0));
pOldPen = pDC->SelectObject(&pen);
pDC->SetPixel(center,RGB(0,0,0));
pDC->Ellipse(center.x - 2,center.y - 2,center.x + 2,center.y + 2);
pDC->SelectObject(pOldPen);
bgnP1.x = center.x;
bgnP1.y = center.y - r;
endP2.x = center.x;
endP2.y = center.y - r + ceil(r/10);
DrawLine(pDC,bgnP1,endP2);
for(i = 0; i < 60; i++) //画表盘上60个刻度
{
float angle;
angle = i* 6; //每个刻度是6度的角
angle = angle * PI/180;
bgnP1.x = center.x + r * sin(angle);
bgnP1.y = center.y - r * cos(angle);
endP2.x = center.x + 0.9 * r * sin(angle);
endP2.y = center.y - 0.9 * r * cos(angle);
if((i % 5) == 0) //小时刻度画粗点
{
CPen pen;
CPen *pOldPen;
CString str;
str.Format("%d",ct++); //ct是大的刻度数字(0-11),已经初始化为0
pen.CreatePen(PS_DOT,6,RGB(0,0,0));
pOldPen = pDC->SelectObject(&pen);
DrawLine(pDC,bgnP1,endP2);
pDC->TextOut(endP2.x,endP2.y,str);
pDC->SelectObject(pOldPen);
}
DrawLine(pDC,bgnP1,endP2);
}
}
3、定义时钟对象
6、定义时钟对象,如下图所示。
typedef struct
{
POINT center; //定义时钟的中心
int r; //定义时钟的半径
int h,m,s; //定义时,分,秒
}MyClock; //定义时钟对象
7、在DrawLine()中添加代码,如下所示。
void CExercise4View::DrawLine(CDC *pDC, POINT p1, POINT p2)
{
pDC->MoveTo(p1);
pDC->LineTo(p2);
}
4、画时针、分针、秒针
8、画时针,如下图所示。
void CExercise4View::DrawHourPointer(CDC *pDC, MyClock clock)
{
POINT p1,p2; //定义时针的两个端点位置
float angle; //角度
int s,m,h; //秒,分,时
CPen pen;
CPen *pOldPen;
s = clock.s;
m = clock.m;
h = clock.h;
angle = h*30.0*PI/180 + m*30.0*PI/(60*180) + m*30.0*PI/(3600*180);
/*计算当前时针的倾角,单位弧度,由时针、分针决定,一个小时是30度的角(360/12=30)*/
pen.CreatePen(PS_SOLID,9,RGB(0,0,0)); //时针9个像素宽度画
pOldPen = pDC->SelectObject(&pen);
p1.x = clock.center.x;
p1.y = clock.center.y; //时针的起始位置
p2.x = clock.center.x + 0.5*clock.r*sin(angle); // 时针长为半径的0.5倍
p2.y = clock.center.y - 0.5*clock.r*cos(angle);
DrawLine(pDC,p1,p2);
pDC->SelectObject(pOldPen); //恢复原来的画笔
}
9、画分针,如下图所示。
void CExercise4View::DrawMinutePointer(CDC *pDC, MyClock clock)
{
POINT p1,p2; //定义分针的两个端点位置
float angle;
int s,m;
CPen pen;
CPen *pOldPen;
s = clock.s;
m = clock.m;
angle = m*6.0*PI/180 + s*6.0*PI/(60*180);
/*计算当前分针的倾角,单位弧度,由分针、秒针决定,一分钟是6度的角*/
pen.CreatePen(PS_SOLID,4,RGB(0,0,0)); //分针4个像素宽度画
pOldPen = pDC->SelectObject(&pen);
p1.x = clock.center.x;
p1.y = clock.center.y; //分针的起始位置
p2.x = clock.center.x + 0.7*clock.r*sin(angle);
p2.y = clock.center.y - 0.7*clock.r*cos(angle);
DrawLine(pDC,p1,p2);
pDC->SelectObject(pOldPen); //恢复原来的画笔
}
10、画秒针,如下图所示。
void CExercise4View::DrawSecondPointer(CDC *pDC, MyClock clock)
{
POINT p1,p2; //定义秒针的两个端点位置
float angle;
int s;
CPen pen;
CPen *pOldPen;
s = clock.s;
angle = s*6.0*PI/180;
pen.CreatePen(PS_SOLID,2,RGB(255,0,0)); //分针2个像素宽度画
pOldPen = pDC->SelectObject(&pen);
p1.x = clock.center.x;
p1.y = clock.center.y;
p2.x = clock.center.x + 0.9*clock.r*sin(angle);
p2.y = clock.center.y - 0.9*clock.r*cos(angle);
DrawLine(pDC,p1,p2);
pDC->SelectObject(pOldPen); //恢复原来的画笔
}
5、新建菜单
11、点击左下角中间的资源视图“ResourceView”,选择“Menu”新建菜单。双击“帮助(H)”右侧虚线框,在“标明©:”里添加“动画时钟”;再双击“动画时钟”下面的虚线框,添加内容如下图所示。
12、右击“走时”、“停止”、“设置时钟”,选择“建立类向导…”,如下图所示。
6、插入对话框
13、添加对话框。鼠标右击“Dialog”,选择“插入Dialog”,并对其进行编辑,如下图所示。
14、右击选择“属性”,对其重命名为IDD_Dlg_SetPara,如下图所示。
15、建立一个IDD_Dlg_SetPara所对应的的类,取类名CDlg_SetPara,如下图所示。
7、对话框和类的绑定
16、将编辑框所对应的内容和刚刚上面建立的类进行绑定。在Member Variables中添加成员变量,如下图所示。
17、在OnMSetPara()中添加代码,如下图所示。
void CExercise4View::OnMSetPara()
{
// TODO: Add your command handler code here
CDlg_SetPara dlgsetpara;
dlgsetpara.m_h = m_clock.h;
dlgsetpara.m_m = m_clock.m;
dlgsetpara.m_s = m_clock.s;
UpdateData(false);
if(dlgsetpara.DoModal() == IDOK)
{
m_clock.h = dlgsetpara.m_h;
m_clock.m = dlgsetpara.m_m;
m_clock.s = dlgsetpara.m_s;
Invalidate(true);
}
}
18、添加OnInitialUpdate()函数,对时钟进行初始化,如下图所示。
void CExercise4View::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
m_clock.h = 6;
m_clock.m = 22;
m_clock.s = 0;
}
19、添加成员函数ClockRun(),如下图所示。
void CExercise4View::ClockRun(MyClock &clock)
{
clock.s++;
if(60 == clock.s)
{
clock.s = 0;
clock.m++;
if(60 == clock.m)
{
clock.m = 0;
clock.h++;
if(12 == clock.h)
{
clock.h = 0;
}
}
} //12小时制
}
20、添加消息句柄,调用系统时钟(WM_TIMER), 如下图所示。
21、在OnTimer()中调用ClockRun()函数,如下图所示。
void CExercise4View::OnMStart()
{
// TODO: Add your command handler code here
SetTimer(1,1000,NULL); //1000ms = 1s,即1s中断一次
}
void CExercise4View::OnMStop()
{
// TODO: Add your command handler code here
KillTimer(1);
}
void CExercise4View::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
ClockRun(m_clock);
Invalidate(true);
CView::OnTimer(nIDEvent);
}
8、运行结果
22、运行结果如下图所示。
按“走时”,时钟会运动;按“停止”,时钟会停止;按“设置时针”,会弹出对话框,进行时间设定。并且时钟会随着窗口的变化而相应的变大或变小。