MFC简易计算器的实现
MFC简易计算器的实现
1 概述
1.1 第一步
添加组件 界面布局:根据所要的需求+-*/,四则运算,科学运算等,设计一下布局
1.2 第二步
给各个组件 按钮和文本框添加函数:设置它的相应函数
1.3 第三步
测试:看看有没有问题
2 第一步 添加组件 界面布局
实际上,0、1、2、3并没有全都用到,只用了1 HuangPengcalculator.rc和3 HuangPengcalculator.cpp这两个也可以实现简易的计算器
2.1 HuangPengcalculatorapp.rc
先设置界面布局,添加组件,所添加的组件都会在Resource.h里面自动生成
按住Ctrl可以多选,进行多个组件的复制操作
对各个组件进行相应设计,得到最终的界面布局
2.2 描述文字 ID
在属性列表里面,对各个组件(按钮和文本框)进行命名(描述文字),并按顺序、条理修改对应的ID,以免出现混乱对应不上的问题
所定义的这些按钮以及编辑框就都会出现在Resource.h里面
3 第二步 给各个组件 按钮和文本框添加函数
3.1 依次双击控件按钮和两个编辑框
依次(Button1到Button19)双击控件按钮和两个编辑框,会在“计算器Dlg.cpp”生成代码 ,到时候控件响应事件就是在这里做的(推荐将除了数字以外的按钮的ID改成英文来区别,如乘法:ButtonMut)
要对哪个组件 按钮和文本框添加函数只需要双击这个组件(按钮或文本框),便可快速进入到.cpp的相应函数位置,然后对这个函数进行具体的实现,即可完成该组件(按钮或文本框)的函数添加
3.2 对两编辑框添加变量
右键第一个编辑框选择添加变量,添加一个value的CString类型的变量mStr,这个变量绑定了编辑框1,我们就通过操作这个变量来实现按钮响应的可视化,就是说输入哪一个数字都会显示在第一个编辑框内。
第二个edit,我们需要右键添加变量,给他绑定一个private的vlaue的double的mResult,这个是用来接收结果的,因此第二个编辑框也就是用来显示结果的。
3.3 按钮添加响应事件
进入计算器Dlg.cpp(你自己的工程叫XXX就是XXXDlg.cpp),为按钮添加响应事件,代码如下。
void CHuangPengcalculatorDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr+L"1";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
添加完后就可以调试运行一下了,写程序我们要学会调试,调试的过程中寻求反馈,菜鸟程序员不要一码到底不然很容易对编程失去兴趣。(毛主席说过,越是困难的时候越是要看到光明,大概就是这个意思吧)
接下来将其他同类型的按钮也添加响应事件,包括Button2-Button11如下面代码所示:
void CHuangPengcalculatorDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr+L"1";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"2";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"3";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"4";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton5()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"5";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton6()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"6";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton7()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"7";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton8()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"8";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton9()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"9";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton0()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"0";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
3.4 在Dlg.h里面添加一些变量和函数
我们要在"计算器Dlg.h"(XXXDlg.h)里面添加一些变量和函数,代码如下:
/*这两个函数都要在Dlg.cpp里面重写*/
void SaveFirstValue();//这个是用来保存一个输入完成的值的
void Calculator();//这个是用来实现计算的
private:
double mNum1;//第一个值
double mNum2;//第二个值
int mFlag;//传递运算符,来触发switch中的事件
CString mStr;//这个是edit1绑定的值,字符串类型,不用自己手动定义
double mResult;//这个是edit2绑定的值,double型,不用手动定义
转到“计算器Dlg.cpp”重写上面两个关键函数,在程序末尾写:
void CHuangPengcalculatorDlg::SaveFirstValue()
{
UpdateData(TRUE);//刷新应用状态
mNum1 = _wtof(mStr);//“_wtof”可以将CString转换成double型
mStr = L"";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::Calculator()
{
UpdateData(TRUE);
mNum2 = _wtof(mStr);
switch (mFlag)//按接收键传过来的mFlag的值,以此来判断是什么运算符
{
case 1:
mResult = mNum1 + mNum2;
break;
case 2:
mResult = mNum1 - mNum2;
break;
case 3:
mResult = mNum1 * mNum2;
break;
case 4:
mResult = mNum1 / mNum2;
break;
case 5:
mResult = pow(mNum1, mNum2);
break;
case 6:
{
if (mNum1 < 0 || mNum2 < 0 || mNum1 == 1)
{
MessageBox(TEXT("该对数无效,请重新输入!"));
mStr = "";
return;
}
else
mResult = log(mNum2) / log(mNum1);
break;
}
case 7:
{
double item = 1;
mResult = 1;
int i = 1;
do
{
item = item * mNum2 / i;
i++;
mResult += item;
} while (fabs(item) > 1e-6);
break;
}
case 8:
{
mResult = 1.0;
for (long long i = 1; i <= long long(mNum1); i++)
mResult *= i;
break;
}
case 9:
{
long long num = mNum2;
num %= 360;
mNum1 = num;
mNum1 = mNum1 / 180 * 3.1415926;
double item = mNum1;
mResult = mNum1;
long long i = 1;
do
{
item = -item * mNum1 * mNum1 / ((2 * i) * (2 * i + 1));
mResult += item;//sinx=x-x^3/3!+x^5/5!-x^7/7!+...
i++;
} while (fabs(item) >= 1e-5);//当精度达到10的五次方时跳出
break;
}
case 10:
{
long long num = mNum2;
num %= 360;
mNum1 = num;
mNum1 = mNum1 / 180 * 3.1415926;
double item = 1;
mResult = 1;
long long i = 1;
do
{
item = -item * mNum1 * mNum1 / ((2 * i) * (2 * i - 1));
mResult += item;//cosx=1-x^2/2!+x^4/4!-x^6/6!+...
i++;
} while (fabs(item) >= 1e-5);//当精度达到10的五次方时跳出
break;
}
case 11:
{
long long num = mNum2;
num %= 180;
if (num == 90 || num == -90)//去除不再范围内的数
{
MessageBox(TEXT("此值不在正切函数的有效区域内,请重新输入"));
}
else
{
mNum1 = num;//将大度数化小
mNum1 = mNum1 / 180 * 3.1415926;//化为弧度制
mResult = tan(mNum1);
}
break;
}
case 12:
mResult = sqrt(mNum1);
break;
}
UpdateData(FALSE);
}
同样是在“计算器Dlg.cpp”下一步将添加运算符响应事件,添加在数字按钮后最好:(顺序为等于、加、减、乘、除):
void CHuangPengcalculatorDlg::OnBnClickedButtonjia()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 1;//加法的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonjian()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 2;//减法的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtoncheng()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 3;//乘法的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonchu()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 4;//除法的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonpoint()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L".";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButtoncifang()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 5;//指数(次方)的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonlognx()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 6;//对数lognx的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonex()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 7;//e^x的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonx()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 8;//x!的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonsin()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 9;//sin的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtoncos()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 10;//cos的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtontan()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 11;//tan的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonsqrt()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 12;//开方的功能
}
3.5 添加"清除"、“删除”、“退出”
还是在“计算器Dlg.cpp”
void CHuangPengcalculatorDlg::OnBnClickedButtonback()//删除最后一个数字
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(FALSE);//将数据更新到控件
if (!mStr.IsEmpty())
{
mStr = mStr.Left(mStr.GetLength() - 1);//删除最右边一位
}
UpdateData(FALSE);//将数据更新到控件
}
void CHuangPengcalculatorDlg::OnBnClickedButtonclear()//清除键,归零键
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
mStr = L"0";//字符串前加L就是把数据转换成Unicode格式
mResult = 0.0;
mNum1 = 0.0f;
mNum2 = 0.0f;
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButtonexit()//退出软件
{
// TODO: 在此添加控件通知处理程序代码
exit(0);
}
3.6 添加支持键盘操作的功能
描述:可以通过小键盘来用计算器,按回车键计算结果,按Backspace删除最后一位数字。
右键单击对话框,选择添加“类向导”,选择“虚函数”,选择下面这个函数,双击它,应用。
然后返回到“计算器Dlg.cpp”找到刚刚添加的类,在里面添加键盘按键响应事件。
BOOL CHuangPengcalculatorDlg::PreTranslateMessage(MSG* pMsg)//支持键盘操作
{
// TODO: 在此添加专用代码和/或调用基类
if (pMsg->message == WM_KEYDOWN)
{
if (pMsg->wParam == VK_RETURN)//回车键
{
Calculator();
}
if (pMsg->wParam == VK_BACK)//删除键
{
CHuangPengcalculatorDlg::OnBnClickedButtonback();
}
if (pMsg->wParam == VK_ADD)//加法键
{
CHuangPengcalculatorDlg::OnBnClickedButtonjia();
}
if (pMsg->wParam == VK_SUBTRACT)//减法键
{
CHuangPengcalculatorDlg::OnBnClickedButtonjian();
}
if (pMsg->wParam == VK_MULTIPLY)//乘法键
{
CHuangPengcalculatorDlg::OnBnClickedButtoncheng();
}
if (pMsg->wParam == VK_DIVIDE)//除法键
{
CHuangPengcalculatorDlg::OnBnClickedButtonchu();
}
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) return TRUE;//屏蔽esc键
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) return TRUE;//屏蔽回车键,让他不再退出
else
return CDialogEx::PreTranslateMessage(pMsg);
}
在属性页将edit1设置成只能输入数字
将edit2设置成只读
运行成功!你可以在工程文件的Debug目录下找到“.exe”文件。
4 第三步 测试:看看有没有问题
整个MFC简易计算器的代码如下:
4.1 Dlg.h
// HuangPengcalculatorDlg.h: 头文件
//
#pragma once
// CHuangPengcalculatorDlg 对话框
class CHuangPengcalculatorDlg : public CDialogEx
{
// 构造
public:
CHuangPengcalculatorDlg(CWnd* pParent = nullptr); // 标准构造函数
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_HUANGPENGCALCULATOR_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButton1();
afx_msg void OnBnClickedButton2();
afx_msg void OnBnClickedButton3();
afx_msg void OnBnClickedButton4();
afx_msg void OnBnClickedButton5();
afx_msg void OnBnClickedButton6();
afx_msg void OnBnClickedButton7();
afx_msg void OnBnClickedButton8();
afx_msg void OnBnClickedButton9();
afx_msg void OnBnClickedButton0();
afx_msg void OnBnClickedButtonjia();
afx_msg void OnBnClickedButtonjian();
afx_msg void OnBnClickedButtoncheng();
afx_msg void OnBnClickedButtonchu();
afx_msg void OnBnClickedButtonpoint();
afx_msg void OnBnClickedButtoncifang();
afx_msg void OnBnClickedButtonlognx();
afx_msg void OnBnClickedButtonex();
afx_msg void OnBnClickedButtonx();
afx_msg void OnBnClickedButtonsin();
afx_msg void OnBnClickedButtoncos();
afx_msg void OnBnClickedButtontan();
afx_msg void OnBnClickedButtonsqrt();
afx_msg void OnBnClickedButtonequal();
afx_msg void OnBnClickedButtonback();
afx_msg void OnBnClickedButtonclear();
afx_msg void OnEnChangeEdit1();
afx_msg void OnEnChangeEdit2();
/*这两个函数都要在Dlg.cpp里面重写*/
void SaveFirstValue();//这个是用来保存一个输入完成的值的
void Calculator();//这个是用来实现计算的
private:
double mNum1;//第一个值
double mNum2;//第二个值
int mFlag;//传递运算符,来触发switch中的事件
CString mStr;//这个是edit1绑定的值,字符串类型,不用自己手动定义
double mResult;//这个是edit2绑定的值,double型,不用手动定义
public:
afx_msg void OnBnClickedButtonexit();
virtual BOOL PreTranslateMessage(MSG* pMsg);
};
4.2 Dlg.cpp
// HuangPengcalculatorDlg.cpp: 实现文件
//
#include "pch.h"
#include "framework.h"
#include "HuangPengcalculator.h"
#include "HuangPengcalculatorDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CHuangPengcalculatorDlg 对话框
CHuangPengcalculatorDlg::CHuangPengcalculatorDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_HUANGPENGCALCULATOR_DIALOG, pParent)
, mStr(_T(""))
, mResult(0)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CHuangPengcalculatorDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, mStr);
DDX_Text(pDX, IDC_EDIT2, mResult);
}
BEGIN_MESSAGE_MAP(CHuangPengcalculatorDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CHuangPengcalculatorDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON2, &CHuangPengcalculatorDlg::OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON3, &CHuangPengcalculatorDlg::OnBnClickedButton3)
ON_BN_CLICKED(IDC_BUTTON4, &CHuangPengcalculatorDlg::OnBnClickedButton4)
ON_BN_CLICKED(IDC_BUTTON5, &CHuangPengcalculatorDlg::OnBnClickedButton5)
ON_BN_CLICKED(IDC_BUTTON6, &CHuangPengcalculatorDlg::OnBnClickedButton6)
ON_BN_CLICKED(IDC_BUTTON7, &CHuangPengcalculatorDlg::OnBnClickedButton7)
ON_BN_CLICKED(IDC_BUTTON8, &CHuangPengcalculatorDlg::OnBnClickedButton8)
ON_BN_CLICKED(IDC_BUTTON9, &CHuangPengcalculatorDlg::OnBnClickedButton9)
ON_BN_CLICKED(IDC_BUTTON0, &CHuangPengcalculatorDlg::OnBnClickedButton0)
ON_BN_CLICKED(IDC_BUTTONJIA, &CHuangPengcalculatorDlg::OnBnClickedButtonjia)
ON_BN_CLICKED(IDC_BUTTONJIAN, &CHuangPengcalculatorDlg::OnBnClickedButtonjian)
ON_BN_CLICKED(IDC_BUTTONCHENG, &CHuangPengcalculatorDlg::OnBnClickedButtoncheng)
ON_BN_CLICKED(IDC_BUTTONCHU, &CHuangPengcalculatorDlg::OnBnClickedButtonchu)
ON_BN_CLICKED(IDC_BUTTONPOINT, &CHuangPengcalculatorDlg::OnBnClickedButtonpoint)
ON_BN_CLICKED(IDC_BUTTONCIFANG, &CHuangPengcalculatorDlg::OnBnClickedButtoncifang)
ON_BN_CLICKED(IDC_BUTTONLOGNX, &CHuangPengcalculatorDlg::OnBnClickedButtonlognx)
ON_BN_CLICKED(IDC_BUTTONEX, &CHuangPengcalculatorDlg::OnBnClickedButtonex)
ON_BN_CLICKED(IDC_BUTTONX, &CHuangPengcalculatorDlg::OnBnClickedButtonx)
ON_BN_CLICKED(IDC_BUTTONSIN, &CHuangPengcalculatorDlg::OnBnClickedButtonsin)
ON_BN_CLICKED(IDC_BUTTONCOS, &CHuangPengcalculatorDlg::OnBnClickedButtoncos)
ON_BN_CLICKED(IDC_BUTTONTAN, &CHuangPengcalculatorDlg::OnBnClickedButtontan)
ON_BN_CLICKED(IDC_BUTTONSQRT, &CHuangPengcalculatorDlg::OnBnClickedButtonsqrt)
ON_BN_CLICKED(IDC_BUTTONEQUAL, &CHuangPengcalculatorDlg::OnBnClickedButtonequal)
ON_BN_CLICKED(IDC_BUTTONBACK, &CHuangPengcalculatorDlg::OnBnClickedButtonback)
ON_BN_CLICKED(IDC_BUTTONCLEAR, &CHuangPengcalculatorDlg::OnBnClickedButtonclear)
ON_EN_CHANGE(IDC_EDIT1, &CHuangPengcalculatorDlg::OnEnChangeEdit1)
ON_EN_CHANGE(IDC_EDIT2, &CHuangPengcalculatorDlg::OnEnChangeEdit2)
ON_BN_CLICKED(IDC_BUTTONEXIT, &CHuangPengcalculatorDlg::OnBnClickedButtonexit)
END_MESSAGE_MAP()
// CHuangPengcalculatorDlg 消息处理程序
BOOL CHuangPengcalculatorDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CHuangPengcalculatorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CHuangPengcalculatorDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CHuangPengcalculatorDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CHuangPengcalculatorDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr+L"1";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"2";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"3";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"4";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton5()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"5";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton6()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"6";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton7()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"7";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton8()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"8";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton9()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"9";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButton0()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L"0";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButtonjia()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 1;//加法的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonjian()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 2;//减法的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtoncheng()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 3;//乘法的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonchu()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 4;//除法的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonpoint()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//刷新应用状态
mStr = mStr + L".";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButtoncifang()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 5;//指数(次方)的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonlognx()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 6;//对数lognx的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonex()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 7;//e^x的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonx()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 8;//x!的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonsin()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 9;//sin的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtoncos()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 10;//cos的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtontan()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 11;//tan的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonsqrt()
{
// TODO: 在此添加控件通知处理程序代码
SaveFirstValue();
mFlag = 12;//开方的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonequal()
{
// TODO: 在此添加控件通知处理程序代码
Calculator();//等于号的功能
}
void CHuangPengcalculatorDlg::OnBnClickedButtonback()//删除最后一个数字
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(FALSE);//将数据更新到控件
if (!mStr.IsEmpty())
{
mStr = mStr.Left(mStr.GetLength() - 1);//删除最右边一位
}
UpdateData(FALSE);//将数据更新到控件
}
void CHuangPengcalculatorDlg::OnBnClickedButtonclear()//清除键,归零键
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
mStr = L"0";//字符串前加L就是把数据转换成Unicode格式
mResult = 0.0;
mNum1 = 0.0f;
mNum2 = 0.0f;
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::OnBnClickedButtonexit()//退出软件
{
// TODO: 在此添加控件通知处理程序代码
exit(0);
}
void CHuangPengcalculatorDlg::OnEnChangeEdit1()
{
// TODO: 如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CDialogEx::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 在此添加控件通知处理程序代码
}
void CHuangPengcalculatorDlg::OnEnChangeEdit2()
{
// TODO: 如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CDialogEx::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 在此添加控件通知处理程序代码
}
void CHuangPengcalculatorDlg::SaveFirstValue()
{
UpdateData(TRUE);//刷新应用状态
mNum1 = _wtof(mStr);//“_wtof”可以将CString转换成double型
mStr = L"";//字符前加L是把字符转换成Unicode型
UpdateData(FALSE);
}
void CHuangPengcalculatorDlg::Calculator()
{
UpdateData(TRUE);
mNum2 = _wtof(mStr);
switch (mFlag)//按接收键传过来的mFlag的值,以此来判断是什么运算符
{
case 1:
mResult = mNum1 + mNum2;
break;
case 2:
mResult = mNum1 - mNum2;
break;
case 3:
mResult = mNum1 * mNum2;
break;
case 4:
mResult = mNum1 / mNum2;
break;
case 5:
mResult = pow(mNum1, mNum2);
break;
case 6:
{
if (mNum1 < 0 || mNum2 < 0 || mNum1 == 1)
{
MessageBox(TEXT("该对数无效,请重新输入!"));
mStr = "";
return;
}
else
mResult = log(mNum2) / log(mNum1);
break;
}
case 7:
{
double item = 1;
mResult = 1;
int i = 1;
do
{
item = item * mNum2 / i;
i++;
mResult += item;
} while (fabs(item) > 1e-6);
break;
}
case 8:
{
mResult = 1.0;
for (long long i = 1; i <= long long(mNum1); i++)
mResult *= i;
break;
}
case 9:
{
long long num = mNum2;
num %= 360;
mNum1 = num;
mNum1 = mNum1 / 180 * 3.1415926;
double item = mNum1;
mResult = mNum1;
long long i = 1;
do
{
item = -item * mNum1 * mNum1 / ((2 * i) * (2 * i + 1));
mResult += item;//sinx=x-x^3/3!+x^5/5!-x^7/7!+...
i++;
} while (fabs(item) >= 1e-5);//当精度达到10的五次方时跳出
break;
}
case 10:
{
long long num = mNum2;
num %= 360;
mNum1 = num;
mNum1 = mNum1 / 180 * 3.1415926;
double item = 1;
mResult = 1;
long long i = 1;
do
{
item = -item * mNum1 * mNum1 / ((2 * i) * (2 * i - 1));
mResult += item;//cosx=1-x^2/2!+x^4/4!-x^6/6!+...
i++;
} while (fabs(item) >= 1e-5);//当精度达到10的五次方时跳出
break;
}
case 11:
{
long long num = mNum2;
num %= 180;
if (num == 90 || num == -90)//去除不再范围内的数
{
MessageBox(TEXT("此值不在正切函数的有效区域内,请重新输入"));
}
else
{
mNum1 = num;//将大度数化小
mNum1 = mNum1 / 180 * 3.1415926;//化为弧度制
mResult = tan(mNum1);
}
break;
}
case 12:
mResult = sqrt(mNum1);
break;
}
UpdateData(FALSE);
}
BOOL CHuangPengcalculatorDlg::PreTranslateMessage(MSG* pMsg)//支持键盘操作
{
// TODO: 在此添加专用代码和/或调用基类
if (pMsg->message == WM_KEYDOWN)
{
if (pMsg->wParam == VK_RETURN)//回车键
{
Calculator();
}
if (pMsg->wParam == VK_BACK)//删除键
{
CHuangPengcalculatorDlg::OnBnClickedButtonback();
}
if (pMsg->wParam == VK_ADD)//加法键
{
CHuangPengcalculatorDlg::OnBnClickedButtonjia();
}
if (pMsg->wParam == VK_SUBTRACT)//减法键
{
CHuangPengcalculatorDlg::OnBnClickedButtonjian();
}
if (pMsg->wParam == VK_MULTIPLY)//乘法键
{
CHuangPengcalculatorDlg::OnBnClickedButtoncheng();
}
if (pMsg->wParam == VK_DIVIDE)//除法键
{
CHuangPengcalculatorDlg::OnBnClickedButtonchu();
}
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) return TRUE;//屏蔽esc键
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) return TRUE;//屏蔽回车键,让他不再退出
else
return CDialogEx::PreTranslateMessage(pMsg);
}
4.3 整体
5 相应功能对应的代码
5.1 lognx
case 6:
{
if (mNum1 < 0 || mNum2 < 0 || mNum1 == 1)
{
MessageBox(TEXT("该对数无效,请重新输入!"));
mStr = "";
return;
}
else
mResult = log(mNum2) / log(mNum1);
break;
}
5.2 e^x
case 7:
{
double item = 1;
mResult = 1;
int i = 1;
do
{
item = item * mNum2 / i;
i++;
mResult += item;
} while (fabs(item) > 1e-6);
break;
}
5.3 x!
case 8:
{
mResult = 1.0;
for (long long i = 1; i <= long long(mNum1); i++)
mResult *= i;
break;
}
5.4 sin
case 9:
{
long long num = mNum2;
num %= 360;
mNum1 = num;
mNum1 = mNum1 / 180 * 3.1415926;
double item = mNum1;
mResult = mNum1;
long long i = 1;
do
{
item = -item * mNum1 * mNum1 / ((2 * i) * (2 * i + 1));
mResult += item;//sinx=x-x^3/3!+x^5/5!-x^7/7!+...
i++;
} while (fabs(item) >= 1e-5);//当精度达到10的五次方时跳出
break;
}
5.5 cos
case 10:
{
long long num = mNum2;
num %= 360;
mNum1 = num;
mNum1 = mNum1 / 180 * 3.1415926;
double item = 1;
mResult = 1;
long long i = 1;
do
{
item = -item * mNum1 * mNum1 / ((2 * i) * (2 * i - 1));
mResult += item;//cosx=1-x^2/2!+x^4/4!-x^6/6!+...
i++;
} while (fabs(item) >= 1e-5);//当精度达到10的五次方时跳出
break;
}
5.6 tan
case 11:
{
long long num = mNum2;
num %= 180;
if (num == 90 || num == -90)//去除不再范围内的数
{
MessageBox(TEXT("此值不在正切函数的有效区域内,请重新输入"));
}
else
{
mNum1 = num;//将大度数化小
mNum1 = mNum1 / 180 * 3.1415926;//化为弧度制
mResult = tan(mNum1);
}
break;
}
5.7 sqrt
case 12:
mResult = sqrt(mNum1);
break;
}
计算器当中基本的输入,输出,计算,转换,归零,删除等操作
Dlag.h 声明,调用
Dlag.cpp 定义,实现
导入图片
6 简易计算器的优化
6.1 左上角关于窗口内容的修改
Dlg.h的文件>>资源视图>>IDD_ABOUTBOX>>在关于窗口内进行修改相关的内容
修改成如下格式
6.2 MFC自定义窗口添加背景图片
第一步 在Dlg.cpp的初始化函数OnInitDialog()里面添加背景图片的相关代码
// TODO: 在此添加额外的初始化代码
CString sPath = _T("E:\\C++\\C++课程学习\\大作业\\HuangPengcalculator\\HuangPengcalculator\\res\\picture.jfif");//图片所存放的位置
CImage img;//创建一个空白的图片对象img
img.Load(sPath);//将图片背景载入到img里,此时img就可以代表图片了
HBITMAP hbmp=img.Detach();//HBIT是windows位图的句柄;Detach释放图片资源,img.Detach释放之后会放回一个HBITMAP类型的值
CBitmap bmp;//CBit是C++中的位图对象
bmp.Attach(hbmp);//将bmp和图片资源hbmp绑定
m_bgBrush.CreatePatternBrush(&bmp);//CreatePatternBrush的作用是初始化使用位图指定模式的笔画,此时已经创建了设置背景时会使用到的笔刷
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
/*
图片所存放的位置的注意事项
1.要用“\\”,而不能用“\”
2.picture.jfif要带有图片文件的类型“.jfif”,不能只写picture,否则无法正常编译
E:\\C++\\C++课程学习\\大作业\\HuangPengcalculator\\HuangPengcalculator\\res\\picture.jfif
*/
第二步 在头文件Dlg.h的public域下加以下代码
public:
CBrush m_bgBrush;//设置背景图片的成员变量m_bgBrush
第三步 项目>>类向导>>消息>>搜索两个函数WM_CTLCOLOR(控制窗口显示样式的消息响应函数)和WM_NCHITTEST>>并双击这两个函数进行添加>>于是在Dlg.cpp最底下会出现这两个函数对应的代码>>对这两个函数内部添加代码
第四步 对这两个函数内部添加代码
HBRUSH CHuangPengcalculatorDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)//OnCtlColor函数是控制我们窗口显示样式的响应函数;pWnd是窗口的指针
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: 在此更改 DC 的任何特性
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
if (pWnd==this)//如果pWnd==this是我们的当前窗口的话,就把我们刚刚创建的背景底数给它返回
{
return m_bgBrush;
}
return hbr;
}
LRESULT CHuangPengcalculatorDlg::OnNcHitTest(CPoint point)//如果当设置类型去掉了默认的标题栏,就无法拖动窗口了,该函数用于解决此情况窗口不能拖动的情况
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
LRESULT ret = CDialogEx::OnNcHitTest(point);//CDialogEx::OnNcHitTest(point)是一个LRESULT类型的返回值
return ret == HTCLIENT ? HTCAPTION: ret;//判断,这个ret是我们接收到的消息,HTCLIENT表示的是窗口,如果接收到的消息是窗口的话,此时因为设置去掉了默认的标题栏,就应该把这个消息改成标题栏,返回一个HTCAPTION,HTCAPTION表示模拟一个标题,这样窗口就改成标题栏了,就可以拖动了;如果不是窗口HTCLIENT,就把ret原路返回,因为此时的窗口自带默认的标题栏可以拖动
}
7 MFC的帮助文档
7.1 在Visual Studio界面查找MFC文档
7.2 在百度上搜索MFC的帮助文档网址
MFC的帮助文档网址:https://learn.microsoft.com/zh-cn/cpp/mfc/,查找帮助MFC文档
8 Visual Studio的调试方法
8.1 直接运行调试
直接运行调试,根据错误列表,进行修改