学习MFC,可以可以锻炼c++的使用

完成一个简答的计算器,其实没有啥难度,但是 学习过较为简单的delphi,现在去使用较为复杂的mfc编程的,还是遇到一些小问题,在这里做一个总结吧,主要分为两个部分,程序的实现和MFC上陌生的概念。
程序运行结果

MFC 上遇到的困难

本次主要讲对话框。

如何手动添加自定义的消息映射函数

我在写计算器的时候想写一个能够对我按下那个按钮的来做处理的函数(如果我每个按钮来都写一个函数来处理,是不是就太烦锁了),所以我可以写一个消息映射函数 afx_msg Onnumberkey(UINT nID);
afx_msg为消息标志,它向系统声明:有消息映射到函数实现体;而在map宏定义中,就有具体消息和此函数的映射定义(可以是自定义,也可以是系统自动完成的),afx是 application framework
当然在前面加是上afx_msg是远远不够的,我们还需要在这个宏处理上加入这一段

BEGIN_MESSAGE_MAP(CCalculatorDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
//上面的是系统帮我们添加的
	ON_COMMAND_RANGE(IDC_BUTTON1, IDC_BUTTON10, OnNumberKey)
	ON_COMMAND_RANGE(IDC_BUTTON11, IDC_BUTTON20, OnOperationKey)
END_MESSAGE_MAP()//这里的语法陌生吧 这里是宏处理

ON_COMMAND_RANGE

ON_COMMAND_RANGE( id1, id2, memberFxn )
使用这个宏把一个连续范围的命令ID映射到单个命令处理函数。ID的范围从id1开始,到id2结束。
ON_COMMAND_RANGE把一个范围的命令ID映射到一个成员函数。用ON_COMMAND把单个命令ID映射到成员函数。每个给定的命令ID只能有一个消息映射入口。这就是说,不能把命令映射到多于一个的处理函数。关于映射消息范围的更多信息参见“Visual C++程序员指南”中的“消息映射范围的处理函数”。
ps 这里一定是要连续的id ,如果我们的按钮id 不连续 那就不可以这样哇。

按钮的莫名其妙

我们在写程序的时候就会遇到这样的问题
问题.png
但是我们明明定义了这按钮哇,但是为啥会没有呢。这个时候我们要就要检查这个Resource.h这个头文件了,打开它,你就会发现问题的所在。这里面存着,按钮的消息的宏定义。
Resource.h
我们通过rc2设计大量按钮的时候一定要注意,要整齐的排列他们的顺序要不然 很烦!!!!,乱复制的话 ,id和 名字很容易对不上号。

_T("") 与 L""

字符串前面加L表示该字符串是Unicode字符串。
_T是一个宏,如果项目使用了Unicode字符集(定义了UNICODE宏),则自动在字符串前面加上L,否则字符串不变。因此,Visual
C++里边定义字符串的时候,用_T来保证兼容性。VC支持ascii和unicode两种字符类型,用_T可以保证从ascii编码类型转换到unicode编码类型的时候,程序不需要修改。

字符串和整数转化 atoi()和itoa()

将整形转换为字符串型

'string itoa(int x,char *string,int jz);'
x是被转换的整数,string转换后储存字符串,jz为转换进制数,如2,8,10,16进制等

将字符串转换成一个整数值

'string atoi(s)'
如果第一个非空格字符存在,是数字或者正负号则开始做类型转换,之后检测到非数字(包括结束符 \0) 字符时停止转换,返回整型数,否则,返回零。

程序实现

CalculatorDlg.h

#pragma once


// CCalculatorDlg 对话框
class CCalculatorDlg : public CDialogEx
{
// 构造
public:
	CCalculatorDlg(CWnd* pParent = nullptr);	// 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_CALCULATOR_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;
	//自定义变量
	double number1, number2;
	int NumberState, OperationState;//标记我们对第几个number 操作,Operation 标记 我们进行那种运算
	void  cal();
	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	//自定义的消息
	afx_msg void OnNumberKey(UINT nID);//对数字按键
	afx_msg void OnOperationKey(UINT nID);//对操作按键

	DECLARE_MESSAGE_MAP()
public:
	double  m_result;//映射着输出框
};

自定的函数的实现

void CCalculatorDlg::OnNumberKey(UINT nID)
{
	int n = 0;
	switch (nID)
	{
	case IDC_BUTTON1:n = 1; break;
	case IDC_BUTTON2:n = 2; break;
	case IDC_BUTTON3:n = 3; break;
	case IDC_BUTTON4:n = 4; break;
	case IDC_BUTTON5:n = 5; break;
	case IDC_BUTTON6:n = 6; break;
	case IDC_BUTTON7:n = 7; break;
	case IDC_BUTTON8:n = 8; break;
	case IDC_BUTTON9:n = 9; break;
	case IDC_BUTTON10:n = 0; break;
	}
	if (NumberState == 1)//等于1的话就是我们现在首次输入
	{
		m_result = m_result * 10 + n;//* 10 是要 进行下一位计算
		number1 = m_result;
		UpdateData(false);
	}
	else
	{
		m_result = m_result * 10 + n;
		number2 = m_result;
		UpdateData(false);
	}
}
//对其他操作按键的处理
void CCalculatorDlg::OnOperationKey(UINT nID)
{
	switch (nID)
	{
	case IDC_BUTTON11:
	
		m_result = -m_result;
		
		if (NumberState == 1)

			number1 = m_result;
		else
			number2 = m_result;
		UpdateData(false);
		break;
	
	
	case IDC_BUTTON12:
		m_result=(int)m_result/10;
		if (NumberState == 1)

			number1 = m_result;
		else
			number2 = m_result;
		UpdateData(false);
		break;
	case IDC_BUTTON13://除法
		OperationState=1; 
		UpdateData(false);
		m_result = 0;
		NumberState = 2;//每次对一个新的运算的时候表示我已经有了一次运算结果了
		break;

	case IDC_BUTTON14:
		OperationState = 2;//乘法
		UpdateData(false);
		m_result = 0;
		NumberState = 2;
		break;
	case IDC_BUTTON15:
		OperationState = 3;//减法
		UpdateData(false);
		m_result = 0;
		NumberState = 2;
		break;
	case IDC_BUTTON16:
		OperationState = 4;//加法
		UpdateData(false);
		m_result = 0;
		NumberState = 2;
		break;
		
	case IDC_BUTTON17://c
		number1=number2=m_result=0;
		NumberState = 1;
		UpdateData(false);
		break;
	case IDC_BUTTON18:
		number1=m_result=sqrt(number1);
		UpdateData(false);
		break;
	case IDC_BUTTON19:
		if (number1 == 0)
			MessageBox(_T("零没有倒数"));
		else
		number1=m_result=1/number1;
		break;
	case IDC_BUTTON20:
		cal();
		break;
	
	}
}

void  CCalculatorDlg::cal()
{
	switch (OperationState)
	{
	case 1: //除法
		if (number2 == 0)
		{
			MessageBox(_T("零不能错除数"));
			number1 = number2 = m_result = 0;
			NumberState = 1;
			UpdateData(false);
		}else
		{
			m_result = (double)number1 / number2;
			UpdateData(false);
			number1 = m_result;
			NumberState = 2;	
		}
		break;
	case 2: //乘法
		m_result = (double)number1 *number2;
		UpdateData(false);
		number1 = m_result;
		NumberState = 2;
		break;
	case 3: //减法
		m_result = number1 - number2;
		UpdateData(false);
		number1 = m_result;
		NumberState = 2;
		break;
	case 4: //加法
		m_result = number1 + number2;
		UpdateData(false);
		number1 = m_result;
		NumberState = 2;
		break;
	}
	OperationState = 0;
}

结语

我的博客的小程序也上线了,感谢大佬爱写代码的猫 的webhalo
微信小程序

Q.E.D.


努力学习的小菜鸟