手把手教MFC做计算器
手把手教MFC做计算器
![](http://rescdn.qqmail.com/zh_CN/htmledition/images/showfd083516.gif)
标签:
杂谈 |
分类: Cplusplus |
上个月,国庆期间在研究MFC贪吃蛇的程序之余,很有兴致去想做一个“加法器”,顾名思义也就只能实现一个加法功能而已。当初是做出来了,不过是只能用键盘输入数字的,这个和Windows自带的计算器有差别,再者,我当初做的加法器实现的方式很简单,就是用在对话框页面中添加2个编辑框控件和一个按钮控件“+”,然后关联ID,然后再CDialog中添加代码实现功能。
近日,在继续学习MFC的过程,看到这个半成品,就有完善它成为一个计算器的想法,当然就在此基础上。这里声明,该计算器的制作方法和过程和百度上的有一些区别,并不是“很常规”的那种计算器写法,纵然是我自己练手的作品,但是一些基本的功能也是能实现的,现在就手把手教制作这个计算器。
STEP 1(页面设计部分与控件添加部分)
首先打开VC,选择MFC AppWizard[exe],设定好路径和工程名(这里我设置工程名为为“My”)。这里要注意的是在创建向导步骤1的时候,我们选择“基本对话框”。
之后我们可以点击完成便看到以下界面
此时我们把当前页面上原配的控件按Delete全部清除(如下图)
接着我们按照MFC自带的控件选项进行我们本次计算器的控件添加(以下是控件)
我们在原先清空的界面中依次用上图控件画出一个基本的计算器页面(如下图)。
当然作为“所见即所得”的MFC控件设计,干净整齐的界面是基本要求,甚至会影响用户的心情。
上图我们用按钮控件添加一共15个按钮,分别是数字“ 0 ~ 9” 以及 “+ - * /”。
每个控件“属性”都有属于它自己的ID,默认的按钮按键为IDC_BUTTON0,而且Cap当然我们为了“顾名思义”,对控件ID进行修改成我们容易辨认的(也可以不改),添加完控件并修改ID之后。(如下图)
这里我们把数字按钮0 设置ID为IDC_BUTTON14_NUM0,其他的依次类推
完成修改ID后,就需给控件添加消息响应了,基本操作可以是直接双击控件,便会有向导提示。
MFC默认下了的响应信息都为On_开头,而且以下显示的是数字5的消息响应.之后所有的依次类推,这步骤一般不
对成员函数名称做任何修改,直接点击OK即可
之后就会跳转到具体的代码实现过程 这里我们依次给每一个控件添加消息响应函数
(以下仅列出一部分)
到此为止 我们基本上完成了计算器页面的前半部分预备工作,下来是我们的对控件具体实现代码的添加
这里我把添加的控件消息响应函数列出来
这里忘记了,提醒一点
编辑框控件的ID是
IDC_EDIT1
IDC_EDIT2
IDC_EDIT3
还有 加减乘除的控件添加当初没有进行名字的设置
默认为
void CMyDlg::OnButton1()//加
void CMyDlg::OnButton2()//减
void CMyDlg::OnButton3()//乘
void CMyDlg::OnButton4()//除
在开始第二步之前有一项工作时必须要做的,那便是添加3个成员变量和一个CEdit类的变量
具体添加方法,就是右键主对话框CMyDlg->Add Member Variable
也可以是在菜单栏中选择
“查看”->“建立类向导”
这里我们把3个编辑框控件内的变量都改变为double型的(因为进行四则运算难免出现小数点)
之后再在控件IDC_EDIT3中选择"Add Variable"
并且数据类型选择 Control类型 此时变量自动改为了 CEdit类
这步的意思是说 我们把编辑框控件3的设置为CEdit类 并且设置一个成员对象是m_CResult。
//
STEP 2(控件消息响应函数具体代码添加部分)
首先从加法开始
void CMyDlg::OnButton1()
{
// TODO: Add your control notification handler code here
UpdateData();
double n_result;
n_result = m_num1 + m_num2;
m_result = n_result;
char sz[20];
sprintf(sz,"%f",m_result);
m_CResult.SetWindowText(sz);
}
UpdateData() 是MFC的窗口函数,用来刷新数据的
由于我们进行基本运算需要更新数据 所以必须添加这个函数。(可以认为是必须的)
n_result = m_num1 + m_num2;
m_result = n_result;
char sz[20];
sprintf(sz,"%f",m_result);
以上代码是进行 加法的基本语句,然后数组保存并格式化打印输出。
m_CResult.SetWindowText(sz);此句是把结果输出在之前用CEdit类创建的对象m_CResult,m_CResult调用SetWindowText(sz);把结果显示在编辑框中。
无独有偶
剩下的减法 乘法 和除法 也是大同小异(只是把 符号小改一下便可~~)
这里贴出所有加减乘除的代码
void CMyDlg::OnButton1()
{
// TODO: Add your control notification handler code here
UpdateData();
double n_result;
n_result = m_num1 + m_num2;
m_result = n_result;
char sz[20];
sprintf(sz,"%f",m_result);
m_CResult.SetWindowText(sz);
}
void CMyDlg::OnButton2()
{
// TODO: Add your control notification handler code here
UpdateData();
double n_result;
n_result = m_num1 - m_num2;
m_result = n_result;
char sz[20];
sprintf(sz,"%f",m_result);
m_CResult.SetWindowText(sz);
}
void CMyDlg::OnButton3()
{
// TODO: Add your control notification handler code here
UpdateData();
double n_result;
n_result = m_num1 * m_num2;
m_result = n_result;
char sz[20];
sprintf(sz,"%f",m_result);
m_CResult.SetWindowText(sz);
}
void CMyDlg::OnButton4()
{
// TODO: Add your control notification handler code here
UpdateData();
double n_result;
n_result = m_num1 / m_num2;
m_result = n_result;
char sz[20];
sprintf(sz,"%f",m_result);
m_CResult.SetWindowText(sz);
}
这里我特地说明一下
由于我们预设了2个编辑框所想实现的功能是,如在编辑框1内输入一个输入30,然后再编辑框2内输入另一个数字20,并且再进行运算。那么存在一个问题。这个问题其实困惑了我很久,那就是,如何用判断用户是在哪个编辑框上输入了数字,所以我们需要给程序加入一个功能,那便是判断用户是在编辑框1输入,还是编辑框2内输入。
那么我们想,在日常我们用电脑的过程中,一般都是用鼠标去点击编辑框来进行一系列操作。那么我可以加入一个鼠标左键点击WM_LBUTTONDOWN消息和一个 EN_SETFOCUS事件来响应这个鼠标消息。 EN_SETFOCUS为判断焦点事件(通俗点说,那便是判断光标在什么地方)
这样一来,一切逻辑都理顺了。我们用户用鼠标选择并点击编辑框的时候,我们用WM_LBUTTONDOWN消息去响应,然后与此同此,我们把响应的和EN_SETFOCUS联系起来,我们预设一个全局变量nEditFlag ,作为在EN_SETFOCUS函数里的一个 标记,并在鼠标点下的时候用nEditFlag 去表示编辑框目前被选定的状态,nEditFlag ==1 的时候我们就判断用户选择了编辑框1 ,再者当nEditFlag ==2的时候说明编辑框2被选定。
这里我告诉大家如何添加 事件 EN_SETFOCUS,由于EN_SETFOCUS是一个判断焦点的,所以对象应该是编辑框1和编辑框2里添加,所以我们回到对话框编辑页面。
“右键编辑框1”->点击“事件”-> “选择EN_SETFOCUS”(这里程序默认的响应函数是OnsetfocusEdit1)
依次类推我们也给编辑框2添加事件响应函数OnsetfocusEdit2,方法同上
如下图
设置好之后,我们还要做一些初始化工作,在程序运行之初,我们先初始化nEditFlag = 0;那么在哪里初始化呢?很简单,正如大家想的一样在OnInitDialog()内进行初始化
我们只需在OnInitDialog()函数中 加入一句
nEditFlag = 0;便可以了(如下图黑条字体部分)
之后我们再为两个事件响应函数进行OnsetfocusEdit1()和OnsetfocusEdit2()添加代码
当用户选定编辑框1的时候,nEditFlag = 1;
当用户选定编辑框2的时候,nEditFlag = 2;
而鼠标消息WM_LBUTTONDOWN具体代码如下
//
STEP 3(按键0~9的响应部分)
这里由于代码都大同小异,所以就用数字按钮1,2来进行简要说明
用if语句去判断标记常量 nEditFlag 从而给判断是m_num1还是m_num2进行操作
这里
m_num1是编辑框1内的数字
m_num2是编辑框2内的数字
剩下了3~9代码以上大同小异。
这里进行一个说明
m_num2=m_num2*10+1; 很多人会问这步是说明意思,这步乍看貌似有点一头雾水(当初我也是这样)但是仔细看看还是能看明白的。
比方说 用户想打出自然数“234”
用户第一次点的数字是2 那么此时对应代码执行是这段
m_num2=m_num2*10+2; 那么m_num2 = 0*10 +2 (初始化时m_num2 = 0)
之后如果在点击3的时候执行的代码是
m_num2=m_num2*10+3; (此时经过第一步m_num2已经为2了,再点了3 结果为m_num2= 2*10+3 = 23)
最后点击4 执行的代码是
m_num2=m_num2*10+4;(23*10 +4=234)
通过以上小例子 大家明白了吧~ 为什么要 “先乘以10 再加 数字”
总结,其实这次非主流计算器编写,(说是非主流,说白了就是有2个编辑框输入数字,人家XP只有1个编辑框)。最大的障碍就是唯独是那个EN_SETFOCUS这个函数的空白了。我只单存的百度到GetFocus()能获得焦点,但是其实问题远远并没有那么简单,涉及到很多问题。
我当初设置判断的时候还不知道用一个EN_SETFOCUS,并且初始化标记这个方法,过后才知道。我把之前的错误帖一下顺便是当作是一个警告
void CMyDlg::OnButton14Num0()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
if( GetDlgItem(IDC_EDIT1)->GetFocus())
{
m_num1=m_num1*10+0;
}
else if( GetDlgItem(IDC_EDIT2)->GetFocus())
{
m_num2=m_num2*10+0;
}
UpdateData(FALSE);
}
//
分析
GetDlgItem()如果大家不熟悉的话 我可以先解释一下是获得编辑框
首先GetDlgItem(IDC_EDIT1)获取了ID为IDC_EDIT1也就是编辑框CEdit类的对象的指针,继承了CWnd类
函数GetFocus是CWnd中的静态函数,来看一下函数原型:static CWnd* PASCAL GetFocus( ); 返回值是CWnd* 类型的,也就是说如果当前对话框或是控件被focus,那么就返回这个对话框或控件的指针.我错误的在if语句中将这个指针返回值当作了判断条件,所以呢,如果指针为NULL则if不执行,否则if就会执行。因为CEdit是一个控件类,其父窗口是有的,就是计算器的主窗口。所以当程序运行的时候,无论是第一个编辑框被focus或是第二个编辑框被focus,只要主对话框被focus了,那么调用GetDlgItem(IDC_EDIT1)->GetFocus())还是调用GetDlgItem(IDC_EDIT2)->GetFocus())还是直接调用this->GetFocus()它们的返回值都是一样的,就是父对话框的指针。当然不为NULL,所以第一个if就会执行。所以就显示在第一个编辑框了。
忙活了大半天,还是自己的积累不够。弄到最后根本不是在研究计算器怎么写的问题,而是那个GetFocus() 和EN_SETFOCUS()等问题。这几天太累了,过得浑浑噩噩,程序的进展也极其缓慢,讨厌去动手实践,往往是有想法,但是没心情去弄,我自己也深知这个是大忌,可能是最近睡眠不足吧,还有其他课程的紧张造成我不能把心思全部投入到C++中~唉是在惭愧 我也反省了~ 最后还是庆幸自己克服了困难,实现了“鼠标点击”功能吧~ 改天写一个准Windows的计算器。
不过这个那是后话了,下去目标是网络版的贪吃蛇,现在毫无头绪啊~
手把手教MFC做计算器相关推荐
- 手把手教你做关键词匹配项目(搜索引擎)---- 第九天
第九天 回顾: 8. 手把手教你做关键词匹配项目(搜索引擎)---- 第八天 7. 手把手教你做关键词匹配项目(搜索引擎)---- 第七天 6. 手把手教你做关键词匹配项目(搜索引擎)---- 第六天 ...
- python手机版做小游戏代码大全-Python大牛手把手教你做一个小游戏,萌新福利!...
原标题:Python大牛手把手教你做一个小游戏,萌新福利! 引言 最近python语言大火,除了在科学计算领域python有用武之地之外,在游戏.后台等方面,python也大放异彩,本篇博文将按照正规 ...
- jsp mysql视频_手把手教你做jsp servlet mysql实现的图书管理系统附带视频开发教程和完整源码...
上一个教程我们做的是对数据库框架底层原理的讲解,然后教大家做了一个自己的数据库框架,这次我们做的这个图书管理系统就是用我们上个教程自己写的数据库框架,整个项目做完框架运行的很稳定,没有出现任何问题.如 ...
- oracle可以在liux上装_【Oracle】手把手教你做之Linux上安装Oracle11g
手把手教你做之Linux上安装Oracle11g 这是我第一次安装时的过程,及遇到问题的解决办法,在此记录,有不妥之处,多多交流. 因为高稳定性及高定制低系统消耗等原因,我们希望在Linux上安装Or ...
- 手把手教你做关键词匹配项目(搜索引擎)---- 第二十一天
客串:屌丝的坑人表单神器.数据库那点事儿 面向对象升华:面向对象的认识----新生的初识.面向对象的番外----思想的梦游篇(1).面向对象的认识---如何找出类 负载均衡:负载均衡----概念认识篇 ...
- 手把手教你做产品经理,视频课教程已经发布,欢迎观看
手把手教你做产品经理,视频课教程已经发布,欢迎观看 http://edu.51cto.com/course/course_id-5062.html 转载于:https://blog.51cto.com ...
- 可视化实战!Python+BI,手把手教你做炫酷的NBA可视化分析
之前手痒做了一次NBA可视化分析,好多人追着我问教程,这两天终于闲下来了,花时间整理这篇NBA可视化分析教程,手把手教大家做一次炫酷的数据可视化分析! 先部分展示本次教程的作品: 数据获取 本次可视化 ...
- 易基因|干货:手把手教你做RNA m5C甲基化测序分析(RNA-BS)
大家好,这是专注表观组学十余年,领跑多组学科研服务的易基因. 本期,我们讲讲m5C RNA甲基化重亚硫酸盐测序测序(RNA-BS)实验怎么做,从技术原理.建库测序流程.信息分析流程等方面详细介绍. 一 ...
- 手把手教你做树莓派魔镜-MagicMirror(一)-准备工作
本系列文章: 手把手教你做树莓派魔镜-MagicMirror(一)-准备工作 手把手教你做树莓派魔镜-MagicMirror(二)-烧写系统卡 手把手教你做树莓派魔镜-MagicMirror(三)-系 ...
最新文章
- 《ABAQUS 6.14超级学习手册》——1.2 ABAQUS分析模块
- 写有效率的SQL查询(V)
- IT人士还是要善待自己
- DevOps:软件架构师行动指南(文摘)
- C++ 11 中的POD
- 68. Leetcode 669. 修剪二叉搜索树 (二叉搜索树-基本操作类)
- 自建K8S迁移镜像、应用至阿里云ACK最佳实践
- Mysql主从配置,实现读写分离
- 可动态调节参数的线程池实现
- 3-1HDFS基本概念
- iOS-Runtime-Headers
- 工作变得简单又高效 试试这八个WebApp
- java 数组的应用(一维)
- deepin安装卡在deepin标志界面解决方案
- 周莫凡python_机器学习 | 莫烦Python
- 由边际成本引发的思考
- 如何快速搭建php网站,如何轻松建站?站点一键部署搭建(详细教程)
- 人物-作家-卡耐基:戴尔·卡耐基
- 阿里云企业物联网平台推出千里传音播报服务 高效打造云端一体智能硬件
- 【Win 10 应用开发】MIDI 音乐合成——音符消息篇
热门文章
- 微信小程序 - 手写下拉刷新效果
- Android期末项目:美食点餐APP的设计与实现
- 使用MSComm编写串口程序
- 查找数据库中一条指定字段为NULL的数据
- 使用D435i+Avia跑Fast-LIVO
- oracle dba_profile,查询oracle的profile设置语句
- Unity (二) Animator:Events - 动画事件案例(呐喊出现字幕)
- CGCTF pwn When_did_you_born
- 模拟登录模块以及获取cookie
- 『津津乐道播客』#131. 日本异闻录·我曾经去了一个假的日本