[小插曲]VC学习——基于MFC的模拟时钟程序

2023-05-16

一、程序窗口设计步骤
(1)用AppWizard生成一个名为Clock的单文档(SDI)程序框架。为了简化应用程序,在第四步时去掉Docking toolbarInitial status bar选择项(不删除也可),其他各选项均可用缺省设置。
(2)编辑项目的菜单资源,在主框架窗口的主菜单(IDR_MAINFRAME)中添加一个名为“时钟控制”的下拉菜单。在“时钟控制”菜单中添加三个菜单选项“启动时钟”、“停止时钟”和“时间设置”。并在菜单属性项中设定“启动时钟”菜单的ID标号为ID_START,“停止时钟”菜单的ID标号为ID_STOP,“时间设置”菜单的ID标号为ID_SETTIME。为了简化菜单,可删除系统原有的“文件”、“编辑”菜单项。
(3)利用ClassWizard为视图类添加菜单命令处理函数。进入ClassWizardMessage Maps选项卡,选择Class Name项为CClockView类,在Object IDs列表框中分别选择新添加的菜单选项的ID,在Messages列表框中选择COMMAND,按下Add Function按钮添加成员函数。ClassWizard会为“启动时钟”、“停止时钟”和“时间设置”菜单选项添加相应的消息响应函数OnStart ( )、OnStop ( )和OnSettime ( )
(4)利用ClassWizard为视图类添加定时器和鼠标消息处理函数。进入ClassWizard的Message Maps选项卡,选择Class Name项为 CClockView类,在Messages列表框中分别选择定时器消息WM_TIMER和鼠标消息WM_LBUTIONDOWN,按下Add Function按钮添加成员函数。ClassWizard会添加相应的定时器和鼠标消息响应函数OnTimerOnLButtonDown
(5)使用Developer Studio菜单的Insert / Resource…选项调出Insert Source对话框,为项目添加新的对话框资源。在对话框属性中,修改对话框名为“时间设定”。在对话框中增加用来输入年、月、日、时、分、秒的编辑框控件。
通过控件属性,将年、月、日、时、分、秒等编辑控件的ID改为IDC_YEAR、IDC_MONTH、IDC_DAY、IDC_HOUR、IDC_MINUTE和IDC_SECOND。
(6)利用ClassWizard自动建立对话框类。进入ClassWizard后,弹出一个对话框询问是否要为该对话框模板建立类。按下“OK”按钮,会弹出New Class对话框,在Name栏填写对话框类的名称CSetTimeDlg后按“OK”按钮,即可为对话框创建一个对应的类。
(7) 利用ClassWizard为对话框类添加与各控件对应的数据成员。选择MemberVariables选项卡,确保Class Name项为对话框CSetTimeDlg类,然后在选项卡下方的窗口中选择各控件的ID并按下“Add Variable…”按钮,为其添加对应成员变量。

控制ID 变量类型 变量名 变量范围
IDC_YEAR int m_Year 0~3000
IDC_MONTH int m_Month 1~12
IDC_DAY int m_Day 1~31
IDC_HOUR int m_Hour 0~23
IDC_MINUTE int m_Minute 0~59
IDC_SECOND int m_Second 0~59

最后一列为变量取值范围。
(8)编辑工程的图标资源,在Resource View选项窗口中修改Icon结点所包含的主框架图标(IDR_MAINFRAME)。此步非必须。
(9)完成以上工作后,即可修改程序框架,添加必要的代码。
二、主要源代码:
按以下步骤向视图类(CClockView)添加下列数据成员及成员函数。
(1) 添加表示年、月、日、时、分、秒的变量。

     int year;
     int month;
     int day;
     int hour;
     int minute;
     int second;

(2) 添加秒表的计数变量。

 int watch;

(3) 添加时钟的画笔及画刷变量。

CPen m_HouPen, 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) 添加两个函数,计算时钟各指针位置。

void SetClock (int hour, int minute, int second);
CPoint GetPoint (int nLenth, int nValue);

(7) 在视图类构造函数中增加初始化语句,之前加上头文件

#include<ctime>

CClockView::CClockView()
{
// 设定时间
char   time[32];
SYSTEMTIME     st;  
GetLocalTime(&st);
day = st.wDay;
hour = st.wHour;
minute = st.wMinute;
month = st.wMonth;
second = st.wSecond;
year = st.wYear;
// 设定画笔/画刷
m_HouPen. CreatePen (PS_SOLID, 5, RGB (255, 0, 0) ); // 时针画笔
m_MinPen. CreatePen (PS_SOLID, 3, RGB (0, 0, 250) ); // 分针画笔
m_SecPen. CreatePen (PS_SOLID, 1, RGB (0, 0, 0) ); // 秒针画笔
m_MarkBrush. CreateSolidBrush (RGB (250, 250, 0) ); 
// 设定表心位置
m_Center. x = 200;
m_Center. y = 200; 
// 设定时钟半径
m_Radius = 200; 
// 计算指针位置
 SetClock (hour, minute, second);
 // 设定秒表计数器及按钮位置
watch = 0;
m_WatchStart = CRect (480, 310, 560, 340); // 启动钮
m_WatchStop = CRect (590, 310, 670, 340); // 停止钮
}
编写指针位置计算函数SetClock和GetPoint。首先在ClockView. cpp文件头部添加下面两行代码,以便进行数学计算。
#include "math.h"
#define PI 3.14159265 
然后添加下列代码:  
//计算各个指针位置的函数 
void CClockView::SetClock(int hour, int minute, int second)
{
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_Radius/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_Radius*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_Radius * 8/10), second);
m_Second [1] = GetPoint (30, second + 30);
} 
// 计算以表心为原点的指针的端点位置
CPoint CClockView ::GetPoint (int nLenth, int nValue)
{
CPoint p;
double angle = nValue* PI /30-PI/2;
p.x = m_Center.x + (int) (nLenth * cos(angle));
p.y = m_Center.y + (int) (nLenth * sin(angle));
return p;
}
绘制表盘上的标记、时针、分针和秒针,并显示数字时钟及秒表,在OnDraw函数中添加下面代码:
void CClockView::OnDraw(CDC* pDC)
{
CClockDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc); 
// 绘制表盘上的标记
pDC->SelectObject(m_MarkBrush);
int k=0;
for(int i=0;i<60;i++)
{
CPoint pt=GetPoint(175,i);
if (i%5==0)
{
//显示表盘上的数字
CString str[12]={"12","1","2","3","4","5","6","7","8","9","10","11"};
    pDC->TextOut(pt.x-5,pt.y-5,str[k]);
k++;
}else
{
//显示数字之间的圆圈
pDC->Ellipse(pt.x-2,pt.y-2,pt.x+2,pt.y+2);
}
} 
// 画时针
pDC->SelectObject (m_HouPen);
if (m_OldHour[0]!= m_Hour[0])
{ 
// 用白色覆盖原位置时针
pDC->SetROP2(R2_WHITE);
pDC->MoveTo(m_OldHour [0] );
pDC->LineTo(m_OldHour [1] );
pDC->SetROP2(R2_COPYPEN); 
//时针绘制
pDC->MoveTo(m_Hour[0]);
pDC->LineTo(m_Hour[1]);
}
else
{ 
// 时针绘制
pDC->MoveTo(m_Hour[0]);
pDC->LineTo(m_Hour[1]);
}
// 画分针
pDC->SelectObject (m_MinPen);
if (m_OldMin[0]!=m_Minute[0])
{ 
// 用白色覆盖原位置分针
pDC->SetROP2(R2_WHITE);
pDC->MoveTo(m_OldMin[0]);
pDC->LineTo(m_OldMin[1]);
pDC->SetROP2(R2_COPYPEN); 
// 分针绘制
pDC->MoveTo(m_Minute[0]);
pDC->LineTo(m_Minute[1]);
}
else
{
// 分针绘制
pDC->MoveTo(m_Minute[0]);
pDC->LineTo(m_Minute[1]);
} 
// 用白色覆盖原位置秒针
pDC->SelectObject(m_SecPen);
pDC->SetROP2(R2_WHITE);
pDC->MoveTo(m_OldSec[0]);
pDC->LineTo(m_OldSec[1]);
pDC->SetROP2(R2_COPYPEN); 
// 秒针绘制
pDC->MoveTo(m_Second[0]);
pDC->LineTo(m_Second[1]);
// 数字时钟显示
pDC->SelectStockObject(WHITE_BRUSH);
pDC->Rectangle(450,30,700,180);
pDC->TextOut(535,20,"当前时间");
CString m_Date,m_Time;
m_Date.Format ("% 4d年%4d月%4d日",year,month,day);
pDC->TextOut(510,70,m_Date);
m_Time.Format("%4d点%4d分%4d秒",hour,minute,second);
pDC->TextOut(510,100,m_Time); 
// 秒表显示
pDC->Rectangle(450,220,700,370);
pDC->TextOut(545,200,"秒 表");
int minSec= watch%100;
int Sec=(watch/100)%60;
int Min=(watch/100)/60;
m_Time.Format("% 02d: % 02d: % 02d",Min,Sec,minSec);
pDC->TextOut(535,260,m_Time);
pDC->Rectangle(&m_WatchStart);
pDC->Rectangle(&m_WatchStop);
pDC->TextOut(m_WatchStart.left + 18,m_WatchStart.top + 5,"启动");
pDC->TextOut(m_WatchStop.left + 18,m_WatchStop.top + 5,"停止");
} 

请注意将表示时间的整数转换为CString字符串类型的方法以及秒表的显示方法。另外,watch计数器以1/100秒为计数单位,每达到100则秒数加1。
按照下列步骤增加时钟控制代码:
修改Onstart和OnStop函数,设置时钟运动消息。按比正常时钟快20倍的假定,50ms产生一个消息。本程序采用和正常时间同步,即1000ms产生一个消息, 其代码为:

void CClockView::OnStart() 
{
SetTimer (1, 1000, NULL);
} 
void CClockView::OnStop() 
{
KillTimer (1);
}
修改OnTimer函数,正确计算并处理年、月、日、时、分、秒等变量的联动变化 ,其代码为:
void CClockView::OnTimer(UINT nIDEvent) 
{
if (nIDEvent == 1)
{
second++; // 秒增加
if (second>59)
{
second=0;
minute++; // 分增加
}
if (minute>59)
{
minute= 0;
hour++; // 小时增加
}
if (hour>23)
{
hour=0;
day++; // 日增加
}
switch(month)
{
case 1: // 大月
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if (day>31)
{
day= 1;
month++; // 月增加
}
break;
case 4: // 小月
case 6:
case 9:
case 11:
if (day>30)
{
day=1;
month++; // 月增加
}
break;
case 2:
if (year%4 ==0 && day>29) // 润二月
{
day=1;
month++; // 月增加
}
if (year%4!=0 && day>28) // 二月
{
day=1;
month++;
}
break;
}
if (month > 12)
{ 
// 年增加
year++;
month=1;
}
SetClock (hour, minute, second);
Invalidate (false); 
}
// 秒表定时器消息处理
if (nIDEvent == 2)
{
watch++;
Invalidate (false);
}
CView::OnTimer(nIDEvent);
}

添加时间设置对话框代码。
首先在ClockView. cpp文件头部添加下列语句:

#include “SetTimeDlg. h”

在时间设定对话框类的构造函数中,做如下修改,将初始日期设为当前时间,之前要加上头文件

#include<ctime>

CSetTimeDlg::CSetTimeDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSetTimeDlg::IDD, pParent)
{
//||AFX_DATA_INIT(CSetTimeDlg)
char   time[32];
SYSTEMTIME     st;  
GetLocalTime(&st);
m_Day = st.wDay;
m_Hour = st.wHour;
m_Minute = st.wMinute;
m_Month = st.wMonth;
m_Second = st.wSecond;
m_Year = st.wYear;// ||AFX_DATA_INIT
} 
最后,在OnSettime函数中添加代码如下:
void CClockView::OnSettime() 
{
CSetTimeDlg SetDlg;
if (SetDlg.DoModal ()==IDOK)
{
year=SetDlg.m_Year;
month= SetDlg.m_Month;
day= SetDlg.m_Day;
hour=SetDlg.m_Hour;
minute=SetDlg.m_Minute;
second=SetDlg.m_Second; 
}
// 计算各指针位置
SetClock (hour,minute,second);
Invalidate (true);
} 
按以下步骤设计秒表控制程序:
在OnLButtonDown函数中增加下列内容,以便响应单击秒表启动、停止框所发出的消息:
void CClockView::OnLButtonDown(UINT nFlags, CPoint point) 
{
if (m_WatchStart.PtInRect(point))
{
watch=0;
SetTimer(2,10,NULL);
}
if (m_WatchStop.PtInRect(point))
{
KillTimer (2);
}
CView::OnLButtonDown(nFlags, point);
}

编译,连接,运行程序。
运行结果:
这里写图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[小插曲]VC学习——基于MFC的模拟时钟程序 的相关文章

  • [转]伪代码的写法

    伪代码的写法 xff08 附 xff1a 12种排序算法详解 xff09 转自 xff1a http blog sina com cn s blog 134451adb0102wfgu html 伪代码 xff08 Pseudocode x
  • linux C++调用python3的程序

    环境 xff1a ubuntu1404 python3 4 3 首先安装对应python不同版本的调用库 sudo apt get install python3 4 dev xff0c python脚本基本不用变 xff0c 在C 43
  • Bug 记录

    Bug记录 CocosCreator打包出现 Error xff1a Program type already present android support v4 os ResultReceiver MyResultReceiver 解决
  • I2C通信

    I2 C 芯片间 总线接口连接微控制器和串行 I 2 C 总线 它提供多主机功能 xff0c 控制所有 I 2 C 总线特定的 时序 协议 仲裁和定时 1 xff0c 物理层 1 IIC是一种两线串行的通信方式 xff0c SCL xff0
  • 使用Mybatis-Plus代码生成器的报错解决

    使用Mybatis Plus的同学 xff0c 在使用代码生成器的时候不知道有没有遇到过这个问题 xff1a 21 36 23 829 main DEBUG com baomidou mybatisplus generator AutoGe
  • Debian之安装完成后找不到命令解决办法

    1 修改配置文件 bashrc vim root bashrc export PATH 61 PATH usr sbin 2 使配置文件生效 source root bashrc
  • 相机标定、双目相机标定(原理)、三维重建效果展示

    1 相机标定的目的 xff1a xff08 1 xff09 通过单目相机标定分别求出左右相机的内参数和外参数 xff08 2 xff09 矫正由于镜头畸变造成的图片的变形 xff0c 例如 xff0c 现实中的直线 xff0c 拍摄成图像后
  • mac系统做openstack qcow2/raw镜像

    1 vmware安装出来虚拟机 xff08 操作系统不拆分 xff09 2 zhangjinyudeMacBook Pro Asianux vmwarevm zhangjinyu ls lh total 2820216 rw 1 zhang
  • 使用 Chrome 获取 Cookie 的数据

    Chrome 浏览器自带的开发功能相当强大 xff0c 这里只使用它的抓包功能 一 在浏览器中打开目标网站并登录 xff0c 进入目标页面 二 在 Chrome 浏览器下方的开发工具中单击 Network 标签页 按 F5 键 xff0c
  • 后台开发SQL技术总结

    一 字符串截取 1 substring str pos 用法 从字符串的第 4 个字符位置开始取 xff0c 直到结束 mysql gt select substring 39 example com 39 4 43 43 substrin
  • 论文记录:图像描述技术综述

    文章目录 前言 一 什么是image caption xff1f 二 基于深度学习的图像描述方法 1 基于编码器 解码器的方法 2 基于注意力机制的方法 3 基于生成对抗网络的方法 4 基于强化学习的方法 5 基于密集描述的方法 总结 前言
  • 一个接口有多个实现类

    如果一个接口有多个实现类 xff0c 在Controller层注入后调用 xff0c 怎么知道调用的是接口的哪个方法呢 xff1f 经过一番测试 和查找资料 终于找到了结果 2 0一个接口对应多个实现类 一个接口对应对个实现类 xff0c
  • c/c++使用libcurl库做http客户端及封装(HTTP_GET和HTTP_POST)

    由于项目需求需要发送http post去请求数据 xff0c 所以上网去寻找了一些发送http请求的方法 xff0c 发现libcurl较为常用 xff0c 然后根据官网上的例子 xff0c 对libcurl做了一些简单的封装 xff0c
  • (医学三维重建)MATLAB体绘制算法:多层面重建(MPR)

    xff08 医学三维重建 xff09 MATLAB体绘制算法 xff1a 多层面重建 xff08 MPR xff09 算法原理代码实现测试结果其他 by HPC ZY 算法原理 体绘制中比较特殊的一种 xff0c 因为它的输出是各种切面 就
  • Qt各个类之间继承关系

  • QGC -- 配置相机参数数据流说明(1)

    一 相关配置文件及对应画面 1 界面GeneralSettings qml 2 Video SettingsGroup json对应界面如下 xff1a span class token punctuation span span clas
  • ubuntu18.04 Intel Realsense T265与Realsense D435i 使用教程

    主要包括 xff1a realsense sdk驱动安装与ros包安装编译D435i与t256相机使用多个相机联合使用 官网链接 xff1a https github com IntelRealSense realsense roshttp
  • 2023年第八届团队程序设计天梯赛选拔校赛(三)题解

    文章目录 7 1 认识时钟7 2 修剪灌木7 3 求和运算7 4 合并数组7 5 骰子游戏7 6 字符串最大跨距7 7 上台阶7 8 A B7 9 括号匹配7 10 列出连通集7 12 哲哲打游戏7 13 喊山 标号标题分数提交通过率7 1
  • 学习挖掘机和程序员哪个好

    guanghuacheng guanghuacheng 等 级 xff1a 结帖率 xff1a 0 00 楼主发表于 xff1a 2011 04 14 16 57 13 快要高考了 学习成绩一般 不想上了 家里让去学挖掘机 我不想去 要想培
  • 我的2014作的一手好死,2015求轻虐

    真的好想上来开头就写 新的一年 xff0c 全新的自己 xff0c 但是这样自欺欺人的话我还是别说了 xff0c 省得一大批损友又来吐嘈我 2015年希望找到自己的另一半这样的话我也不想再提了 xff0c 因为这样写了两年 依旧单身 xff

随机推荐

  • 织梦后台登陆不上提示验证码不正确

    1 密码明明正确的 xff0c 却无法登陆后台管理 解答 xff1a 此外 xff0c 不管是新人 xff0c 还是phper xff0c 都要注意的是 xff1a 用户名和密码只能由 a z A Z 64 这些字符组成 xff0c 不能是
  • 浅谈视觉与语言中的多模态研究,究竟都研究什么

    前言 随着人工智能的整体进步 xff0c 计算机视觉和自然语言处理已经有了巨大的 有了如此强大的算法和自主系统的综合能力 xff0c 就需要合并知识领域 xff0c 实现跨模态兼容 xff0c 视觉语言 VisLang 研究具有更复杂的任务
  • 复选框单选框与文字对齐问题的研究与解决

    原文地址 xff1a http www zhangxinxu com wordpress p 61 56 前言 目前中文网站上面的文字 xff0c 就我的个人感觉而言 xff0c 绝大多数网站的主流文字大小为12px xff0c 因为在目前
  • 我的2014作的一手好死,2015求轻虐

    真的好想上来开头就写 新的一年 xff0c 全新的自己 xff0c 但是这样自欺欺人的话我还是别说了 xff0c 省得一大批损友又来吐嘈我 2015年希望找到自己的另一半这样的话我也不想再提了 xff0c 因为这样写了两年 依旧单身 xff
  • iOS系统及微信中不支持audio自动播放问题

    span class hljs tag lt span class hljs title script span span class hljs attribute src span 61 span class hljs value 34
  • 模拟复选框

    span class hljs doctype lt DOCTYPE html gt span span class hljs tag lt span class hljs title html span gt span span clas
  • 验证码刷新

    lt label span class hljs keyword class span 61 span class hljs string 34 focusa 34 span gt 看不清 xff1f lt a href 61 span c
  • 如何从数据库调出数据显示到页面PHP+Mysql+Html(简单实例)

    首先显示一下数据库的数据 页面信息 lt DOCTYPE html PUBLIC 34 W3C DTD XHTML 1 0 Transitional EN 34 34 http www w3 org TR xhtml1 DTD xhtml1
  • PHP+MYSQL+HTML 学生成绩查询

    首先创建一个数据库名为 xscj xff0c 表信息如下 xff1a 页面信息为 xff1a lt DOCTYPE html PUBLIC 34 W3C DTD XHTML 1 0 Transitional EN 34 34 http ww
  • php试题与答案(一)

    1 xff0e mysql connect 与 64 mysql connect 的区别是 B A 64 mysql connect 不会忽略错误 将错误显示到客户端 B mysql connect 不会忽略错误 将错误显示到客户端 C 没
  • php试题与答案(二)

    37 xff0e 在str replace 1 2 3 函数中1 2 3 所代表的名称是 B A 34 取代字符串 xff02 xff0c xff02 被取代字符串 xff02 xff0c xff02 来源字符串 xff02 B xff02
  • PHP实现上一页下一页翻页代码实例

    lt php 1 xff0c 将数据库的所有记录查询出来 xff0c 然后再一页一页的显示 link 61 mysql connect 39 localhost 39 39 root 39 39 123 39 mysql select db
  • 论文笔记:Dual-Level Collaborative Transformer for Image Captioning

    前言 论文详情可以参照这篇 xff0c 写得很好 本小白这篇内容主要是对论文中的一些思想和图以及部分公式进行自己的解读 如有错误 xff0c 请多多谅解 论文思想 首先 xff0c 根据论文第一作者在知乎所说 xff08 搜这篇论文名称可以
  • win10环境下基于OpenVINO部署yolov5模型

    以在Intel的OpenVINO上部署Yolov5模型为例 xff0c 加深对模型部署的理解 1 训练准备 获取yolov5模型及数据集 git clone git github com ultralytics yolov5 pt模型 co
  • docker常用命令集锦

    登录服务器 ssh v 64 192 sudo权限 su 查看docker版本 docker version 查看内核版本 uname a 启动docker docker ps a docker start container名 docke
  • git详细使用

    git搭建 amp 更新远程仓库 配置用户 span class token function git span config global user name span class token string 34 John Doe 34
  • Mindspore安装

    本文用于记录搭建昇思MindSpore开发及使用环境的过程 xff0c 并通过MindSpore的API快速实现了一个简单的深度学习模型 什么是MindSpore 昇思MindSpore是一个全场景深度学习框架 xff0c 旨在实现易开发
  • 机械臂的运动控制

    前言 xff1a 近年来 xff0c 随着服务机器人的兴起 xff0c 机械臂也正走进我们的日常生活 xff0c 近年来出现了一些低成本的 小型的 桌面版 的机械臂的产品 xff0c 相信这将是服务机器人的一个重要方向 xff01 机械臂由
  • Gazebo仿真

    在ROS中有3个可以模拟机器人的模拟器软件 xff1a Gazebo Stage ArbotiX 就是RVIz 你可以任选一个 xff1a Gazebo是一个仿真环境 xff08 平台 xff09 xff0c 可以进行三维机器人动力学仿真等
  • [小插曲]VC学习——基于MFC的模拟时钟程序

    一 程序窗口设计步骤 xff08 1 xff09 用AppWizard生成一个名为Clock的单文档 xff08 SDI xff09 程序框架 为了简化应用程序 xff0c 在第四步时去掉Docking toolbar和Initial st