vs2008简易闹钟制作

第一次写博客,就把这第一次献给亲爱的MFC吧~作为一个MFC初学者,我懂得各位同是初学者的同学朋友们的不易,网上关于从MFC 0基础开始讲解MFC的书籍并不多,在这里就对我练习的这个小程序尽可能地做详细地讲解,请各同学朋友多多指点,相互学习,高手勿喷~

最终小程序的运行结果如下图所示(时钟各个点的位置的数学算法可以自己用正余弦定理计算一下或者去参考一下网上其他人计算好的):



好了,上正题,笔者这个MFC小程序是用VS2012写成的,于是乎我们第一步打开VS2012,依次点击“文件->新建->项目”以此来新建一个项目,并选择MFC的模板,这里我们就将项目名称命名为“ClockShower”:



在弹出来的向导中,我们先别急点击“完成”,点击“下一步”进入下一界面,在应用程序类型中,我们选择应用程序类型为“单个文档”,其他的可以保持默认:



再不断地点击“下一步”(保持默认配置就行了),直到出现“生成的类”这个向导界面,我们选中CClockShowerView,在“基类”中选择CFormView,这样CClockShowerView就继承了允许对话框控件拖动到View视图的特性,我们就可以在单文档程序中使用对话框的控件了:



好了,准备工作做好了,点击“完成”,生成项目。

项目生成好后,我们首先运行一下,得到如下界面:



在这里向同学朋友们说明一下View的客户端区域和MainFrm显示的范围界限,因为在View中的绘图和在MainFrame中的绘图得到的效果并不一样,可以自己尝试一下:



在左下方找到资源视图(或者点击菜单上的“视图->资源视图”),打开“IDD_CLOCKSHOWER_FORM”,这个就是在View视图中显示的对话框了,在右边的工具箱->对话框编辑器中,我们可以看到此时项目允许我们拖动各种控件(如果点击了工具箱后,仍没有看到控件的列表,请点击工具箱,然后在工具箱选项卡中的空白处右键->重置工具箱,等vs重置工具箱后就可以看到了),我们选择“Month Calendar Control”这个控件并拖到对话框上,然后再运行一遍程序,怎么样,是不是看到了一个日历,有点感觉了吧:



对于这个日历的控件,在这里我们不需要对它做些什么,只需要它摆在一旁做衬托就行,接下来我们找到“Menu->IDR_MAINFRAME”,这就是单文档程序中的主菜单窗口了,我们菜单右边的“请在此键入”中输入我们自定义的菜单选项和子菜单选项“时钟日历程序”和“开始/停止”:



好了,添加菜单项完毕之后,得为菜单项添加消息处理程序或者COMMAND消息,否则这个菜单项就会变灰,无法使用。于是我们对“开始/停止”右键->添加事件处理程序,在弹出来的对话框中首先选择COMMAND消息类型,在右边的“类列表”中选择CMainFrame(或者选择CClockShowerView也是可以的,并且在View中绘制要合理一些,这里我们就选在CMainFrame来讲解了),然后点击“添加编辑”这样在MainFrm.cpp中我们可以看到多了一个CMainFrame::OnStartorstopControl()



同理我们再为“开始/停止”这个子菜单项添加UPDATE_COMMAND_UI消息处理程序,添加完毕后,我们在MainFrm.h中的CMainFrame类中添加私有变量m_Start,并在MainFrm.cpp的构造函数中初始化m_Start = TRUE,然后在刚才的两个COMMAND消息函数中添加代码:

[cpp]  view plain  copy
  1. void CMainFrame::OnStartorstopControl()  
  2. {  
  3.     // TODO: 在此添加命令处理程序代码  
  4.     if(m_Start)  
  5.     {  
  6.         //通过关闭定时器停止运行时钟程序  
  7.         KillTimer(1);  
  8.     }  
  9.     else   
  10.     {  
  11.         //通过打开定时器开始运行时钟程序  
  12.         SetTimer(1,1000,NULL);  
  13.     }  
  14.     //绘图使能标识取反     
  15.     m_Start = !m_Start;   
  16. }  
  17.   
  18.   
  19. void CMainFrame::OnUpdateStartorstopControl(CCmdUI *pCmdUI)  
  20. {  
  21.     // TODO: 在此添加命令更新用户界面处理程序代码  
  22.     //根据m_bDraw的值设置是否选中     
  23.     pCmdUI->SetCheck(m_Start);   
  24. }  


选择“类视图”,找到并选中CMainFrame这个类,右键->属性或者在右边面板上找到“属性”,在属性面板上找到“消息”,然后再找到“WM_TIMER”这个消息,也就是定时器的消息,点击“<Add OnTimer>”,就会看到vs为我们在CMainFrame类中建好了一个定时器的消息处理函数OnTimer,前面的SetTimer(1,1000,NULL)就是让程序每隔1秒执行一次OnTimer函数:



好了,消息处理函数的准备工作也做完了,我们就开始来建类(为什么要建类?规范代码,便于维护,易于阅读,老师说你懂的 :) )

这里我们就建两个简单的类就行了,一个是时钟类CClock,一个是针类(时针、分针、秒针)CNeedle,在“解决方案”视图中我们右键“头文件”->添加->类来新建这两个类


写好类名后直接点击“完成”就可以了



同理添加CNeedle这个类,完成后会发现我们的“头文件”和“源文件”中分别多了“Clock.h、Needle.h”和“Clock.cpp、Needle.cpp”这四个文件,其中.h文件是用于定义一个类或者其他公有的结构例如枚举、结构体等,我们修改Clock.h和Needle.h中的类,添加代码:


Clock.h

[cpp]  view plain  copy
  1. #pragma once  
  2. #include "Needle.h"  
  3. //时钟类  
  4. class CClock  
  5. {  
  6. public:  
  7.     CClock(void);  
  8.     ~CClock(void);  
  9.     //绘制时钟周围的大圈  
  10.     void DrawCircle(CDC *pDC,int x1,int y1,int x2,int y2);  
  11.     //绘制时钟上面的各个点  
  12.     void Draw(CDC *pDC,int nMoveToX,int nMoveToY,int nDrawX,int nDrawY);  
  13.     //创建画笔  
  14.     void CreatePen(int index,int nPenStyle,int nWidth,COLORREF color);  
  15.     //获得圆圈的画笔  
  16.     CPen *GetCirclePen();  
  17.     //获得关键点的画笔  
  18.     CPen *GetKeyPointPen();  
  19.     //获得其他点的画笔  
  20.     CPen *GetPointPen();  
  21.     //获取时针  
  22.     CNeedle *GetHourNeedle();  
  23.     //获取分针  
  24.     CNeedle *GetMinuteNeedle();  
  25.     //获取秒针  
  26.     CNeedle *GetSecondNeedle();  
  27.   
  28. private:  
  29.     //时针  
  30.     CNeedle *m_HourNeedle;  
  31.     //分针  
  32.     CNeedle *m_MinuteNeedle;  
  33.     //秒针  
  34.     CNeedle *m_SecondNeedle;  
  35.     //外部圆的画笔  
  36.     CPen m_CirclePen;  
  37.     //关键点的画笔  
  38.     CPen m_KeyPointPen;  
  39.     //其他点的画笔  
  40.     CPen m_PointPen;  
  41. };  

Needle.h

[cpp]  view plain  copy
  1. #pragma once  
  2. //针类  
  3. class CNeedle  
  4. {  
  5. public:  
  6.     CNeedle(void);  
  7.     ~CNeedle(void);  
  8.   
  9.     //创建画笔  
  10.     void CreatePen(int nPenStyle,int nWidth,COLORREF color);  
  11.     //绘制自己  
  12.     void Draw(CDC *pDC,int moveToX,int moveToY,int drawX,int drawY);  
  13.     //获取自己的画笔  
  14.     CPen *GetPen();  
  15.   
  16. public:  
  17.     //画笔  
  18.     CPen m_Pen;  
  19. };  

然后在他们各自的cpp文件中写入实现方法:


Clock.cpp

[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2. #include "Clock.h"  
  3. #include "Needle.h"  
  4.   
  5. CClock::CClock(void)  
  6. {  
  7.     //构造时针、分针、秒针  
  8.     m_HourNeedle = new CNeedle();  
  9.     m_MinuteNeedle  = new CNeedle();  
  10.     m_SecondNeedle = new CNeedle();  
  11. }  
  12.   
  13.   
  14. CClock::~CClock(void)  
  15. {  
  16.     //释放成员  
  17.     delete(m_HourNeedle);  
  18.     delete(m_MinuteNeedle);  
  19.     delete(m_SecondNeedle);  
  20. }  
  21.   
  22. //绘制时钟周围的大圈  
  23. void CClock::DrawCircle(CDC *pDC,int x1,int y1,int x2,int y2)  
  24. {  
  25.     pDC->Ellipse(x1,y1,x2,y2);  
  26. }  
  27.   
  28. //绘制时钟上面的各个点  
  29. void CClock::Draw(CDC *pDC,int nMoveToX,int nMoveToY,int nDrawX,int nDrawY)  
  30. {  
  31.     //将绘点移动到根点  
  32.     pDC->MoveTo(nMoveToX,nMoveToY);  
  33.     //连线绘制  
  34.     pDC->LineTo(nDrawX,nDrawY);  
  35. }  
  36.   
  37. //创建画笔,0绘制圆圈,1绘制关键点,2绘制其他点  
  38. void CClock::CreatePen(int index,int nPenStyle,int nWidth,COLORREF color)  
  39. {  
  40.     if(index == 0)  
  41.         m_CirclePen.CreatePen(nPenStyle,nWidth,color);  
  42.     else if(index == 1)  
  43.         m_KeyPointPen.CreatePen(nPenStyle,nWidth,color);  
  44.     else   
  45.         m_PointPen.CreatePen(nPenStyle,nWidth,color);  
  46. }  
  47.   
  48. //获得画笔  
  49. CPen *CClock::GetCirclePen()  
  50. {  
  51.     return &m_CirclePen;  
  52. }  
  53.   
  54. //获得关键点的画笔  
  55. CPen *CClock::GetKeyPointPen()  
  56. {  
  57.     return &m_KeyPointPen;  
  58. }  
  59.   
  60. //获得其他点的画笔  
  61. CPen *CClock::GetPointPen()  
  62. {  
  63.     return &m_PointPen;  
  64. }  
  65.   
  66. //获取时针  
  67. CNeedle *CClock::GetHourNeedle()  
  68. {  
  69.     return m_HourNeedle;  
  70. }  
  71.   
  72. //获取分针  
  73. CNeedle *CClock::GetMinuteNeedle()  
  74. {  
  75.     return m_MinuteNeedle;  
  76. }  
  77.   
  78. //获取秒针  
  79. CNeedle *CClock::GetSecondNeedle()  
  80. {  
  81.     return m_SecondNeedle;  
  82. }  

Needle.cpp

[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2. #include "Needle.h"  
  3.   
  4.   
  5. CNeedle::CNeedle(void)  
  6. {  
  7. }  
  8.   
  9.   
  10. CNeedle::~CNeedle(void)  
  11. {  
  12. }  
  13.   
  14. void CNeedle::CreatePen(int nPenStyle,int nWidth,COLORREF color)  
  15. {  
  16.     m_Pen.CreatePen(nPenStyle,nWidth,color);  
  17. }  
  18.   
  19. void CNeedle::Draw(CDC *pDC,int moveToX,int moveToY,int drawX,int drawY)  
  20. {  
  21.     //移动到目标根点  
  22.     pDC->MoveTo(moveToX,moveToY);  
  23.     //连线形成绘制  
  24.     pDC->LineTo(drawX,drawY);  
  25. }  
  26.   
  27. CPen *CNeedle::GetPen()  
  28. {  
  29.     return &m_Pen;  
  30. }  

OK,到这里,类已经建完,还得去实例化它们并且调用才能看到效果,于是乎我们又转到MainFrm.h中为CMainFrame类添加私有成员变量,代码如下(包括了之前的m_Start在内了),记得要加上#include “Clock.h”,否则识别不了CClock这个类:

[cpp]  view plain  copy
  1. private:  
  2.   
  3.     //控制菜单项的标识  
  4.     bool m_Start;  
  5.     //时钟  
  6.     CClock *m_Clock;  
  7.     //当前系统时间  
  8.     CTime m_CurrentTime;  
  9.     //当前的小时  
  10.     int m_Hour;  
  11.     //当前的秒  
  12.     int m_Second;  
  13.     //当前的分  
  14.     int m_Minute;  

同时为了让代码结构看起来更工整一些,我们还是创建几个方法分别把各种的实现给封装起来,尽量避免所有代码都写在一个函数里,于是我们在MainFrm.h中继续添加方法,代码如下:

[cpp]  view plain  copy
  1. public:  
  2.     //输出Title以及时钟的文字  
  3.     void PrintText(CDC *pDc,int quarterWidth,int threeQuartersWidth,int quarterHeight,int threeQuartersHeight,int midWidth,int midHeight);  
  4.     //绘制时钟的图形  
  5.     void DrawClock(CDC *pDc,int quarterWidth,int threeQuartersWidth,int quarterHeight,int threeQuartersHeight,int midWidth,int midHeight);  
  6.     //绘制日历的所有内容  
  7.     void DrawCalendar(CDC *pDc,CRect rect);  
  8.     //初始化数据  
  9.     void Init();  

然后在MainFrm.cpp的CMainFrame这个类中写上这几个方法的具体实现(也就是实现时钟和日历的绘制的核心代码,代码我基本都添加了注释了的,同学们朋友们如果看不太明白的话给我留言哈,能帮到的一定帮忙~)

[cpp]  view plain  copy
  1. //初始化数据  
  2. void CMainFrame::Init()  
  3. {  
  4.     m_Start = FALSE;  
  5.     //构造时钟  
  6.     m_Clock = new CClock();  
  7.     //构建时钟外圆的画笔  
  8.     m_Clock->CreatePen(0,PS_SOLID,3,RGB(255,255,0));  
  9.     //构建时钟关键点的画笔  
  10.     m_Clock->CreatePen(1,PS_SOLID,3,RGB(0,0,0));  
  11.     //构建时钟其他点的画笔  
  12.     m_Clock->CreatePen(2,PS_SOLID,2,RGB(0,0,0));  
  13.     //构建秒针的画笔  
  14.     m_Clock->GetSecondNeedle()->CreatePen(PS_SOLID,2,RGB(255,0,0));  
  15.     //构建分针的画笔  
  16.     m_Clock->GetMinuteNeedle()->CreatePen(PS_SOLID,4,RGB(0,0,255));  
  17.     //构建时针的画笔  
  18.     m_Clock->GetHourNeedle()->CreatePen(PS_SOLID,6,RGB(0,255,0));  
  19. }  
  20.   
  21. //输出界面中的文字,根据六个方向确定时钟和文字的坐标  
  22. void CMainFrame::PrintText(CDC *pDc,int quarterWidth,int threeQuartersWidth,int quarterHeight,int threeQuartersHeight,int midWidth,int midHeight)  
  23. {  
  24.     //获取当前的系统时间,传递给m_CurrentTime  
  25.     this->m_CurrentTime = CTime::GetCurrentTime();  
  26.     //格式化时间字符串为时分秒  
  27.     CString str = this->m_CurrentTime.Format("%H:%M:%S");  
  28.   
  29.     //设置标题字体为微软雅黑  
  30.     CFont titleFont;  
  31.     titleFont.CreateFontW(35,15,0,0, FW_NORMAL,false ,false,false,  
  32.                                  DEFAULT_CHARSET,OUT_DEVICE_PRECIS ,CLIP_DEFAULT_PRECIS,  
  33.                                  DEFAULT_QUALITY,DEFAULT_PITCH ,_T("微软雅黑"));  
  34.     //选择新建的字体  
  35.     pDc->SelectObject(&titleFont);  
  36.   
  37.     //输出标题  
  38.     pDc->TextOutW(midWidth-180,40,_T("欢迎使用时钟日历模拟程序"));  
  39.   
  40.   
  41.     //设置字体为微软雅黑  
  42.     CFont font;  
  43.     font.CreateFontW(20,7,0,0, FW_NORMAL,false ,false,false,  
  44.                                  DEFAULT_CHARSET,OUT_DEVICE_PRECIS ,CLIP_DEFAULT_PRECIS,  
  45.                                  DEFAULT_QUALITY,DEFAULT_PITCH ,_T("微软雅黑"));  
  46.     //选择新建的字体  
  47.     pDc->SelectObject(&font);  
  48.   
  49.     //输出时间的文字  
  50.         pDc->TextOutW(midWidth-30,midHeight+quarterHeight+20,str);  
  51.         //输出星期几  
  52.         CString clockWeek(_T("星期"));  
  53.         int week = m_CurrentTime.GetDayOfWeek();  
  54.         CString weekStr;  
  55.         switch (week)  
  56.         {  
  57.         case 1:weekStr += _T("天");clockWeek+=weekStr;break;  
  58.         case 2:weekStr += _T("一");clockWeek+=weekStr;break;  
  59.         case 3:weekStr += _T("二");clockWeek+=weekStr;break;  
  60.         case 4:weekStr += _T("三");clockWeek+=weekStr;break;  
  61.         case 5:weekStr += _T("四");clockWeek+=weekStr;break;  
  62.         case 6:weekStr += _T("五");clockWeek+=weekStr;break;  
  63.         case 7:weekStr += _T("六");clockWeek+=weekStr;break;  
  64.         default:  
  65.             break;  
  66.         }  
  67.         pDc->TextOutW(midWidth-25,midHeight+quarterHeight+40,clockWeek);  
  68. }  
  69.   
  70. //绘制时钟,根据六个方向确定时钟坐标  
  71. void CMainFrame::DrawClock(CDC *pDc,int quarterWidth,int threeQuartersWidth,int quarterHeight,int threeQuartersHeight,int midWidth,int midHeight)  
  72. {  
  73.     //更换画外部圆圈的画笔并储存系统画笔  
  74.         CPen *pOldPen = pDc->SelectObject(m_Clock->GetCirclePen());  
  75.         //画圆  
  76.         m_Clock->DrawCircle(pDc,midWidth-quarterHeight,quarterHeight,midWidth+quarterHeight,threeQuartersHeight);  
  77.         //更改成绘制关键点的画笔  
  78.         pDc->SelectObject(m_Clock->GetKeyPointPen());  
  79.         //画12,将画笔移至客户区中间宽度,四分之一的高度的地方,然后y轴向下延伸20个单位,其他的同理  
  80.         m_Clock->Draw(pDc,midWidth,quarterHeight,midWidth,quarterHeight+20);  
  81.         //画6  
  82.         m_Clock->Draw(pDc,midWidth,threeQuartersHeight,midWidth,threeQuartersHeight-20);  
  83.         //画3  
  84.         m_Clock->Draw(pDc,midWidth+quarterHeight,midHeight,midWidth+quarterHeight-20,midHeight);  
  85.         //画9  
  86.         m_Clock->Draw(pDc,midWidth-quarterHeight,midHeight,midWidth-quarterHeight+20,midHeight);  
  87.         //画1  
  88.         m_Clock->Draw(pDc,midWidth+quarterHeight/2,midHeight-(int)(0.866*(double)quarterHeight),midWidth+quarterHeight/2-10,midHeight-(int)(0.866*(double)quarterHeight)+17);  
  89.         //画7  
  90.         m_Clock->Draw(pDc,midWidth-quarterHeight/2,midHeight+(int)(0.866*(double)quarterHeight),midWidth-quarterHeight/2+10,midHeight+(int)(0.866*(double)quarterHeight)-17);  
  91.         //画2  
  92.         m_Clock->Draw(pDc,midWidth+(int)(0.866*(double)quarterHeight),midHeight-quarterHeight/2,midWidth+(int)(0.866*(double)quarterHeight)-17,midHeight-quarterHeight/2+10);  
  93.         //画8  
  94.         m_Clock->Draw(pDc,midWidth-(int)(0.866*(double)quarterHeight),midHeight+quarterHeight/2,midWidth-(int)(0.866*(double)quarterHeight)+17,midHeight+quarterHeight/2-10);  
  95.         //画4  
  96.         m_Clock->Draw(pDc,midWidth+(int)(0.866*(double)quarterHeight),midHeight+quarterHeight/2,midWidth+(int)(0.866*(double)quarterHeight)-17,midHeight+quarterHeight/2-10);  
  97.         //画10  
  98.         m_Clock->Draw(pDc,midWidth-(int)(0.866*(double)quarterHeight),midHeight-quarterHeight/2,midWidth-(int)(0.866*(double)quarterHeight)+17,midHeight-quarterHeight/2+10);  
  99.         //画5  
  100.         m_Clock->Draw(pDc,midWidth+quarterHeight/2,midHeight+(int)(0.866*(double)quarterHeight),midWidth+quarterHeight/2-10,midHeight+(int)(0.866*(double)quarterHeight)-17);  
  101.         //画11  
  102.         m_Clock->Draw(pDc,midWidth-quarterHeight/2,midHeight-(int)(0.866*(double)quarterHeight),midWidth-quarterHeight/2+10,midHeight-(int)(0.866*(double)quarterHeight)+17);  
  103.   
  104.         //更换回系统画笔  
  105.         pDc->SelectObject(pOldPen);  
  106.   
  107.         //画其他点  
  108.         for(int i=0;i<60;i++)  
  109.         {  
  110.             m_Clock->Draw(pDc,midWidth+(int)(quarterHeight*sin(i*PI/30)),midHeight-(int)(quarterHeight*cos(i*PI/30)),midWidth+(int)(quarterHeight*0.87*sin(i*PI/30)),midHeight-(int)(quarterHeight*0.87*cos(i*PI/30)));  
  111.         }  
  112.   
  113.         //更改成秒针画笔  
  114.         pDc->SelectObject(m_Clock->GetSecondNeedle()->GetPen());  
  115.         //pDc->SelectObject(&penS);  
  116.         //画秒针  
  117.         m_Clock->GetSecondNeedle()->Draw(pDc,midWidth-(int)(quarterHeight*0.3*sin(this->m_Second*PI/30)),midHeight+(int)(quarterHeight*0.3*cos(this->m_Second*PI/30)),midWidth+(int)(quarterHeight*0.8*sin(this->m_Second*PI/30)),midHeight-(int)(quarterHeight*0.8*cos(this->m_Second*PI/30)));  
  118.         //更改成分针画笔  
  119.         pDc->SelectObject(m_Clock->GetMinuteNeedle()->GetPen());  
  120.         //画分针  
  121.         m_Clock->GetMinuteNeedle()->Draw(pDc,midWidth,midHeight,midWidth+(int)(quarterHeight*0.8*sin(2*PI*(this->m_Minute/60.0+this->m_Second/3600.0))),midHeight-(int)(quarterHeight*0.8*cos(2*PI*(this->m_Minute/60.0+this->m_Second/3600.0))));  
  122.         //更改画笔  
  123.         pDc->SelectObject(m_Clock->GetHourNeedle()->GetPen());  
  124.         //画时针  
  125.         m_Clock->GetHourNeedle()->Draw(pDc,midWidth,midHeight,midWidth+(int)(quarterHeight*0.6*sin(2*PI*(this->m_Hour/12.0+this->m_Minute/720.0))),midHeight-(int)(quarterHeight*0.6*cos(2*PI*(this->m_Hour/12.0+this->m_Minute/720.0))));  
  126.   
  127.         //换回系统画笔  
  128.         pDc->SelectObject(pOldPen);  
  129. }  
  130.   
  131. //绘制日历的所有内容  
  132. void CMainFrame::DrawCalendar(CDC *pDc,CRect rect)  
  133. {  
  134.     //-----------------绘制日历矩形框和数字  
  135.           
  136.   
  137.         //日历矩形框的左边界就是三分之二的客户区宽度  
  138.         int calendarLeft = rect.Width()/3*2;  
  139.         //日历矩形框的顶部边界就是四分之一的客户区高度  
  140.         int calendarTop = rect.Height()/4;  
  141.         //日历矩形框的右边界就是客户区的最右边  
  142.         int calendarRight = rect.Width();  
  143.         //日历矩形框的底部边界就是客户区的四分之三的高度  
  144.         int calendarButtom = rect.Height()/4*3;  
  145.   
  146.         //绘制矩形框  
  147.         pDc->Rectangle(calendarLeft,calendarTop,calendarRight,calendarButtom);  
  148.   
  149.         /* 
  150.         *日历矩形框的高度均分为8部分,宽度均分为7部分 
  151.         */  
  152.         int partWidth = (calendarRight-calendarLeft)/7;  
  153.         int partHeight = (calendarButtom-calendarTop)/8;  
  154.   
  155.         int year = m_CurrentTime.GetYear();  
  156.         CString head;  
  157.         //int转cstring  
  158.         head.Format(TEXT("%d"),year);  
  159.         head+=_T("年");  
  160.         int month = m_CurrentTime.GetMonth();  
  161.         CString headPart;  
  162.         headPart.Format(TEXT("%d"),month);  
  163.         head+=headPart+_T("月");  
  164.   
  165.         //一周的第一天为星期天,GetDayOfWeek为1,依次类推  
  166.         //CString cc;  
  167.         int dayOfWeak = m_CurrentTime.GetDayOfWeek();  
  168.         //int dayOfWeak = m_CurrentTime.GetDay();  
  169.         //cc.Format(TEXT("%d"),dayOfWeak);  
  170.         //head+=_T("星期")+cc;  
  171.   
  172.         //在日历矩形框中顶部绘制年月  
  173.         pDc->TextOutW(calendarLeft-20+(calendarRight-calendarLeft)/2-10,calendarTop+10,head);  
  174.   
  175.   
  176.         //设置字体颜色  
  177.         pDc->SetTextColor(RGB (125,0,255));  
  178.   
  179.         //在日历矩形框中绘制星期  
  180.         pDc->TextOutW(calendarLeft+5,calendarTop+partHeight*1,_T("周日"));  
  181.         pDc->TextOutW(calendarLeft+5+partWidth,calendarTop+partHeight*1,_T("周一"));  
  182.         pDc->TextOutW(calendarLeft+5+partWidth*2,calendarTop+partHeight*1,_T("周二"));  
  183.         pDc->TextOutW(calendarLeft+5+partWidth*3,calendarTop+partHeight*1,_T("周三"));  
  184.         pDc->TextOutW(calendarLeft+5+partWidth*4,calendarTop+partHeight*1,_T("周四"));  
  185.         pDc->TextOutW(calendarLeft+5+partWidth*5,calendarTop+partHeight*1,_T("周五"));  
  186.         pDc->TextOutW(calendarLeft+5+partWidth*6,calendarTop+partHeight*1,_T("周六"));  
  187.   
  188.         //设置字体颜色  
  189.         pDc->SetTextColor(RGB (0,0,0));  
  190.   
  191.         //在日历矩形框中绘制具体天数的日期  
  192.         //当前是几号  
  193.         int nowDay = m_CurrentTime.GetDay();  
  194.         //当前天数的备份  
  195.         int nowDayBack = nowDay;  
  196.         //当前是星期几  
  197.         int nowWeak = m_CurrentTime.GetDayOfWeek();  
  198.   
  199.         //计算当前天数应在的行数  
  200.         int row;  
  201.         //默认是在第一行  
  202.         row = 1;  
  203.         if((nowDay - nowWeak)>=0)  
  204.         {  
  205.             row = (nowDay-nowWeak)/7+1;  
  206.   
  207.             if((nowDay-nowWeak)%7 != 0)  
  208.             {  
  209.                 row++;  
  210.             }  
  211.         }  
  212.           
  213.   
  214.         //行号的备份  
  215.         int rowBack = row;  
  216.           
  217.         //更换画笔  
  218.         CPen *pOldPen = pDc->SelectObject(m_Clock->GetSecondNeedle()->GetPen());  
  219.   
  220.         //圈出当前天数的日期  
  221.         pDc->Ellipse(calendarLeft+partWidth*(nowWeak-1),calendarTop+partHeight*(row+1),calendarLeft+partWidth*(nowWeak),calendarTop+partHeight*(row+2));  
  222.   
  223.         //换回系统画笔  
  224.         pDc->SelectObject(pOldPen);  
  225.   
  226.         //分行绘制数字  
  227.         //只当前天数那一行往前推  
  228.         for(int j=0;j<nowWeak;j++)  
  229.         {  
  230.             if(nowDay == 0)  
  231.                 break;  
  232.   
  233.             CString cstr;  
  234.             cstr.Format(TEXT("%d"),nowDay--);  
  235.             pDc->TextOutW(calendarLeft+partWidth*(nowWeak-j-1) + 5,calendarTop+partHeight*(row+1),cstr);  
  236.         }  
  237.   
  238.         //当前天数往上推  
  239.         int R = row-1;  
  240.         if(R>0)  
  241.         {  
  242.             for(int i=0;i<R;i++)  
  243.             {  
  244.                 row--;  
  245.   
  246.                 if(nowDay == 0)  
  247.                         break;  
  248.   
  249.                 for(int j=0;j<7;j++)  
  250.                 {  
  251.                     CString cstr;  
  252.                     cstr.Format(TEXT("%d"),nowDay--);  
  253.                     pDc->TextOutW(calendarLeft+partWidth*(7-j-1) + 5,calendarTop+partHeight*(row+1),cstr);  
  254.                     if(nowDay == 0)  
  255.                         break;  
  256.                 }  
  257.             }  
  258.         }  
  259.   
  260.         //当前天数往下推  
  261.         //本月剩余天数  
  262.         int restDay;  
  263.         if(month == 1||month == 3||month == 5||month == 7||month == 8||  
  264.             month == 10||month == 12)  
  265.         {  
  266.             restDay = 31-nowDayBack;  
  267.         }  
  268.         else if(month == 2)  
  269.         {  
  270.             //闰年  
  271.             if((year%4 == 0&&year%100)||(year%400 == 0))  
  272.             {  
  273.                 restDay = 29 - nowDayBack;  
  274.             }  
  275.             //平年  
  276.             else   
  277.             {  
  278.                 restDay = 28 - nowDayBack;  
  279.             }  
  280.         }  
  281.         else   
  282.         {  
  283.             restDay = 30 - nowDayBack;  
  284.         }  
  285.         for(int i=0;i<restDay;i++)  
  286.         {  
  287.             CString cstr;  
  288.             cstr.Format(TEXT("%d"),++nowDayBack);  
  289.             pDc->TextOutW(calendarLeft+partWidth*(nowWeak++) + 5,calendarTop+partHeight*(rowBack+1),cstr);  
  290.             //换行  
  291.             if(nowWeak == 7)  
  292.             {  
  293.                 rowBack++;  
  294.                 nowWeak = 0;  
  295.             }  
  296.         }  
  297. }  

记得要添加MainFrm.cpp中添加这些头文件,否则会提示找不到相应的变量或者类:

[cpp]  view plain  copy
  1. #include "ClockShowerView.h"  
  2. #define PI 3.141593  
  3. #include "math.h"  

同时因为在CMainFrame中添加了对View的头文件的调用,在ClockShowerView.h中需要添加头文件:

[cpp]  view plain  copy
  1. #include "ClockShowerDoc.h"  

最后我们在CMainFrame的构造函数中修改并添加对Init的调用即可:

[cpp]  view plain  copy
  1. // CMainFrame 构造/析构  
  2.   
  3. CMainFrame::CMainFrame()  
  4. {  
  5.     // TODO: 在此添加成员初始化代码  
  6.     Init();  
  7.   
  8.     theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_VS_2008);  
  9. }  

然后我们就开始运行程序,出来后,点击菜单上的“时钟日历程序”中的子菜单项“开始/停止”,我们的时钟和自己绘制的日历就出来了~,自己绘制的日历会根据系统时间的变化而变化,各同学们朋友们可以更改自己的系统时间来验证这个我自己绘制的日历是否正确(算法自己写的但是也没怎么测试过,就只试了9月和10月的每一天都无问题,应该还是可以的哈 :)  )



最后,附上整个程序的源码,免积分~多

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值