参考资料:

     1.MFC响应键盘
     2.计算器实例
     3.MFC文件对话框
     4.MFCUpdateData()函数的使用
     5.MFC教程
     6.winuser.h
     7.C++ 中int,char,string,CString类型转换

GitHub链接:传送门

题目链接:传送门

关于本次作业

一开始完全是无从下手,从选择"qt"还是"MFC"就开始犹豫,最后想到VS2015自带有MFC,省去重新安装"qt"的麻烦,选择了"MFC"(后来听说qt在实现上会简单很多,知道真相的喔眼泪掉下来)。因为这次作业所以重新开始使用VS,之前安装好就没怎么用,所以在软件的使用上又浪费了点时间去熟悉。查找了关于MFC的资料= =嗯,我想现在也没有时间去系统的学习它,所以放弃了整套的学习,直接查找关于MFC实现计算器方面的资料,又在GitHub上下载了几个计算器成品,把这些成品拆分掉才开始有了一点头绪。开始动手后,感觉跟高中时候会考要用的那个VB有点像,也是拖动各种工具然后去加代码= =但是还是天真了,毕竟不太一样的东西。最后算是勉勉强强实现了计算器图形界面。

实践中遇到的问题:

  • 1、关于键盘响应,一开始查找资料,顺利完成小键盘上数字的响应,但是主键盘上的数字却一直找不到其所对应的VK值,困扰了很久,最后才从一份文档中发现,MFC并没有关于主键盘上的字母所对应的VK值,而是采用直接引用的办法= =知道真相后有种欲哭无泪的感觉,很简单的解决办法,但是这过程花费了大把的时间。
  • 2、从编辑框中读取文件路径,一开始采用的方法是在编辑框中添加响应,通过UpdateData来更新,在输入文件路径的编辑框还算顺利,同样的办法用到输出文件路径的编辑框,程序运行后整个都卡住了。特别是如果我先在输出文件路径的编辑框中输入然后再在输入文件路径的编辑框输入路径,程序就不会卡,极度郁闷= =也找不到解决方法,其实现在对于这个问题还是懵懵的,最后加了一个button,按下之后才获取两个编辑框中的值进行批处理。
  • 3、在输入输出文件路径的编辑框中,不支持删除功能,最后用了两个button来清空,没有采用逐字删除的功能。
  • 4、键盘响应的问题,如果在输入输出文件的编辑框中使用了数字进行输入,计算器的显示区也会显示出这些数字,目前想到的解决办法是通过判断光标的位置,如果停在输入输出文件编辑框,则不键盘响应,但是这个方法没有成功,不知道是不是我判断焦点那块代码写得有问题,暂时没有很好的解决。

第三次更新:

为什么没有写第二次更新呢= =我忘了第二次更新的时候修复了什么bug。

  • 1、本次修改了光标停在文件编辑框输入以字母形式的文件名也会出现在计算显示区的问题。
  • 2、增加了支持文件输入输出编辑框的逐字删除。
  • 3、关于光标停在编辑框,键盘按键无法响应的问题,初次解决方案通过“关于本程序”的按钮弹出操作说明来告知使用者如何解决,后来考虑到并非人人都会点击“关于本程序”按钮,额外加了一个“消除”焦点的按钮。
  • 4、更改了显示区字体大小以及字体为“微软雅黑”(使用者电脑如果没有这个字体的话= =)

第四次更新

  • 1、修复了显示精度,诸如“(85.18-(-6140))(-93.28+1)=”能得出-233023.6104而不再是-233024以及对于表达式“-72-((-50-53)(-45*-91))=”得出-10851822而不是-1.08518e+007的问题
  • 2、改正了显示区当表达式过长停留在最先输入的字符上,支持从左到右的阅读顺序来显示表达式。
  • 3、主界面增加了最大化、最小化。
  • 4、更正了计算结果为0时显示为“-0”的错误(不小心发现学长的数据也有“-0”)
  • 5、修改了生成程序的默认图标,以及属性中版本等默认信息为个人信息。

未实现功能:

  • 1、使用者输入不合法表达式没有以弹窗模式进行警告,仅只是通过判断使程序不响应此操作。
  • 2、界面被吐槽丑= =确实硬伤,时间关系= =都是泪。
  • 3、没有增加按钮来支持显示科学表达式与普通表达式的转换

写在后面:

程序界面:


由于时间问题,对于界面的样式、字体等也没细弄,批处理区设在了主界面,没有弄成模态对话框的形式(我觉得不会很丑啊= =别打我= =),倒是增加了一个“关于本程序”的按钮,利用模态对话框来弹出另一个界面介绍程序。以后如果还有弄界面= = 我想我会果断选择qt了= =另外程序界面支持被随意拉伸,其实加个函数就能固定程序界面大小,但是我觉得这样随意拉伸挺好的,也就没有更改。还在不断改进,想到bug再来修改吧。

核心代码:

// 如果上一次按的是“=”按钮,清屏
void CCalculatorDlg::Clear()
{
    if (lastPress == true)
    {
        mEdit.SetWindowText(_T(""));
        lastPress = false;
    }
}

void CCalculatorDlg::OnBnClicked1()
{
    // 数字“1”按钮
    Clear();
    UpdateData(TRUE);
    CString str;
    mEdit.GetWindowText(str);
    str = str + _T("1");
    mEdit.SetWindowText(str);
    UpdateData(FALSE);
}

void CCalculatorDlg::OnBnClicked2()
{
    // 数字“2”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    str = str + _T("2");
    mEdit.SetWindowText(str);
}

void CCalculatorDlg::OnBnClicked3()
{
    // 数字“3”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    str = str + _T("3");
    mEdit.SetWindowText(str);
}

void CCalculatorDlg::OnBnClicked4()
{
    // 数字“4”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    str = str + _T("4");
    mEdit.SetWindowText(str);
}

void CCalculatorDlg::OnBnClicked5()
{
    // 数字“5”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    str = str + _T("5");
    mEdit.SetWindowText(str);
}

void CCalculatorDlg::OnBnClicked6()
{
    // 数字“6”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    str = str + _T("6");
    mEdit.SetWindowText(str);
}

void CCalculatorDlg::OnBnClicked7()
{
    // 数字“7”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    str = str + _T("7");
    mEdit.SetWindowText(str);
}

void CCalculatorDlg::OnBnClicked8()
{
    // 数字“8”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    str = str + _T("8");
    mEdit.SetWindowText(str);
}

void CCalculatorDlg::OnBnClicked9()
{
    // 数字“9”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    str = str + _T("9");
    mEdit.SetWindowText(str);
}

void CCalculatorDlg::OnBnClicked0()
{
    // 数字“0”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    if (str != "0")
    {
        str = str + _T("0");
        mEdit.SetWindowText(str);
    }
}

void CCalculatorDlg::OnBnClickedClear()
{
    // “清屏”按钮
    mEdit.SetWindowText(_T(""));
}

void CCalculatorDlg::OnBnClickedBack()
{
    // “后退”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    str = str.Left(str.GetLength()-1);
    mEdit.SetWindowText(str);
}

void CCalculatorDlg::OnBnClickedLeft()
{
    // “左括号”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    if (str == "")
    {
        str = str + _T("(");
        mEdit.SetWindowText(str);
    }
    else
    {
        if(str.GetAt(str.GetLength()-1)<'0' || str.GetAt(str.GetLength()-1)>'9')
        {
            str = str + _T("(");
            mEdit.SetWindowText(str);
        }
    }
}

void CCalculatorDlg::OnBnClickedRight()
{
    // “右括号”按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    if(str != "")
    {
        str = str + _T(")");
        mEdit.SetWindowText(str);
    }
}

void CCalculatorDlg::OnBnClickedDot()
{
    // "."按钮
    Clear();
    CString str;
    mEdit.GetWindowText(str);
    if(str != "")
    {
        if(str.GetAt(str.GetLength()-1)>='0' && str.GetAt(str.GetLength()-1)<='9')
        {
            str = str + _T(".");
            mEdit.SetWindowText(str);
        }
    }
}

void CCalculatorDlg::OnBnClickedAdd()
{
    // 加号
    lastPress = false;
    CString str;
    mEdit.GetWindowText(str);
    str = str + _T("+");
    mEdit.SetWindowText(str);
}

void CCalculatorDlg::OnBnClickedSub()
{
    // 减号
    lastPress = false;
    CString str;
    mEdit.GetWindowText(str);
    str = str + _T("-");
    mEdit.SetWindowText(str);
}

void CCalculatorDlg::OnBnClickedMul()
{
    // 乘号
    lastPress = false;
    CString str;
    mEdit.GetWindowText(str);
    if(str != "")
    {
        if(str.GetAt(str.GetLength()-1)!='+' && str.GetAt(str.GetLength()-1)!='-'
            && str.GetAt(str.GetLength()-1)!='*' && str.GetAt(str.GetLength()-1)!='/')
        {
            str = str + _T("*");
            mEdit.SetWindowText(str);
        }
    }
}

void CCalculatorDlg::OnBnClickedDiv()
{
    // 除号
    lastPress = false;
    CString str;
    mEdit.GetWindowText(str);
    if(str != "")
    {
        if(str.GetAt(str.GetLength()-1)!='+' && str.GetAt(str.GetLength()-1)!='-'
            && str.GetAt(str.GetLength()-1)!='*' && str.GetAt(str.GetLength()-1)!='/')
        {
            str = str + _T("/");
            mEdit.SetWindowText(str);
        }
    }
}

void CCalculatorDlg::OnBnClickedEql()
{
    // 等号,计算结果
    CString str;
    mEdit.GetWindowText(str);
    if(str.Find('+')==-1 && str.Find('-')==-1 && str.Find('*')==-1 && str.Find('/')==-1)
        return;
    else
        lastPress = true;

    CT2CA pszConvertedAnsiString(str);  // 将 TCHAR 转换为 LPCSTR
    string exp_str(pszConvertedAnsiString); // 从 LPCSTR 构造 string

    que = ipt.ToStringQueue(exp_str);
    if (que.empty())
    {
        str = "ERROR";
    }
    else
    {
        string tmp;
        stringstream ss;
        ss.precision(10);
        stk = cal.NumCalculator(que);
        ss << stk.top();
        ss >> tmp;
        str = tmp.c_str();
    }
    mEdit.SetWindowText(str);
}

BOOL CCalculatorDlg::PreTranslateMessage(MSG* pMsg)
{
    bool flag = true;
    CWnd *pFocusWnd = GetFocus();
    if (pFocusWnd && (pFocusWnd == GetDlgItem(IDC_OPEN_EDIT) || pFocusWnd == GetDlgItem(IDC_SAVE_EDIT)))
    {
        flag = false;
    }
    else
    {
        flag = true;
    }
    if (pMsg->message == WM_KEYDOWN && flag)
        {
            switch (pMsg->wParam)
            {
            case VK_NUMPAD0:
                OnBnClicked0(); break;
            case VK_NUMPAD1:
            case '1':
                OnBnClicked1(); break;
            case '2':
            case VK_NUMPAD2:
                OnBnClicked2(); break;
            case '3':
            case VK_NUMPAD3:
                OnBnClicked3(); break;
            case '4':
            case VK_NUMPAD4:
                OnBnClicked4(); break;
            case '5':
            case VK_NUMPAD5:
                OnBnClicked5(); break;
            case '6':
            case VK_NUMPAD6:
                OnBnClicked6(); break;
            case '7':
            case VK_NUMPAD7:
                OnBnClicked7(); break;
            case VK_NUMPAD8:
                OnBnClicked8(); break;
            case VK_NUMPAD9:
                OnBnClicked9();
                break;
            case '8':
                if (GetKeyState(VK_SHIFT) < 0)
                {
                    OnBnClickedMul();
                }
                else
                {
                    OnBnClicked8();
                }
                break;
            case '9':
                if (GetKeyState(VK_SHIFT) < 0)
                {
                    OnBnClickedLeft();
                }
                else
                {
                    OnBnClicked9();
                }
                break;
            case '0':
                if (GetKeyState(VK_SHIFT) < 0)
                {
                    OnBnClickedRight();
                }
                else
                {
                    OnBnClicked0();
                }
                break;
            case VK_OEM_PLUS:
                if (GetKeyState(VK_SHIFT) < 0)
                {
                    OnBnClickedAdd();
                }
                else
                {
                    OnBnClickedEql();
                }
                break;
            case VK_OEM_PERIOD:
            case VK_DECIMAL:
                OnBnClickedDot(); break;
            case VK_SUBTRACT:
            case VK_OEM_MINUS:
                OnBnClickedSub(); break;
            case VK_DIVIDE:
            case VK_OEM_2:
                OnBnClickedDiv(); break;
            case VK_ADD:
                OnBnClickedAdd(); break;
            case VK_MULTIPLY:
                OnBnClickedMul(); break;
            case VK_BACK:
                OnBnClickedBack(); break;
            case VK_RETURN:
                OnBnClickedEql(); return TRUE;
            case VK_ESCAPE:
                OnBnClickedClear(); return TRUE;
            default:
                break;
            }
        }

    return CDialogEx::PreTranslateMessage(pMsg);
}

void CCalculatorDlg::OnEnChangeShow()
{
    // TODO:  如果该控件是 RICHEDIT 控件,它将不
    // 发送此通知,除非重写 CDialogEx::OnInitDialog()
    // 函数并调用 CRichEditCtrl().SetEventMask(),
    // 同时将 ENM_CHANGE 标志“或”运算到掩码中。

    // TODO:  在此添加控件通知处理程序代码
}

void CCalculatorDlg::OnBnClickedOpenButton()
{
    // TODO: 在此添加控件通知处理程序代码
    // 设置过滤器
    TCHAR szFilter[] = _T("文本文件(*.txt)|*.txt|所有文件(*.*)|*.*||");
    // 构造打开文件对话框
    CFileDialog fileDlg(TRUE, _T("txt"), NULL, 0, szFilter, this);
    CString strFilePath;

    // 显示打开文件对话框
    if (IDOK == fileDlg.DoModal())
    {
        // 如果点击了文件对话框上的“打开”按钮,则将选择的文件路径显示到编辑框里
        strFilePath = fileDlg.GetPathName();
        //tEdit.SetWindowText(strFilePath);
        SetDlgItemText(IDC_OPEN_EDIT, strFilePath);

        //SetDlgItemText(IDC_OPEN_EDIT, L" ");
    }
}

void CCalculatorDlg::OnBnClickedSaveButton()
{
    // TODO: 在此添加控件通知处理程序代码
    // 设置过滤器
    TCHAR szFilter[] = _T("文本文件(*.txt)|*.txt|Word文件(*.doc)|*.doc|所有文件(*.*)|*.*||");
    // 构造保存文件对话框
    CFileDialog fileDlg(FALSE, _T("doc"), _T("my"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter, this);
    CString strFilePath;

    // 显示保存文件对话框
    if (IDOK == fileDlg.DoModal())
    {
        // 如果点击了文件对话框上的“保存”按钮,则将选择的文件路径显示到编辑框里
        strFilePath = fileDlg.GetPathName();
        SetDlgItemText(IDC_SAVE_EDIT, strFilePath);
    }
}

void CCalculatorDlg::OnEnChangeOpenEdit()
{
    // TODO:  在此添加控件通知处理程序代码
    CString strFilePath;
    CString strFile;
    UpdateData(TRUE);
    tEdit.GetWindowText(strFile);
    strFilePath = strFilePath + strFile;
    UpdateData(FALSE);
    CT2CA pszConvertedAnsiString(strFilePath);  // 将 TCHAR 转换为 LPCSTR
    string test_str(pszConvertedAnsiString); // 从 LPCSTR 构造 string
    test_str_ = test_str;
}

void CCalculatorDlg::OnEnChangeSaveEdit()
{
    // TODO:  在此添加控件通知处理程序代码
    CString strFilePath;
    CString strFile;
    UpdateData(TRUE);
    rEdit.GetWindowText(strFile);
    strFilePath = strFilePath + strFile;
    UpdateData(FALSE);
    CT2CA pszConvertedAnsiString(strFilePath);  // 将 TCHAR 转换为 LPCSTR
    string results_str(pszConvertedAnsiString); // 从 LPCSTR 构造 string
    results_str_ = results_str;
}

void CCalculatorDlg::OnBnClickedOk()
{
    // TODO: 在此添加控件通知处理程序代码
    ipt.FileOpen(test_str_);
    opt.FileOpen(results_str_);
    if (!ipt.FileIsOpen())
    {
        cerr << "Could not open " << results_str_ << endl;
        ipt.FileClear();
    }
    else
    {
        while (!ipt.IsEof())
        {
            ipt.Read();
            //getline(ipt.fin, ipt.in);
            if (ipt.in == "")
            {
                continue;
            }
            que = ipt.ToStringQueue(ipt.in);
            if (que.empty())
            {
                opt.OutputToFile(que);
            }
            else
            {
                stk = cal.NumCalculator(que);
                opt.PutAnsTofile(stk);
            }
        }
    }
    ipt.FileClose();
    opt.FileClose();
}

void CCalculatorDlg::OnBnClickedClear1()
{
    //清空文件输入路径内容
    tEdit.SetWindowText(_T(""));
}

void CCalculatorDlg::OnBnClickedClear2()
{
    //清空文件输出路径内容
    rEdit.SetWindowText(_T(""));
}

void CCalculatorDlg::OnBnClickedButtonAbout()
{
    // TODO: 在此添加控件通知处理程序代码
    INT_PTR nRes;             // 用于保存DoModal函数的返回值   

    CTipDlg tipDlg;           // 构造对话框类CTipDlg的实例
    nRes = tipDlg.DoModal();  // 弹出对话框
    if (IDCANCEL == nRes)     // 判断对话框退出后返回值是否为IDCANCEL,如果是则return,否则继续向下执行
        return;
}

void CCalculatorDlg::OnBnClickedButtonOk()
{
    // TODO: 在此添加控件通知处理程序代码
    CWnd *pFocusWnd = GetFocus();
    if (pFocusWnd && (pFocusWnd == GetDlgItem(IDC_OPEN_EDIT)))
    {
        tEdit.SetWindowText(_T(""));
    }
    else if (pFocusWnd && (pFocusWnd == GetDlgItem(IDC_SAVE_EDIT)))
    {
        rEdit.SetWindowText(_T(""));
    }
}

第六次作业——利用MFC实现计算器图形界面以及简单四则运算表达式批处理的更多相关文章

  1. 利用MFC编写计算器

    端午节这两天没什么事,就用MFC写了一个简单的计算器,界面做的也比较简单,如下图1,可以进行简单的加.减.乘和除功能,小数点显示这块做的不是很好,比如输入1.2,不会一个个的显示,而是先显示“1”,后 ...

  2. 初进MFC的世界,太奇妙。第六次作业----未完待续

    又一次的迁徙.我希望能够早些抵达. 第六次作业-未完待续!图形界面,计算器文件 本次的作业是给自己的计算器加一个可视化的窗口,我开始也是很激动和憧憬的,看了很多的界面库,发现并没有想象的那么简单,因为 ...

  3. C++第六次作业

    前言 拿到作业的时候,整个人都不好了,虽然之前和同学说以后一起写游戏,画界面,然而现在的自己对界面的知识一窍不通,虽然同学分享了一些资料,但是通过这次作业,发现自己火候还是不够-- 问题描述及仓库地址 ...

  4. 《ABCD组》第六次作业:团队项目系统设计改进与详细设计

    <ABCD组>第六次作业:团队项目系统设计改进与详细设计 项目 内容 这个作业属于哪个课程 http://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 ht ...

  5. 耿丹CS16-2班第六次作业汇总

    Deadline: 2016-11-13 11:59 作业内容 第六次作业总结 00.本次题目分值最高为**6分/题 × 7题 + 5分/篇 × 1篇 = 47分**,其中有新解法者每题加原创分**2 ...

  6. C2第六次作业解题报告

    看过题解后如果觉得还算有用,请帮忙加点我所在团队博客访问量 http://www.cnblogs.com/newbe/ http://www.cnblogs.com/newbe/p/4069834.h ...

  7. VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)

    VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)-软件开发-鸡啄米 http://www.jizhuomi.com/software/141.html   上一讲中讲了VS20 ...

  8. C语言程序设计第六次作业——循环结构(2)

    C语言程序设计第六次作业--循环结构(2) 之前的博客园图片没处理好,对大家说一声抱歉.希望大家能够多多指出我的错误,我来认真修改 ^ - ^ !. (1)改错题 序列求和:输入一个正实数eps,计算 ...

  9. Python开发——利用正则表达式实现计算器算法

    Python开发--利用正则表达式实现计算器算法 (1)不使用eval()等系统自带的计算方法 (2)实现四则混合运算.括号优先级解析 思路: 1.字符串预处理,将所有空格去除 2.判断是否存在括号运 ...

随机推荐

  1. lecture8-RNN的训练方法之二三

    HInton第8课,之所以说之二三,是因为训练RNN的四种方法之一:长短时记忆在lecture7中介绍过了,这里介绍的是第二和第三种方法:HF优化和Echo (这个字觉得翻译成回声是不是欠妥,所以保留 ...

  2. DateTime.Now.ToString() 用法

    //2008年4月24日 System.DateTime.Now.ToString("D"); //2008-4-24 System.DateTime.Now.ToString(& ...

  3. CSS选择器优先级 CSS权值

    计算指定选择器的优先级:重新认识CSS的权重 标签的权值为 0,0,0,1 类的权值为 0,0,1,0 属性选择的权值为 0,0,1,1  ID的权值为 0,1,0,0 important的权值为最高 ...

  4. js表单提交,面向对象

    一.js表单验证之后再提交 1.普通按钮onclick函数调用表单的submit()函数 <input type=button name="submit1" value=&q ...

  5. java知识点、重点知识点

    重点章节: 面对对象章节 重点知识点: Lambda表达式 数据:内存-->数据库 知识点一拦: 类.面向对象.对象.封装.继承.多态.消息.UML建模.数据类型(基本类型.引用类型).数据类型 ...

  6. HTML5文件系统API和资料整理

    来着火狐开发网络的官方文档:点我打开 : W3C的官方文档: 点我打开 : 园友的博客:  点我打开: 浏览器兼容性, 好了就chrome支持, 我刚刚更新的火狐37也不支持, nice, 太nice ...

  7. 51nod 1163贪心

    用优先队列来贪心,是一个很好地想法.优先队列在很多时候可以维护最值,同时可以考虑到一些其他情况. http://www.51nod.com/onlineJudge/questionCode.html# ...

  8. windows-msconfig

    弹出输入框,输入命令msconfig 打开系统配置,查看相关引导信息,关闭开机启动等

  9. dede使用方法---如何调用指定栏目

    使用dede的时候,我们需要调用某一个指定的栏目,这个时候我们该如何使用标签呢?? 真相就是----{dede:type typeid='27'}*******{/dede:type} 完整的标签代码 ...

  10. IE6、IE7、IE8的CSS、JS兼容

    Internet Explorer 6中查看使用 Microsoft JScript 的网页,可能会遇到web浏览器速度较慢的性能问题.原因是如果js脚本同时创建大量变量,jscript引擎执行垃圾收 ...