参考资料:

     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. 如何用 fiddler 调试线上代码

    有时代码上线了,突然就碰到了坑爹的错误.或者有时看别人家线上的代码,对于一个文件想 fork 下来试试效果又不想把全部文件拉到本地,都可以使用 fiddler 的线上调试功能. 比方说我们打开携程的首 ...

  2. sdk墙内更新方法

    因为GFW有“保护”,我们能“安全”的遨游在中华互联局域网内.如何快速地更新sdk,一直是Android开发者的心病.网上流传着五花八门的方法,在这我记录一些我用过的切实可行的方法供给有需要的人.同时 ...

  3. 前端框架——BootStrap学习

    BootStrap简单总结下:1.栅格系统,能够很好的同时适应手机端和PC端(及传说中的响应式布局) 2.兼容性好 接下来是对BootStrap学习的一些基础案例总结和回顾: 首先引入:bootstr ...

  4. 35-less 简明笔记

    分屏显示文本文件 less [options] [file-list] less与more类似,但比more更加完善 例如:在显示一屏文本之后,less将显示提示副等待下一条命令的输入;可以向前或向后 ...

  5. 十天冲刺---Day2

    站立式会议 站立式会议内容总结: git上Issues新增内容: 燃尽图 照片

  6. “Ceph浅析”系列之一——前言

    开源技术专家章宇同学(@一棹凌烟)在C3沙龙分享过Ceph之后,最近来了劲头,一口气写了一系列<Ceph浅析>的博文,共8篇: "Ceph浅析"系列之一--前言 &qu ...

  7. javascript获得客户端IP的又一方法

    <script language="JavaScript">VIH_BackColor = "palegreen";VIH_ForeColor = ...

  8. 初探psutil

    系统性能信息模块psutil 1,psutil简介 psutil是一个跨平台能够轻松获取系统的进程和系统利用率,主要应用在系统监控,分析和限制系统资源以及进程管理.它实现了很多系统管理的命令,如ps, ...

  9. HTMLTestRunner修改Python3的版本

    在拜读虫师大神的Selenium2+Python2.7时,发现生成HTMLTestRunner的测试报告使用的HTMLTestRunner的模块是用的Python2的语法.而我本人比较习惯与Pytho ...

  10. 使用jmeter进行性能测试-Jmeter教程及技巧汇总 (转)

    http://www.jmeter.cf/loadtesting-jmeter.html 为什么使用jmeter, 它免费开源, 不断发展, 功能逐渐强大. 可以做功能,负载, 性能测试.一套脚本可以 ...