【MFC实践】基于MFC向导C++制作计算器(附文件)

2024-06-08 1457阅读

  • 一、写在前面
    • 1.1 什么是MFC向导?
    • 1.2 使用MFC向导制作计算器
    • 1.3安装visual studio 2022和MFC插件
    • 二、设计计算器界面
      • 1.1 新创建MFC项目
      • 1.2 设计计算器界面
      • 1.3 添加相关变量
      • 1.4 算法的一些问题及解决方式
      • 1.5 计算功能的实现
      • 1.6 其它功能的实现
        • 1.6.1 DEL功能
        • 1.6.2 C置零功能
        • 1.6.3 Ce清除一段字符
        • 1.6.4 %百分号功能
        • 1.6.5 倒数功能
        • 1.6.6 平方功能
        • 1.6.7 开根号功能
        • 1.6.8 说明功能

          一、写在前面

          1.1 什么是MFC向导?

          MFC(Microsoft Foundation Classes)向导是一套用于简化Windows应用程序开发的工具集。 它建立在Microsoft Foundation Classes(MFC)之上,为开发人员提供了一种更直观、高效的方式来构建图形用户界面(GUI)应用程序。MFC向导通过提供可视化设计工具、代码生成器等功能,使得开发者能够更专注于业务逻辑的实现,而不必过多关注繁琐的界面布局和控件创建。

          1.2 使用MFC向导制作计算器

          计算器项目相对简单,但涉及到了UI设计、事件处理、C++编程等方面,是一个适合初学者的实践项目。通过使用MFC向导,能够快速创建一个具有良好界面和基本功能的计算器,同时学会如何使用可视化工具来简化开发过程。以下是计算器项目示例图:

          【MFC实践】基于MFC向导C++制作计算器(附文件)

          1.3安装visual studio 2022和MFC插件

          对于未安装visual studio,下载地址:visual studio 2022 下载传送门,正常安装后,点击继续但无需代码的方式打开,在工具栏点击工具->获取工具和功能->已安装->修改

          【MFC实践】基于MFC向导C++制作计算器(附文件)

          点击单个组件,找到图示两项并勾选,最后点击窗口右下方的修改即可

          【MFC实践】基于MFC向导C++制作计算器(附文件)

          二、设计计算器界面

          1.1 新创建MFC项目

          首先基于MFC向导生成对话框文档(也可以选择单文件文档,但需要另建并加载对话框资源,看个人需求),对于初学者,建议可以取消勾选高级功能中的“公共控件清单、支持重启管理器”(不用增加额外非必要的代码),对于“文档模板属性”和“用户界面功能”默认即可。默认生成主要有主类的头文件MFCApplication1和对话框资源文件IDD_MFCAPPLICATION1_DIALOG。文件名可根据需要修改,这里只是默认文件名为例子。

          【MFC实践】基于MFC向导C++制作计算器(附文件)

          1.2 设计计算器界面

          在工具栏选择Button、Edit Control分别添加按钮、文本框等控件,鼠标选中拖动进行布局,以下是一些简单的布局技巧

          布局方式描述
          Shift多选对齐使用MFC的设计器,你可以通过按住Shift键选择多个控件,然后在属性窗口中设置它们的位置和大小,以实现对齐。
          工具栏描述
          MFC设计器Visual Studio自带的MFC设计器是一个强大的工具,可用于直观地设计和布局界面。
          控件对齐工具MFC设计器中的对齐工具可用于快速将选定的控件水平或垂直对齐,确保它们在界面上整齐排列。
          网格布局在MFC中,你可以使用网格布局管理器来自动调整控件的大小和位置,使它们在窗口中均匀分布。
          代码编辑器通过在代码中手动编辑控件的位置和大小,你可以更精细地控制布局。
          调整控件层次结构通过在层次结构视图中调整控件的嵌套关系,可以影响它们在窗口中的布局。

          布局方式就不在这赘述,懂得如何画就行,使用工具栏和工具箱完成布局和控件的添加,示例样式如下

          【MFC实践】基于MFC向导C++制作计算器(附文件)

          1.3 添加相关变量

          都知道,计算器需要一个变量来存储用户输入的表达式,输入的对象是文本编辑器,故此,应需要为文本编辑器添加一个变量,且该变量的类型应是CString(字符串类,MFC对C++标准库中的字符串类的一个扩展),但变量在类文件声明,所以在这之前应该为对话框资源添加对应的类文件MFCApplication1Dlg(类名可修改):右键对话框->添加类

          【MFC实践】基于MFC向导C++制作计算器(附文件)

          创建类之后,点击工具栏的项目->类向导->成员变量,找到编辑框的那项(本例中ID默认为IDC_Edit2),选中该项右键->添加变量,变量名和类型如下图

          【MFC实践】基于MFC向导C++制作计算器(附文件)

          变量添加完成后,就可以在对话框类文件MFCApplication1Dlg看到变量m_data

          【MFC实践】基于MFC向导C++制作计算器(附文件)

          1.4 算法的一些问题及解决方式

          接下来就是针对每个按钮写入相应消息事件,双击每个按钮跳转对话框实现文件MFCApplication1Dlg.cpp并生成对应函数(函数名与控件ID同名)。m_data变量用于存储用户输入的表达式,对于0-9和运算符按钮控件,事件分别对应不同的值输入,并且m_data是CString类型,那么可以使用下标法在字符串表达式的末尾增字符,简单示例如下:

          m_data+='0'
          m_data+='1'
          m_data+='2'
          m_data+='3'
          m_data+='4'
          m_data+='5'
          m_data+='6'
          m_data+='7'
          m_data+='8'
          m_data+='9'
          m_data+='.'
          m_data+='+'
          m_data+='-'
          m_data+='*'
          m_data+='/'
          

          每次在m_data末尾增设字符,首先需要更新编辑框的内容到变量m_data

          UpdateData();
          

          然而有以下几个问题以及应对解决代码(这里新建数组a作中间变量,i作下标),带着这些问题来设计算法,以便理解。

          • 问题1:计算器默认m_data值为0,那么在0之后的第一个字符若为数字字符,则应该覆盖0,比如控件按钮1的代码示例
            UpdateData();
            if (m_data == "0")
            {
            	i--;//下标向前指向0的位置
            	a[i] = "1";
            	m_data = a[i];//覆盖0
            }
            else
            {
            	a[i] = "1";
            	m_data += a[i];//直接追加
            }
            i++;
            
            • 问题2:若表达式最后一个字符是运算符的一种(+、- 、*、/),则一个字符不能是运算符。对于该问题可以设置一个控制变量f,置初值为1,表示可以追加运算符。
              //当点击运算符按钮,置f为0。
              f=0;
              
              //当点击除运算符以外的按钮,则重新置f为1。
              f=1;
              
              • 问题3:对于运算符’.'也有同样的问题即不能连用,这里设置控制变量pd来互斥。
                //当点击小数点按钮,置pd为1。
                f=1;
                
                //当点击除小数点按钮以外的按钮,则重新置f为0。
                f=0;
                
                • 问题4:小数点按钮和运算符按钮事件也应该相互制约
                  //当表达式最后一个字符是运算符,若要添加小数点则应先追加0
                  if (a[i - 1] == "+" || a[i - 1] == "-" || a[i - 1] == "*" || a[i - 1] == "/")
                  {
                  	a[i] = "0";
                  	m_data += a[i];//先追加0
                  	i++;
                  	a[i] = ".";
                  	m_data += a[i];//再追加小数点
                  }
                  else
                  {
                  	a[i] = ".";
                  	m_data += a[i];//直接追加小数点
                  }
                  i++;
                  f = 0;
                  
                  //当表达式最后一个字符是小数点,若要添加运算符则应覆盖小数点
                  //比如加法,其它运算符按钮响应事件也如此
                  if (a[i - 1] == ".")
                  {
                  	i--;
                  	a[i] = "+";
                  	// 获取最后一个字符的索引
                  	int lastIndex = m_data.GetLength() - 1;
                  	// 替换最后一个字符为 '+'
                  	m_data.SetAt(lastIndex, _T('+'));//覆盖
                  }
                  else
                  {
                  	a[i] = "+";
                  	m_data += a[i];//直接追加
                  }
                  f = 1;
                  i++;
                  

                  1.5 计算功能的实现

                  变量m_data是CString类型,用于存储计算表达式,包含加减乘除运算符和小数点符号,对于运算优先级的处理方式:首先定义三个变量用于下标取值p、left、right。外循环p获取m_data字符串的乘除运算符,内循环left和right分别指向p所指向运算符左右两侧的运算符,用m_data.Mid()函数截取p所指运算符两侧的数字,根据判断p指向的运算符进行乘法或者除法运算,最后使用m_data.Delete()和 m_data.Insert()函数替换运算结果。

                  void CMFCApplication1Dlg::OnBnClickedEqual()
                  {
                  	int length = m_data.GetLength();
                  	int left = 0, right = 0, p = 0;
                  	//先乘除
                  	for (p = 0; p  '9')
                  		{
                  			left = p - 1;
                  			right = p + 1;
                  			while (left >= 0)
                  			{
                  				if (m_data.GetAt(left) == '0' || m_data.GetAt(left) == '1' || m_data.GetAt(left) == '2' || m_data.GetAt(left) == '3' || m_data.GetAt(left) == '4' || m_data.GetAt(left) == '5' || m_data.GetAt(left) == '6' || m_data.GetAt(left) == '7' || m_data.GetAt(left) == '8' || m_data.GetAt(left) == '9' || m_data.GetAt(left) == '.')
                  				{
                  					left--;
                  				}
                  				else break;
                  			}
                  			while (right  '9')
                  		{
                  			left = p - 1;
                  			right = p + 1;
                  			while (left >= 0)
                  			{
                  				if (m_data.GetAt(left) == '0' || m_data.GetAt(left) == '1' || m_data.GetAt(left) == '2' || m_data.GetAt(left) == '3' || m_data.GetAt(left) == '4' || m_data.GetAt(left) == '5' || m_data.GetAt(left) == '6' || m_data.GetAt(left) == '7' || m_data.GetAt(left) == '8' || m_data.GetAt(left) == '9' || m_data.GetAt(left) == '.')
                  				{
                  					left--;
                  				}
                  				else break;
                  			}
                  			while (right  
                  

                  1.6 其它功能的实现

                  1.6.1 DEL功能

                  作用删除表达式的上一个字符

                  void CMFCApplication1Dlg::OnBnClickedDel()
                  {
                  	UpdateData();  // 更新 m_data 长度
                  	// 获取当前的字符串长度
                  	int length = m_data.GetLength();
                  	// 检查字符串是否为空
                  	if (length > 0)
                  	{
                  		// 如果字符串长度大于1,删除最后一个字符
                  		if (length > 1)
                  		{
                  			a[i] = '\0';
                  			m_data.Delete(length - 1, 1);
                  		}
                  		else
                  		{
                  			// 如果字符串只剩最后一个字符,将m_data设置为"0"
                  			a[i] = '0';
                  			m_data = _T("0");
                  		}
                  		// 更新界面上的文本框等显示
                  		UpdateData(FALSE);
                  	}
                  	f = 0;
                  	pd = 0;
                  	UpdateData(false);
                  }
                  

                  1.6.2 C置零功能

                  void CMFCApplication1Dlg::OnBnClickedC()
                  {
                  	m_data = "0";//置零
                  	UpdateData(false);
                  }
                  

                  1.6.3 Ce清除一段字符

                  void CMFCApplication1Dlg::OnBnClickedCe()
                  {
                  	// TODO: 在此添加控件通知处理程序代码
                  	int p = m_data.GetLength()-1;
                  	while (p>=0)
                  	{
                  		if (m_data.GetAt(p) == '+' || m_data.GetAt(p) == '-' || m_data.GetAt(p) == '/' || m_data.GetAt(p) == '*')
                  		{
                  			break;
                  		}
                  		p--;
                  	}
                  	m_data.Delete(p+1, m_data.GetLength() - 1-p);
                  	UpdateData(false);
                  }
                  

                  1.6.4 %百分号功能

                  void CMFCApplication1Dlg::OnBnClickedFeature6()
                  {
                  	int p = m_data.GetLength() - 1;
                  	while (p >= 0)
                  	{
                  		if (m_data.GetAt(p) == '+' || m_data.GetAt(p) == '-' || m_data.GetAt(p) == '/' || m_data.GetAt(p) == '*')
                  		{
                  			break;
                  		}
                  		p--;
                  	}
                  	CString a = m_data.Mid(p + 1, m_data.GetLength() - 1 - p);
                  	m_data.Delete(p + 1, m_data.GetLength() - 1 - p);
                  	double b = _ttof(a) * 0.01;
                  	a.Format(_T("%f"), b);
                  	m_data.Insert(p + 1, a);
                  	UpdateData(false);
                  }
                  

                  1.6.5 倒数功能

                  void CMFCApplication1Dlg::OnBnClickedFeature3()
                  {
                  	int p = m_data.GetLength() - 1;
                  	while (p >= 0)
                  	{
                  		if (m_data.GetAt(p) == '+' || m_data.GetAt(p) == '-' || m_data.GetAt(p) == '/' || m_data.GetAt(p) == '*')
                  		{
                  			break;
                  		}
                  		p--;
                  	}
                  	CString a = m_data.Mid(p + 1, m_data.GetLength() - 1 - p);
                  	m_data.Delete(p + 1, m_data.GetLength() - 1 - p);
                  	double b =1/ _ttof(a) ;
                  	a.Format(_T("%f"), b);
                  	m_data.Insert(p + 1, a);
                  	UpdateData(false);
                  }
                  

                  1.6.6 平方功能

                  void CMFCApplication1Dlg::OnBnClickedFeature4()
                  {
                  	// TODO: 在此添加控件通知处理程序代码
                  	int p = m_data.GetLength() - 1;
                  	while (p >= 0)
                  	{
                  		if (m_data.GetAt(p) == '+' || m_data.GetAt(p) == '-' || m_data.GetAt(p) == '/' || m_data.GetAt(p) == '*')
                  		{
                  			break;
                  		}
                  		p--;
                  	}
                  	CString a = m_data.Mid(p + 1, m_data.GetLength() - 1 - p);
                  	m_data.Delete(p + 1, m_data.GetLength() - 1 - p);
                  	double b = _ttof(a) * _ttof(a);
                  	a.Format(_T("%f"), b);
                  	m_data.Insert(p + 1, a);
                  	UpdateData(false);
                  }
                  

                  1.6.7 开根号功能

                  void CMFCApplication1Dlg::OnBnClickedFeature5()
                  {
                  	// TODO: 在此添加控件通知处理程序代码
                  	int p = m_data.GetLength() - 1;
                  	while (p >= 0)
                  	{
                  		if (m_data.GetAt(p) == '+' || m_data.GetAt(p) == '-' || m_data.GetAt(p) == '/' || m_data.GetAt(p) == '*')
                  		{
                  			break;
                  		}
                  		p--;
                  	}
                  	CString a = m_data.Mid(p + 1, m_data.GetLength() - 1 - p);
                  	m_data.Delete(p + 1, m_data.GetLength() - 1 - p);
                  	double b = sqrt(_ttof(a)) ;
                  	a.Format(_T("%f"), b);
                  	m_data.Insert(p + 1, a);
                  	UpdateData(false);
                  }
                  

                  1.6.8 说明功能

                  void CMFCApplication1Dlg::OnBnClickedFeature1()
                  {
                  	MessageBox("1. 百分比计算(%)\n输入一个数字,然后使用百分号(% )进行百分比计算。计算器将返回输入数的百分之一。\n2. 删除字符或运算符(del)\n通过按下“del”按钮,可以删除最后一个输入的字符或运算符。这有助于纠正输入错误。\n3. 清零(C)\n按下“C”按钮将清空当前输入的所有内容,使计算器重置为零状态。\n4. 清除最后一个数(CE)\n使用“CE”按钮可以清除输入的最后一个数字,保留其他输入和运算符。");
                  }
                  
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]