1整体设计

创建对话框程序,并且设计对话框相关控件如图

相应的ID和对应的成员变量如图:

我的想法是这样的,只读属性的编辑框添加有CString类型的成员变量(如s_hour),在xxxDlg.h里另外定义了对应的int型成员变量(如n_hour),就是因为如果想要显示01:03:07这样的时间时,单纯的用于计时的int变量十位是不会显示“0”的。所以我通过除以10和余10把一位数的十位和个位取出来,再转化为CString类型的变量,数据交换同步到编辑框显示。

2 编辑框的显示

①初始化显示00:00:00

在初始化函数

BOOL CEbbinghausDlg::OnInitDialog()

里面,将各变量初始化为0,CString型变量可直接初始化为字符串“00”,更新数据显示。

n_hour = ;
n_minute = ;
n_second = ;
s_hour = "";
s_minute = "";
s_second = "";
UpdateData(FALSE);

②发现编辑框显示的字体很小,如图

那么就要修改字体大小。

给编辑框控件添加edit类型的变量,如第一个ID_HOUR的编辑框:添加edit类型的,CEdit,f_hour。

在头文件XXXDlg.h里定义字体变量。

CFont my_Font;

在OnInitDialog()函数里添加初始化代码

my_Font.CreatePointFont(, "Arial");
f_hour.SetFont(&my_Font);
f_minute.SetFont(&my_Font);
f_second.SetFont(&my_Font);

效果:

注:字体要是找不到用什么好,可以在word里找找,再填到函数参数表里。

my_Font.CreatePointFont(400, "Calibri");

③按下buttun control:Start开始计时

在头文件里定义这两个成员变量

BOOL b_review;
BOOL b_suspend;

b_review是用来决定定时5min是否完成的,没到就是FALSE,到了就是TRUE。b_suspend是指示当前是否暂停的,暂停即为TRUE,否则FALSE。初始化均为FALSE。

b_review = FALSE;
b_suspend = FALSE;

现在要开始设计定时器了,在cpp文件开头:

#define N_TIME_SEC 1000 //一秒时间间隔
#define N_TIME_SHOW 200 //0.2s刷新显示
#define N_TIMER_SEC 1
#define N_TIMER_SHOW 2

前两个是用于SetTimer()函数的第二个参数,即产生1s和0.2s的信号来访问WM_TIMER消息响应函数。后两个是指明定时器的序号,1s的是1,0.2s的是2,分别用于进行秒加一计数和刷新显示。

void CEbbinghausDlg::OnTimer(UINT_PTR nIDEvent)

这个函数的参数就是当前来“敲门”访问的定时器序号,那么只要在内部进行一下选择,1的时候干什么,2的时候干什么就能区别处理。用switch语句即可。

我们设想按下Start后开始计时,然后数据的变化是通过1s信号访问OnTimer函数,在函数内部调整时分秒变量实现。刷新显示是第二个定时器每0.2s就访问一次OnTimer函数。

那么Start的消息函数里要SetTimer。

void CEbbinghausDlg::OnBnClickedStart()
{
// TODO: 在此添加控件通知处理程序代码
if (b_review||b_suspend)
KillTimer(N_TIMER_SEC);
b_review = FALSE;
b_suspend = FALSE;
n_hour = ;
n_minute = ;
n_second = ;
SetTimer(N_TIMER_SEC, N_TIME_SEC, NULL);
SetTimer(N_TIMER_SHOW, N_TIME_SHOW, NULL);
}

④按下Suspend暂停计时,显示当前数值但是不要清零,因为再次按下Suspend后得继续计时。

void CEbbinghausDlg::OnBnClickedSuspend()
{
// TODO: 在此添加控件通知处理程序代码
b_suspend =!b_suspend;
if (b_suspend)
{
KillTimer(N_TIMER_SEC);
KillTimer(N_TIMER_SHOW);
int h1, h2, m1, m2, s1, s2;
h1 = n_hour / ;
h2 = n_hour % ;
m1 = n_minute / ;
m2 = n_minute % ;
s1 = n_second / ;
s2 = n_second % ;
s_hour.Format("%d%d", h1, h2);
s_minute.Format("%d%d", m1, m2);
s_second.Format("%d%d", s1, s2);
UpdateData(FALSE);
}
else
{
SetTimer(N_TIMER_SEC, N_TIME_SEC, NULL);
SetTimer(N_TIMER_SHOW, N_TIME_SHOW, NULL);
}
}

OnTimer()函数就这样设计:

void CEbbinghausDlg::OnTimer(UINT_PTR nIDEvent)
{
switch (nIDEvent)
{
case :
{
if (b_review == FALSE)
{
n_second++;
if (n_second == )
{
n_second = ;
n_minute++;
}
if (n_minute == )
{
n_minute = ;
n_hour++;
}
if (n_hour == )
n_hour = ; if (n_minute == )
b_review = TRUE;
}
else if (b_review)
{
n_hour = ;
n_minute = ;
n_second = ;
s_hour.Format("%s", "Re");
s_minute.Format("%s", "vi");
s_second.Format("%s", "ew");
}
}
case :
{
if (b_review == FALSE)
{
int h1, h2, m1, m2, s1, s2;
h1 = n_hour / ;
h2 = n_hour % ;
m1 = n_minute / ;
m2 = n_minute % ;
s1 = n_second / ;
s2 = n_second % ;
s_hour.Format("%d%d", h1, h2);
s_minute.Format("%d%d", m1, m2);
s_second.Format("%d%d", s1, s2);
}
else if (b_review)
{
n_hour = ;
n_minute = ;
n_second = ;
s_hour.Format("%s", "Re");
s_minute.Format("%s", "vi");
s_second.Format("%s", "ew");
}
UpdateData(FALSE);
}
default:
break;
}
CDialogEx::OnTimer(nIDEvent);
}

⑤想弄好看点,把文本框背景弄成图片。

先添加位图资源:

OnInitDialog()函数里继续添加:

/*    位图初始化        */
CPaintDC dc(this);
CBitmap bmpBackground;
bmpBackground.LoadBitmap(IDB_BACKGROUND); //ID是你自己的图对应的ID
BITMAP bitmap;
bmpBackground.GetBitmap(&bitmap);
SetWindowPos(NULL, , , bitmap.bmWidth, bitmap.bmHeight, SWP_NOZORDER | SWP_NOMOVE);

OnPaint()函数里的else中添加:

else
{
/* 绘制背景图片 */
//CDialogEx::OnPaint();
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
// GetWindowRect(&rect);
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);
CBitmap bmpBackground;
bmpBackground.LoadBitmap(IDB_BACKGROUND); //IDB_BITMAP1是背景位图对应的ID
BITMAP bitmap;
bmpBackground.GetBitmap(&bitmap);
CBitmap *pbmpOld = dcMem.SelectObject(&bmpBackground);
dc.StretchBlt(, , rect.Width(), rect.Height(), &dcMem, , , bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);//让显示区域矩形宽高和对话框大小一致,先目的后源!
}

设计完成了,效果如下:

但是编辑框的文字还有白色的背景,没做到透明,就很难受。

【MFC】利用MFC写一个计时器小程序的更多相关文章

  1. 手把手教你写一个RN小程序!

    时间过得真快,眨眼已经快3年了! 1.我的第一个App 还记得我14年初写的第一个iOS小程序,当时是给别人写的一个单机的相册,也是我开发的第一个完整的app,虽然功能挺少,但是耐不住心中的激动啊,现 ...

  2. 微信小程序——手把手教你写一个微信小程序

    前言 微信小程序年前的跳一跳确实是火了一把,然后呢一直没有时间去实践项目,一直想搞但是工作上不需要所以,嗯嗯嗯嗯嗯emmmmm..... 需求 小程序语音识别,全景图片观看,登录授权,获取个人基本信息 ...

  3. 用Taro写一个微信小程序(一)——开始一个项目

    一.Taro简介 1.名字由来 Taro['tɑ:roʊ],泰罗·奥特曼,宇宙警备队总教官,实力最强的奥特曼. 2.taro是什么 Taro 是一个开放式跨端跨框架解决方案,支持使用 React/Vu ...

  4. 利用canvas写一个验证码小功能

    刚刚开始接触canvas,写个验证码小功能练练手,实现效果图如下: 主要代码如下: html <!DOCTYPE html> <html lang="en"> ...

  5. 写一个python小程序

    在windows环境下进行操作 window+R 输入cmd  创建一个文件夹 mkdir pytxt 创建一个py文件 py.py  用notepad或者记事本等工具进行编辑 或 首先声明pytho ...

  6. 用Taro写一个微信小程序(二)——配置目录别名

    配置别名可以方便书写代码引用路径,让代码更整洁. 官方文档可参考https://nervjs.github.io/taro/docs/config-detail#alias 一.在config/ind ...

  7. 用Taro写一个微信小程序(三)—— 配置dva

    一.关于dva dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻 ...

  8. 学了C语言,如何利用CURL写一个下载程序?—用nmake编译CURL并安装

    在这一系列的前一篇文章学了C语言,如何为下载狂人写一个磁盘剩余容量监控程序?中,我们为下载狂人写了一个程序来监视磁盘的剩余容量,防止下载的东西撑爆了硬盘.可是,这两天,他又抱怨他的下载程序不好用,让我 ...

  9. 搭建Spring开发环境并编写第一个Spring小程序

    搭建Spring开发环境并编写第一个Spring小程序 2015-05-27      0个评论    来源:茕夜   收藏    我要投稿 一.前面,我写了一篇Spring框架的基础知识文章,里面没 ...

随机推荐

  1. Java | 基础归纳 | Gson && Json

    JSON: JSON就是一种数据的组织形式,用于数据传输. 地址:https://mvnrepository.com/artifact/net.sf.json-lib/json-lib/2.4 Mav ...

  2. python之os、sys和random模块

    import os # print(os.getcwd())#获取当前目录,绝对路径# print(os.chdir('../'))#更改当前目录,../的意思是退回上一级目录# print(os.g ...

  3. 自己写一个websocket

    import socket, base64, hashlib sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsock ...

  4. 不通过ecplise,只通过文件目录 创建最简单的JSP文件

    手动创建最简单的JSP 文件   1.在Tomcat 6.0的安装目录的webapps目录下新建一个目录,起名叫myapp. 2.在myapp目录下新建一个目录WEB-INF,注意,目录名称是区分大小 ...

  5. C#: static关键字的作用(转)

    C#: static关键字的作用   static意思是静态,可以修饰类.字段.属性.方法 标记为static的就不用创建实例对象调用了,可以通过类名直接点出来 static三种用法: 1.用于变量前 ...

  6. 使用原生javascript实现jquery的$(function(){ })

    在使用jquery的时候,经常用到$(function(){})方法或者是$(document).read(function(){})来作为页面dom节点加载完成之后javascript的执行入口,现 ...

  7. ES6学习笔记(11)----Proxy

    参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ Proxy1.概述    Proxy可以用来修改对象的默认操作    let obj = {na ...

  8. android开发哪些坑需要注意

    同一个应用的JNI代码,不要轻易换NDK编译的版本,否则会有很多问题(主要是一些方法实现不一样,并且高版本对代码的检测更严格),比如r8没有问题,但到r9就有问题了,这是个大坑: Android的JN ...

  9. IP地址 子网掩码 默认网关和DNS服务器的关系

    在过去,男人是需要能够上房揭瓦的,是要能够修水管的.现在的男人是需要会装系统的,会设置路由器的.世界变化太快! 废话不多说,本文来讨论一下电脑上最为常见的几个网络参数:IP地址.子网掩码.默认网关和D ...

  10. jsp <%@ include %> 例子

    <%@ include %>:所有代码包含进来之后一起进行处理,最终编译成一个servlet. jsp文件中添加top和bottom.jsp页面 empList.jsp <%@ pa ...