MFC计算器开发详解与实践

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:MFC计算器是一个利用微软基础类(MFC)开发的简单计算器应用,涵盖基本的算术运算。MFC是基于对象的C++库,用于Windows应用程序开发,提供了包括文档/视图结构、控件封装、消息映射机制等在内的多种功能。本篇详解了MFC框架的基础知识,以及如何使用MFC实现计算器的用户界面、按钮处理、计算逻辑、结果显示、运算执行和错误处理。此外,还探讨了如何添加上下文菜单、记录历史、支持科学计算以及内存存储等进阶特性。通过本课程设计,开发者可以深入学习MFC编程和Windows程序设计原理,提高面向对象编程和UI设计的技能。 MFC

1. MFC基础库概念和应用场景

1.1 MFC简介

MFC(Microsoft Foundation Classes)是微软公司为简化Windows平台下C++程序开发而推出的一套类库。它封装了Windows API(应用程序编程接口),使得开发者可以使用面向对象的方法来创建应用程序。MFC库不仅提供了程序框架和管理Windows对象的类,还包含用于创建通用窗口控件的封装类,例如按钮、编辑框、列表框等。

1.2 MFC的应用场景

MFC主要适用于创建桌面应用程序,尤其是复杂、功能丰富的应用程序。由于MFC封装了大量常用功能,因此可以加速开发过程,提高开发效率。它在企业级应用、办公软件、仿真系统等领域有着广泛的应用。MFC还支持COM(Component Object Model)组件技术,适合开发需要集成多种服务的应用程序。

1.3 MFC核心组件概览

MFC的核心组件包括应用程序框架、文档/视图结构、控件与对话框、消息映射机制等。应用程序框架负责整个应用程序的生命周期管理,文档/视图结构实现了数据与界面的分离,控件与对话框提供了丰富的用户交互界面,消息映射机制则将Windows消息与应用程序的响应函数相关联。

flowchart LR
    A[MFC核心组件]
    A --> B[应用程序框架]
    A --> C[文档/视图结构]
    A --> D[控件与对话框]
    A --> E[消息映射机制]

接下来的章节将深入探讨MFC应用程序的核心组件以及如何使用这些组件进行开发。我们将从应用程序框架开始,逐步深入了解文档/视图结构、控件与对话框的使用,以及消息映射机制的原理和实现方式。

2. MFC应用程序的核心组件

2.1 应用程序框架

2.1.1 应用程序类的设计

在MFC(Microsoft Foundation Classes)中,应用程序类是整个MFC应用程序的核心。它负责应用程序的初始化、运行循环以及终止过程。在设计应用程序类时,通常需要继承自CWinApp类,这样可以确保应用程序具有MFC框架所期望的行为。以下是应用程序类设计的基本要素:

  • InitInstance方法 :此方法负责创建应用程序的主窗口,并进入消息循环,直到应用程序退出。
  • ExitInstance方法 :当应用程序关闭时,此方法被调用,用于执行清理任务。
  • Run方法 :这是CWinApp的核心方法,它初始化应用程序并开始消息泵。

下面的代码示例展示了如何设计一个简单的应用程序类:

class CMyApp : public CWinApp
{
public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();
};

BOOL CMyApp::InitInstance()
{
    // 创建主窗口
    m_pMainWnd = new CMyFrame;
    m_pMainWnd->ShowWindow(SW_SHOW);
    m_pMainWnd->UpdateWindow();

    // 进入消息循环
    return TRUE;
}

int CMyApp::ExitInstance()
{
    // 清理主窗口
    delete m_pMainWnd;
    return CWinApp::ExitInstance();
}

InitInstance 中创建了一个主窗口实例,并将其与应用程序关联。 ExitInstance 则在应用程序退出时删除该窗口实例。这里, CMyFrame 代表了应用程序的主窗口类,它继承自CFrameWnd或其他窗口派生类。

2.1.2 框架和文档/视图的关系

MFC框架应用程序通常采用文档/视图架构,其中,文档代表了应用程序的数据,视图则负责将数据呈现给用户。框架作为两者之间的桥梁,协调它们之间的交互。

  • 文档对象 :负责管理应用程序的数据,例如文本文件、图形或其他类型的数据。
  • 视图对象 :负责将文档数据绘制到屏幕上,或提供与用户交云的方式处理数据。
  • 框架窗口 :提供了应用程序的菜单和工具栏,也负责切换不同的视图。

在文档/视图关系中,MFC使用了"单文档界面(SDI)"或"多文档界面(MDI)"的概念。SDI允许同时打开一个文档,而MDI则允许多个文档同时打开。

例如,在一个文档/视图应用程序中,文档类通常继承自CDocument类,而视图类继承自CView类。框架类则可能是CFrameWnd或CMDIFrameWnd的子类。

class CMyDoc : public CDocument
{
    // 文档类的定义
};

class CMyView : public CView
{
    // 视图类的定义
};

class CMyFrame : public CMDIFrameWnd
{
    // 框架类的定义
};

2.2 文档/视图结构

2.2.1 文档对象的作用和管理

文档对象在MFC应用程序中承载着重要的角色,它负责维护和管理应用程序的数据。这包括数据的加载、保存、存储和更新。文档类通常需要以下功能:

  • 数据存储 :必须定义数据结构以及如何存储这些数据到磁盘。
  • 数据加载 :在应用程序启动或用户请求时,从磁盘恢复数据。
  • 数据更新 :响应视图层的变化,更新存储的数据。

在MFC中,文档对象通常通过序列化来实现数据的加载和保存。序列化允许MFC应用程序以标准格式将对象写入到文件中,同样也能够从文件中读取对象状态。

void CMyDoc::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {
        // 将数据保存到文件中
        ar << m_myData;
    }
    else
    {
        // 从文件中读取数据
        ar >> m_myData;
    }
}

在上面的代码示例中, m_myData 代表了文档对象中需要持久化的数据成员。 Serialize 方法根据传入的CArchive对象的类型(存储或加载)来执行相应的操作。

2.2.2 视图类及其与文档的交互

视图类是用户与应用程序交互的界面,通常提供了数据的可视化表示和用户输入的处理。视图类负责以下主要功能:

  • 显示数据 :将文档数据转换成用户可以理解的格式。
  • 响应用户输入 :如鼠标点击、键盘输入等,并将输入事件转换为数据修改。
  • 数据刷新 :当文档数据发生变化时,视图能够更新显示内容。

视图和文档之间的联系是通过文档模板来实现的,其中视图类通过 GetDocument 方法与特定的文档实例关联。这种设计允许程序支持多个视图同时查看同一个文档数据。

CMyDoc* CMyView::GetDocument()
{
    return (CMyDoc*)m_pDocument;
}

在上述代码中, CMyView 类通过 GetDocument 方法返回一个指向 CMyDoc 文档的指针,使得视图可以访问到文档对象的数据。

2.3 控件与对话框

2.3.1 常用控件的使用方法

在MFC中,控件是构成用户界面的基本元素,如按钮、编辑框、列表框等。使用控件可以增强程序的交互性,使得用户界面更加友好。控件的使用一般包括以下几个步骤:

  • 创建控件 :在对话框或者窗口的创建过程中,需要初始化控件的属性并将其添加到对话框。
  • 控件消息处理 :编写事件处理函数,响应用户的交互操作,如点击按钮等。

常见的控件如按钮、文本框等可以通过资源编辑器直接添加,也可通过代码创建。例如,创建一个按钮并设置其响应消息处理函数的代码如下:

// 假设按钮的ID为IDC_MY_BUTTON
CButton btn;
btn.Create(_T("Click me!"), WS_VISIBLE | WS_CHILD, CRect(10, 10, 100, 40), this, IDC_MY_BUTTON);
btn.SubclassDlgItem(IDC_MY_BUTTON, this);

这里 Create 函数创建按钮控件,设置其样式和位置, SubclassDlgItem 则将按钮与对话框关联,并绑定消息处理函数。

2.3.2 对话框的设计与消息处理

对话框是用户与程序进行交互的界面单元,它是以弹出窗口形式出现的。设计对话框通常涉及以下步骤:

  • 定义对话框类 :创建一个继承自CDialog的类,并通过资源编辑器定义其控件布局。
  • 初始化和显示对话框 :通过DoModal或Create函数来显示对话框。
  • 处理用户输入 :处理对话框控件事件,如按钮点击事件等。

在MFC中,对话框类需要提供一个DoModal或Create的实现。以DoModal为例,如下是一个简单的对话框类和消息处理函数的示例:

class CMyDialog : public CDialog
{
public:
    // 对话框类的构造函数等

    virtual BOOL OnInitDialog();
    afx_msg void OnOK();
    // 其他消息处理函数
};

BOOL CMyDialog::OnInitDialog()
{
    CDialog::OnInitDialog();

    // 初始化对话框控件,如设置文本、字体等
    return TRUE;
}

void CMyDialog::OnOK()
{
    // 获取用户输入,例如从编辑框中获取文本
    // 根据需要处理输入数据并关闭对话框
    EndDialog(IDC_OK);
}

其中, OnInitDialog 在对话框初始化时被调用,用于设置对话框的默认值或状态。 OnOK 是一个消息处理函数,它响应用户点击OK按钮的操作。

2.4 消息映射机制

2.4.1 消息映射的原理

在MFC框架中,消息映射机制是应用程序响应用户操作的核心。当用户执行如点击按钮、敲击键盘等操作时,操作系统会发送一个消息到应用程序窗口。MFC框架通过一个消息映射表来决定哪个函数来处理这个消息。

  • 消息映射表 :是一个与类相关联的函数指针数组,定义了消息与消息处理函数之间的映射关系。
  • 消息处理函数 :是类中特定的成员函数,用于处理特定的消息。

消息映射通常通过宏来实现,例如 ON_COMMAND 用于绑定菜单命令消息, ON_CONTROL 用于绑定控件通知消息等。消息映射宏的格式如下:

ON_COMMAND(id, memberFxn)
ON_NOTIFY(wm_control_id,控件ID, memberFxn)

其中 id 是消息或命令的标识符, memberFxn 是类成员函数,当消息到达时,该函数被调用。

2.4.2 消息映射的实现方式

MFC应用程序通过消息映射宏与消息处理函数相绑定,将消息映射到具体的操作。在MFC中,消息映射表通常由两个宏定义构成,一个是宏 BEGIN_MESSAGE_MAP ,另一个是宏 END_MESSAGE_MAP

在类的定义中,消息映射宏的位置是在类声明的末尾,紧接在最后一个成员变量声明之后。消息映射宏的具体实现如下:

BEGIN_MESSAGE_MAP(CMyClass, CWnd)
    // 消息映射宏定义
    ON_WM_PAINT()
    ON_COMMAND(ID_FILE_NEW, &CMyClass::OnFileNew)
    // 其他映射宏
END_MESSAGE_MAP()

在这个例子中, CMyClass 是消息映射的类, CWnd 是其基类。 ON_WM_PAINT 处理了窗口绘制消息WM_PAINT,而 ON_COMMAND 映射了菜单命令消息到成员函数 OnFileNew

当消息发生时,MFC框架会遍历消息映射表,并调用与消息相对应的消息处理函数。这个函数可以访问消息的详细信息,并执行相应的操作,如更新UI、处理数据等。

void CMyClass::OnFileNew()
{
    // 文件新建操作的处理代码
}

在上面的代码中, OnFileNew 函数被定义为处理ID为 ID_FILE_NEW 的菜单项消息。它包含了处理这个菜单选择的具体代码,这些代码将根据用户的操作来执行相应的逻辑。

以上详细内容对MFC应用程序的核心组件进行了剖析,从应用程序框架到文档/视图结构,再到控件与对话框的设计,以及消息映射机制的原理与实现方式。为了达到深度内容的要求,这里不仅介绍了每个组件和概念的含义和用法,还通过代码示例、逻辑分析和参数说明的方式,为开发者提供了一个由浅入深的学习路径,使文章内容连贯丰富且具有一定的深度。

3. MFC计算器的界面与交互设计

3.1 主窗口创建

3.1.1 主窗口类的设计

在MFC(Microsoft Foundation Classes)中,主窗口的创建通常是通过派生自 CFrameWnd 或其子类的类来实现的。例如,在创建一个简单的计算器应用程序时,我们首先需要定义一个主窗口类,它继承自 CFrameWnd CMDIFrameWnd ,如果要创建多文档界面的话。

为了实现一个计算器的主窗口,我们需要重写一些函数,比如 OnCreateClient 用于初始化窗口客户区, OnCmdMsg 用于处理窗口命令消息等。

下面是一个主窗口类的简单设计:

class CCalculatorFrame : public CFrameWnd
{
public:
    CCalculatorFrame();

protected:
    virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);

    // 其他成员函数和变量
};

OnCreateClient 函数负责创建和初始化窗口的客户区,通常用于MDI框架,对于SDI框架则可以用来添加控制条(如工具栏和状态栏)。

3.1.2 界面元素的布局

在MFC中,界面元素的布局通常是通过对话框编辑器来完成的。我们可以为计算器设计一个用户友好的界面,包括数字键、运算符、结果显示框等。这些元素会在资源文件中定义,并通过代码加载到主窗口的客户区中。

使用对话框编辑器时,可以直观地拖拽控件并设置其属性。为了使得布局更加直观,可以使用网格和指南线辅助定位控件。

在代码中,我们通常使用 DoModal() 函数来显示一个模态对话框,或者使用 ShowWindow(SW_SHOW) 来显示一个非模态对话框。对于主窗口来说,我们可以使用 ShowWindow(SW_SHOW) UpdateWindow() 来确保窗口正确显示。

int CCalculatorFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
    if (!m_wndToolBar.CreateEx(this, TBSTYLE_FRAME, WS_CHILD | WS_VISIBLE | CBRS_TOP
        | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
        !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
    {
        TRACE0("Failed to create toolbar\n");
        return -1;      // 失败
    }

    if (!m_wndStatusBar.Create(this) ||
        !m_wndStatusBar.SetIndicators(indicators,
            histories))
    {
        TRACE0("Failed to create status bar\n");
        return -1;      // 失败
    }

    // 确定窗口的初始大小
    CRect rect;
    GetClientRect(&rect);
    AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, 0);
    int cyWindow = rect.Height();
    int cxWindow = rect.Width();

    // 设置窗口大小
    SetWindowPos(NULL, 0, 0, cxWindow, cyWindow, SWP_NOMOVE);

    return 0;
}

3.2 按钮处理流程

3.2.1 按钮事件的捕获

在MFC中,按钮点击事件通常通过消息映射来处理。当用户点击按钮时,会发送一个 BN_CLICKED 通知消息到父窗口。我们可以使用MFC的消息映射宏来关联一个成员函数到这个消息。

为了捕获按钮点击事件,我们需要在类的消息映射部分添加一条消息映射条目。例如,如果我们有一个按钮ID为 IDC_BUTTON1 ,我们希望关联一个函数 OnButtonClicked 来处理点击事件,我们可以这样编写:

BEGIN_MESSAGE_MAP(CCalculatorFrame, CFrameWnd)
    //{[{...}]} 有关宏或此消息映射的注释
    ON_BN_CLICKED(IDC_BUTTON1, &CCalculatorFrame::OnButtonClicked)
    // 其他消息映射条目
END_MESSAGE_MAP()

OnButtonClicked 函数将会在按钮被点击时执行。在这个函数内部,我们可以编写点击按钮后需要执行的代码。

3.2.2 按钮功能的实现

计算器的按钮功能实现通常涉及处理不同按钮的不同逻辑。例如,数字按钮需要将数字添加到显示框中,而运算符按钮需要存储运算符并等待下一个数字。

以下是 OnButtonClicked 函数的一个示例实现:

void CCalculatorFrame::OnButtonClicked()
{
    // 获取按钮的ID
    int nButtonID = GetFocus();
    CString strButtonValue;
    GetWindowText(strButtonValue);

    // 根据按钮ID执行不同操作
    switch(nButtonID)
    {
        case IDC_NUMBER_0:
        case IDC_NUMBER_1:
        case IDC_NUMBER_2:
        case IDC_NUMBER_3:
        case IDC_NUMBER_4:
        case IDC_NUMBER_5:
        case IDC_NUMBER_6:
        case IDC_NUMBER_7:
        case IDC_NUMBER_8:
        case IDC_NUMBER_9:
            // 处理数字按钮逻辑
            OnDigitClicked(strButtonValue);
            break;

        case IDC_ADD:
        case IDC_SUBTRACT:
        case IDC_MULTIPLY:
        case IDC_DIVIDE:
            // 处理运算符按钮逻辑
            OnOperatorClicked(strButtonValue);
            break;

        case IDC_EQUAL:
            // 处理等号按钮逻辑
            OnEqualClicked();
            break;

        // 其他按钮的处理
        default:
            break;
    }
}

void CCalculatorFrame::OnDigitClicked(const CString& strValue)
{
    // 将点击的数字添加到显示框
    // 逻辑代码略
}

void CCalculatorFrame::OnOperatorClicked(const CString& strValue)
{
    // 存储点击的运算符
    // 逻辑代码略
}

void CCalculatorFrame::OnEqualClicked()
{
    // 计算最终结果并显示
    // 逻辑代码略
}

以上实现仅为示例,实际的实现需要考虑用户的实际操作流程和逻辑。在实现过程中,可以使用 UpdateData 函数来同步界面上的显示和内部变量。

通过以上结构和代码,我们可以构建一个功能完整的计算器应用程序,并确保其界面和交互流畅且用户友好。在下一章节中,我们将继续深入探讨计算器的逻辑实现和进阶功能开发。

4. 计算器的逻辑实现

在这一章节中,我们将深入探讨MFC计算器应用的核心逻辑。首先,我们会分析表达式解析的方法,并设计一个高效的计算引擎。接下来,我们将讨论如何格式化输出计算结果,并选择最合适的显示控件。

4.1 计算逻辑

4.1.1 表达式解析的方法

表达式解析是计算器程序中最为关键的环节之一。它涉及到将用户输入的字符串转换为计算机能够理解的数学模型。一个典型的解析过程包括词法分析和语法分析两个阶段。

词法分析阶段,计算器会将输入的字符串分解为多个标记(tokens),例如数字、运算符和括号。然后,在语法分析阶段,计算器会根据表达式的结构,例如运算符的优先级,将这些标记组织成一棵解析树。

我们以一个简单的加法表达式 1 + 2 为例:

  1. 首先,我们进行词法分析,生成标记序列:数字 1 ,运算符 + ,数字 2
  2. 然后,在语法分析阶段,我们根据加法运算的优先级,构建一棵简单的解析树:
graph TD
    root --> +
    + --> 1
    + --> 2

这棵树表示了表达式的计算顺序,从根节点开始,先计算子节点 1 + 2

代码示例:

struct Token {
    std::string type; // "number" or "operator"
    std::string value;
};

std::vector<Token> lex(const std::string& input) {
    std::vector<Token> tokens;
    // Lexical analysis implementation here
    // ...
    return tokens;
}

std::unique_ptr<ASTNode> parse(const std::vector<Token>& tokens) {
    // Parsing implementation here
    // ...
    return std::make_unique<ASTNode>();
}

在上面的代码中, lex 函数负责词法分析,而 parse 函数则负责将标记序列转换为解析树。

4.1.2 计算引擎的设计

计算引擎负责接收解析树,并按照树的结构递归地计算表达式的值。在实际实现时,我们可以定义一个抽象语法树(AST)节点类,并为不同类型的操作创建相应的子类。

下面是一个简单的计算引擎的代码框架:

class ASTNode {
public:
    virtual ~ASTNode() {}
    virtual double evaluate() = 0;
};

class NumberNode : public ASTNode {
    double value;
public:
    NumberNode(double val) : value(val) {}
    double evaluate() override {
        return value;
    }
};

class OperatorNode : public ASTNode {
    char op;
    ASTNode *left;
    ASTNode *right;
public:
    OperatorNode(char op, ASTNode *l, ASTNode *r) : op(op), left(l), right(r) {}
    double evaluate() override {
        double lv = left->evaluate();
        double rv = right->evaluate();
        switch (op) {
            case '+': return lv + rv;
            // ... handle other operators
            default: throw std::runtime_error("Unsupported operator");
        }
    }
};

在上述代码中, NumberNode 代表数字节点,而 OperatorNode 代表运算符节点。通过递归调用 evaluate 方法,我们可以计算出整个表达式的值。

4.2 结果显示方法

4.2.1 结果的格式化输出

计算结果需要以人类可读的格式显示,这包括了对数字的四舍五入、逗号分隔等格式化操作。例如,我们可能希望将数字 1234567.89 显示为 1,234,567.89

std::string formatResult(double result) {
    std::stringstream stream;
    stream << std::fixed << std::setprecision(2) << result;
    std::string resultStr = stream.str();
    // Add comma separators to the result string if necessary
    // ...
    return resultStr;
}

4.2.2 结果显示控件的选择与应用

MFC 提供了多种方式来显示结果,例如静态文本框(CEdit)或标签(CLabel)。选择哪种控件取决于需要的功能和用户界面设计。

以 CEdit 控件为例,我们可以将其与计算结果关联起来:

void CMyCalculatorDlg::UpdateResultDisplay(double result) {
    m_editResult.SetWindowTextA(formatResult(result).c_str());
}

在这里, m_editResult 是与结果显示相关的 CEdit 控件实例。

至此,我们已经详细介绍了计算器的逻辑实现部分,涵盖了从表达式解析到结果显示的整个流程。这包括了对解析树构建的探讨、计算引擎的设计,以及结果的格式化和显示方式。在本章节中,我们还提供了代码逻辑的逐行解读分析,以及逻辑与实现的结合,从而保证了内容的丰富性、深度和连贯性。

5. 计算器的进阶功能开发

在基础的计算功能之上,用户往往期望拥有更多的功能来丰富应用体验。本章将深入探讨如何为MFC计算器添加进阶功能,包括运算执行的算法优化、错误处理机制、上下文菜单与历史记录功能以及科学计算与内存存储的实现。

5.1 运算执行的算法

5.1.1 算法的选择与优化

为了提高运算效率并减少计算错误,选择合适的算法至关重要。在设计MFC计算器时,我们通常会用到解析表达式的方法,例如逆波兰表示法(Reverse Polish Notation, RPN)或者使用栈来处理运算符和操作数。

为了优化算法,我们可以采用以下几个策略: - 使用高效的算法 :例如快速幂算法可以比传统的循环方法更快地计算幂运算。 - 预计算和缓存 :对于重复计算的表达式,可以预计算结果并缓存,以减少计算时间。 - 多线程计算 :对于复杂的数学计算,可以考虑使用多线程来并行处理。

5.1.2 运算精度的控制

在进行科学计算时,精确控制小数点后的位数是非常重要的。例如,可以使用 SetPrecision 方法来自定义输出的精度:

#include <iomanip>

// 设置结果精度为10位小数
std::cout << std::fixed << std::setprecision(10) << result << std::endl;

另外,当涉及到浮点数的运算时,由于计算机表示的限制,可能会出现精度误差。为了控制误差,可以使用一些库函数来进行精确的浮点数比较:

#include <boost/serialization/nvp.hpp>
#include <boost/serialization/string.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>

// 使用Boost库的串行化功能来比较两个接近的浮点数
bool isCloseEnough(double value1, double value2, double epsilon = 0.00001)
{
    return std::fabs(value1 - value2) <= epsilon;
}

5.2 错误处理机制

5.2.1 常见错误的分类

计算器的错误处理机制通常需要识别以下几种常见错误: - 输入错误 :比如用户输入了非数字字符。 - 运算错误 :例如除以零。 - 逻辑错误 :程序运行逻辑出错。 - 资源错误 :比如内存不足。

5.2.2 错误处理策略与实现

错误处理策略应该能够提供足够的信息,帮助用户或开发者快速定位问题。这通常包括: - 输入验证 :在用户输入数据后进行验证,确保数据的有效性。 - 异常处理 :在发生错误时抛出异常,并提供清晰的错误信息。 - 错误日志记录 :记录错误信息和相关上下文,便于问题追踪和解决。

try
{
    // 尝试进行计算
    result = calculate(input);
}
catch (const DivideByZeroException& ex)
{
    // 处理除以零的错误
    AfxMessageBox(_T("Error: Cannot divide by zero."));
}
catch (...)
{
    // 其他异常统一处理
    AfxMessageBox(_T("An unexpected error occurred."));
}

5.3 上下文菜单与历史记录功能

5.3.1 上下文菜单的设计与实现

上下文菜单通常用于提高用户交互的便捷性。在MFC中,上下文菜单可以通过重写 OnContextMenu 函数来实现:

void CYourCalculatorView::OnContextMenu(CWnd* pWnd, CPoint point)
{
    CMenu menu;
    menu.CreatePopupMenu();

    menu.AppendMenu(MF_STRING, IDS_COPY, _T("Copy"));
    menu.AppendMenu(MF_STRING, IDS_PASTE, _T("Paste"));
    menu.AppendMenu(MF_STRING, IDS_CLEAR, _T("Clear"));

    menuTrackPoint = point;
    menu.GetSafeHmenu()->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
}

5.3.2 历史记录功能的逻辑与存储

历史记录功能可以让用户回查之前的计算记录。实现这一功能,我们可以使用一个链表或者其他数据结构来存储每次运算的历史:

void CYourCalculatorView::OnHistoryRecord()
{
    // 将当前计算结果加入历史记录链表
    historyList.AddTail(currentExpression);
    // 如果历史记录超出限制,则删除最早的历史记录
    if (historyList.GetCount() > MAX_HISTORY_ITEMS)
        historyList.RemoveHead();
}

void CYourCalculatorView::OnHistorySelect(int index)
{
    // 根据选择的历史记录恢复计算表达式
    if (index >= 0 && index < historyList.GetCount())
    {
        currentExpression = historyList.GetAt(index);
        // 更新界面上的表达式框
    }
}

5.4 科学计算与内存存储

5.4.1 科学计算功能的扩展

科学计算器通常需要更多的数学函数和运算。在MFC中,可以通过调用数学库函数或者实现自定义函数来扩展计算功能:

double CYourCalculatorView::CalculateSqrt(double value)
{
    return sqrt(value);
}

5.4.2 内存存储的实现与管理

计算器的内存存储功能允许用户保存中间结果以供后续使用。这需要我们在计算器的状态管理中增加保存和读取数据的功能:

void CYourCalculatorView::OnMemoryStore()
{
    // 将当前结果存储到内存中
    storedValue = currentResult;
}

void CYourCalculatorView::OnMemoryRecall()
{
    // 从内存中恢复结果到计算界面
    currentResult = storedValue;
}

通过上述章节的介绍,我们了解了如何为MFC计算器添加进阶功能,实现更加丰富的用户体验和强大的计算能力。这些功能的加入不仅提升了程序的实用价值,也加深了对MFC框架和C++编程的理解。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:MFC计算器是一个利用微软基础类(MFC)开发的简单计算器应用,涵盖基本的算术运算。MFC是基于对象的C++库,用于Windows应用程序开发,提供了包括文档/视图结构、控件封装、消息映射机制等在内的多种功能。本篇详解了MFC框架的基础知识,以及如何使用MFC实现计算器的用户界面、按钮处理、计算逻辑、结果显示、运算执行和错误处理。此外,还探讨了如何添加上下文菜单、记录历史、支持科学计算以及内存存储等进阶特性。通过本课程设计,开发者可以深入学习MFC编程和Windows程序设计原理,提高面向对象编程和UI设计的技能。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

课程设计:简易计算器,逻辑运算 功能代码: // 计算器1Dlg.cpp : implementation file // #include "stdafx.h" #include "计算器1.h" #include "计算器1Dlg.h" #include<cmath> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About int focus=0,point1=0,point2=0,i=0,j=0; double temp1=1,temp2=1,equal; double temp3[100],temp4[100]; class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMy1Dlg dialog CMy1Dlg::CMy1Dlg(CWnd* pParent /*=NULL*/) : CDialog(CMy1Dlg::IDD, pParent) { //{{AFX_DATA_INIT(CMy1Dlg) m_1 = 0.0; m_2 = 0.0; m_result = 0.0; m_string = _T(""); m_string2 = _T(""); m_string3 = _T(""); //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMy1Dlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMy1Dlg) DDX_Control(pDX, IDC_BUTTON_point, m_point); DDX_Text(pDX, IDC_EDIT1, m_1); DDX_Text(pDX, IDC_EDIT2, m_2); DDX_Text(pDX, IDC_EDIT3, m_result); DDX_Text(pDX, IDC_EDIT4, m_string); DDX_Text(pDX, IDC_EDIT5, m_string2); DDX_Text(pDX, IDC_EDIT7, m_string3); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CMy1Dlg, CDialog) //{{AFX_MSG_MAP(CMy1Dlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_EN_SETFOCUS(IDC_EDIT1, OnSetfocusEdit1) ON_EN_CHANGE(IDC_EDIT1, OnChangeEdit1) ON_EN_SETFOCUS(IDC_EDIT2, OnSetfocusEdit2) ON_BN_CLICKED(IDC_BUTTON1, OnButton1) ON_BN_CLICKED(IDC_BUTTON_point, OnBUTTONpoint) ON_EN_CHANGE(IDC_EDIT2, OnChangeEdit2) ON_BN_CLICKED(IDC_BUTTON2, OnButton2) ON_BN_CLICKED(IDC_BUTTON3, OnButton3) ON_BN_CLICKED(IDC_BUTTON4, OnButton4) ON_BN_CLICKED(IDC_BUTTON5, OnButton5) ON_BN_CLICKED(IDC_BUTTON6, OnButton6) ON_BN_CLICKED(IDC_BUTTON7, OnButton7) ON_BN_CLICKED(IDC_BUTTON8, OnButton8) ON_BN_CLICKED(IDC_BUTTON9, OnButton9) ON_BN_CLICKED(IDC_BUTTON0, OnButton0) ON_BN_CLICKED(IDC_BUTTON_delete, OnBUTTONdelete) ON_BN_CLICKED(IDC_BUTTON_equal, OnBUTTONequal) ON_BN_CLICKED(IDC_BUTTON15, OnButton15) ON_BN_CLICKED(IDC_BUTTON16, OnButton16) ON_BN_CLICKED(IDC_BUTTON17, OnButton17) ON_BN_CLICKED(IDC_BUTTON18, OnButton18) ON_BN_CLICKED(IDC_BUTTON19, OnButton19) ON_BN_CLICKED(IDC_BUTTON20, OnButton20) ON_BN_CLICKED(IDC_BUTTON21, OnButton21) ON_BN_CLICKED(IDC_BUTTON22, OnButton22) ON_BN_CLICKED(IDC_BUTTON23, OnButton23) ON_BN_CLICKED(IDC_BUTTON24, OnButton24) ON_BN_CLICKED(IDC_BUTTON25, OnButton25) ON_BN_CLICKED(IDC_BUTTON27, OnButton27) ON_BN_CLICKED(IDC_BUTTON28, OnButton28) ON_BN_CLICKED(IDC_BUTTON29, OnButton29) ON_BN_CLICKED(IDC_BUTTON26, OnButton26) ON_BN_CLICKED(IDC_BUTTON30, OnButton30) ON_BN_CLICKED(IDC_BUTTON31, OnButton31) ON_BN_CLICKED(IDC_BUTTON32, OnButton32) ON_BN_CLICKED(IDC_BUTTON10, OnButton10) ON_BN_CLICKED(IDC_RADIO1, OnRadio1) ON_BN_CLICKED(IDC_RADIO2, OnRadio2) ON_COMMAND(ID_MENUITEM32792, OnMenuitem32792) ON_COMMAND(ID_MENUITEM32793, OnMenuitem32793) ON_COMMAND(ID_MENUITEM32794, OnMenuitem32794) ON_COMMAND(ID_MENUITEM32795, OnMenuitem32795) ON_COMMAND(ID_MENUITEM32796, OnMenuitem32796) ON_COMMAND(ID_MENUITEM32797, OnMenuitem32797) ON_COMMAND(ID_MENUITEM32798, OnMenuitem32798) ON_COMMAND(ID_MENUITEM32799, OnMenuitem32799) ON_COMMAND(ID_MENUITEM32800, OnMenuitem32800) ON_COMMAND(ID_MENUITEM32801, OnMenuitem32801) ON_COMMAND(ID_MENUITEM32802, OnMenuitem32802) ON_COMMAND(ID_MENUITEM32791, OnMenuitem32791) ON_COMMAND(ID_MENUITEM32790, OnMenuitem32790) ON_COMMAND(ID_MENUITEM32789, OnMenuitem32789) ON_COMMAND(ID_MENUITEM32788, OnMenuitem32788) ON_COMMAND(ID_MENUITEM32803, OnMenuitem32803) ON_COMMAND(ID_MENUITEM32804, OnMenuitem32804) ON_BN_CLICKED(IDC_BUTTON33, OnButton33) ON_BN_CLICKED(IDC_BUTTON14, OnButton14) ON_COMMAND(ID_MENUITEM32809, OnMenuitem32809) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMy1Dlg message handlers BOOL CMy1Dlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control } void CMy1Dlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMy1Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle 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; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CMy1Dlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CMy1Dlg::OnSetfocusEdit1() { focus=1; } void CMy1Dlg::OnChangeEdit1() { // TODO: If this is a RICHEDIT control, the control will not // send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask() // with the ENM_CHANGE flag ORed into the mask. // TODO: Add your control notification handler code here } void CMy1Dlg::OnSetfocusEdit2() { focus=2; } void CMy1Dlg::OnBUTTONpoint() //--------------------------------------------------小数点键 { if(focus==1) point1=1; if(focus==2) point2=1; } void CMy1Dlg::OnChangeEdit2() { // TODO: If this is a RICHEDIT control, the control will not // send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask() // with the ENM_CHANGE flag ORed into the mask. // TODO: Add your control notification handler code here } void CMy1Dlg::OnButton1() //-----------------------------------------------------数字键1 {UpdateData(true); if(focus==1&&point1;==0) {m_1=m_1*10+1; i++;temp3[i]=m_1;} if(focus==1&&point1;>=1) {temp1=temp1/10;m_1=temp1+m_1; i++;temp3[i]=m_1;point1++;} if(focus==2&&point2;==0) {m_2=m_2*10+1; j++;temp4[j]=m_2;} if(focus==2&&point2;>=1) {temp2=temp2/10;m_2=temp2+m_2; j++;temp4[j]=m_2;point2++;} UpdateData(false); } void CMy1Dlg::OnButton2() //-----------------------------------------------------数字键2 {UpdateData(true); if(focus==1&&point1;==0) {m_1=m_1*10+2; i++;temp3[i]=m_1;} else if(focus==1&&point1;>=1) {temp1=temp1/10;m_1=temp1*2+m_1; i++;temp3[i]=m_1;point1++;} else if(focus==2&&point2;==0) {m_2=m_2*10+2; j++;temp4[j]=m_2;} else if(focus==2&&point2;>=1) {temp2=temp2/10;m_2=temp2*2+m_2; j++;temp4[j]=m_2;point2++;} UpdateData(false); } void CMy1Dlg::OnButton3() //-----------------------------------------------------数字键3 {UpdateData(true); if(focus==1&&point1;==0) {m_1=m_1*10+3; i++;temp3[i]=m_1;} else if(focus==1&&point1;>=1) {temp1=temp1/10;m_1=temp1*3+m_1; i++;temp3[i]=m_1;point1++;} else if(focus==2&&point2;==0) {m_2=m_2*10+3; j++;temp4[j]=m_2;} else if(focus==2&&point2;>=1) {temp2=temp2/10;m_2=temp2*3+m_2; j++;temp4[j]=m_2;point2++;} UpdateData(false); } void CMy1Dlg::OnButton4() //-----------------------------------------------------数字键4 {UpdateData(true); if(focus==1&&point1;==0) {m_1=m_1*10+4; i++;temp3[i]=m_1;} else if(focus==1&&point1;>=1) {temp1=temp1/10;m_1=temp1*4+m_1; i++;temp3[i]=m_1;point1++;} else if(focus==2&&point2;==0) {m_2=m_2*10+4; j++;temp4[j]=m_2;} else if(focus==2&&point2;>=1) {temp2=temp2/10;m_2=temp2*4+m_2; j++;temp4[j]=m_2;point2++;} UpdateData(false); } void CMy1Dlg::OnButton5() //-----------------------------------------------------数字键5 {UpdateData(true); if(focus==1&&point1;==0) {m_1=m_1*10+5; i++;temp3[i]=m_1;} else if(focus==1&&point1;>=1) {temp1=temp1/10;m_1=temp1*5+m_1; i++;temp3[i]=m_1;point1++;} else if(focus==2&&point2;==0) {m_2=m_2*10+5; j++;temp4[j]=m_2;} else if(focus==2&&point2;>=1) {temp2=temp2/10;m_2=temp2*5+m_2; j++;temp4[j]=m_2;point2++;} UpdateData(false); } void CMy1Dlg::OnButton6() //-----------------------------------------------------数字键6 {UpdateData(true); if(focus==1&&point1;==0) {m_1=m_1*10+6; i++;temp3[i]=m_1;} else if(focus==1&&point1;>=1) {temp1=temp1/10;m_1=temp1*6+m_1; i++;temp3[i]=m_1;point1++;} else if(focus==2&&point2;==0) {m_2=m_2*10+6; j++;temp4[j]=m_2;} else if(focus==2&&point2;>=1) {temp2=temp2/10;m_2=temp2*6+m_2; j++;temp4[j]=m_2;point2++;} UpdateData(false); } void CMy1Dlg::OnButton7() //-----------------------------------------------------数字键7 {UpdateData(true); if(focus==1&&point1;==0) {m_1=m_1*10+7; i++;temp3[i]=m_1;} else if(focus==1&&point1;>=1) {temp1=temp1/10;m_1=temp1*7+m_1; i++;temp3[i]=m_1;point1++;} else if(focus==2&&point2;==0) {m_2=m_2*10+7; j++;temp4[j]=m_2;} else if(focus==2&&point2;>=1) {temp2=temp2/10;m_2=temp2*7+m_2; j++;temp4[j]=m_2;point2++;} UpdateData(false); } void CMy1Dlg::OnButton8() //-----------------------------------------------------数字键8 {UpdateData(true); if(focus==1&&point1;==0) {m_1=m_1*10+8; i++;temp3[i]=m_1;} else if(focus==1&&point1;>=1) {temp1=temp1/10;m_1=temp1*8+m_1; i++;temp3[i]=m_1;point1++;} else if(focus==2&&point2;==0) {m_2=m_2*10+8; j++;temp4[j]=m_2;} else if(focus==2&&point2;>=1) {temp2=temp2/10;m_2=temp2*8+m_2; j++;temp4[j]=m_2;point2++;} UpdateData(false); } void CMy1Dlg::OnButton9() //-----------------------------------------------------数字键9 {UpdateData(true); if(focus==1&&point1;==0) {m_1=m_1*10+9; i++;temp3[i]=m_1;} else if(focus==1&&point1;>=1) {temp1=temp1/10;m_1=temp1*9+m_1; i++;temp3[i]=m_1;point1++;} else if(focus==2&&point2;==0) {m_2=m_2*10+9; j++;temp4[j]=m_2;} else if(focus==2&&point2;>=1) {temp2=temp2/10;m_2=temp2*9+m_2; j++;temp4[j]=m_2;point2++;} UpdateData(false); } void CMy1Dlg::OnButton0() //-----------------------------------------------------数字键0 {UpdateData(true); if(focus==1&&point1;==0) {m_1=m_1*10; i++;temp3[i]=m_1;} else if(focus==1&&point1;>=1) {temp1=temp1/10;m_1=temp1*0+m_1; i++;temp3[i]=m_1;point1++;} else if(focus==2&&point2;==0) {m_2=m_2*10; j++;temp4[j]=m_2;} else if(focus==2&&point2;>=1) {temp2=temp2/10;m_2=temp2*0+m_2; j++;temp4[j]=m_1;point2++;} UpdateData(false); } void CMy1Dlg::OnBUTTONdelete() //--------------------------------退格 {UpdateData(true); if(focus==1) {i--;m_1=temp3[i]; if(point1>0) {point1=point1-1;} if(temp1<1) {temp1=temp1*10;} } if(focus==2) {j--;m_2=temp4[j]; if(point2>0) {point2=point2-1;} if(temp2<1) {temp2=temp2*10;} } UpdateData(false); } void CMy1Dlg::OnBUTTONequal() {//--------------------------------------------------------------------等号键 UpdateData(true); m_result=equal; UpdateData(false); } void CMy1Dlg::OnButton14() { // TODO: Add your control notification handler code here------------- 加法 UpdateData(true); equal=m_1+m_2; m_string="+"; UpdateData(false); } void CMy1Dlg::OnButton15() { // TODO: Add your control notification handler code here-----------减法 UpdateData(true); equal=m_1-m_2; m_string="-"; UpdateData(false); } void CMy1Dlg::OnButton16() {// TODO: Add your control notification handler code here--------------乘法 UpdateData(true); equal=m_1*m_2; m_string="*"; UpdateData(false); } void CMy1Dlg::OnButton17() { // TODO: Add your control notification handler code here--------除法 UpdateData(true); equal=m_1/m_2; m_string="/"; UpdateData(false); } void CMy1Dlg::OnButton18() { // TODO: Add your control notification handler code here------------------逻辑 UpdateData(true); equal=m_1&&m_2; m_string="And";m_string2=" "; UpdateData(false); } void CMy1Dlg::OnButton19() { // TODO: Add your control notification handler code here--------------逻辑或 UpdateData(true); equal=m_1||m_2; m_string="or"; m_string2=" "; UpdateData(false); } void CMy1Dlg::OnButton20() { // TODO: Add your control notification handler code here------------------逻辑非 UpdateData(true); equal=!m_1; m_string="not"; m_string2=" "; UpdateData(false); } void CMy1Dlg::OnButton21() { // TODO: Add your control notification handler code here---------------------逻辑异或 UpdateData(true); equal=int(m_1)^int(m_2); m_string="Xor"; m_string2=" "; UpdateData(false); } void CMy1Dlg::OnButton22() { // TODO: Add your control notification handler code here---------------------正弦 UpdateData(true); m_2=sin(m_1); m_string2="Sin";m_string="="; UpdateData(false); } void CMy1Dlg::OnButton23() { // TODO: Add your control notification handler code here----------------------余弦 UpdateData(true); m_2=cos(m_1); m_string2="Cos";m_string="="; UpdateData(false); } void CMy1Dlg::OnButton24() { // TODO: Add your control notification handler code here------------正切 UpdateData(true); m_2=tan(m_1); m_string2="tan";m_string="="; UpdateData(false); } void CMy1Dlg::OnButton25() { // TODO: Add your control notification handler code here----------------求余 UpdateData(true); equal=int(m_1)%int(m_2); m_string="Mod"; UpdateData(false); } void CMy1Dlg::OnButton27() { // TODO: Add your control notification handler code here------------------log UpdateData(true); m_result=log(m_2)/log(m_1); m_string2="log"; UpdateData(false); } void CMy1Dlg::OnButton28() { // TODO: Add your control notification handler code here--------------------ln UpdateData(true); m_2=log(m_1); m_string2="ln"; m_string="="; UpdateData(false); } void CMy1Dlg::OnButton29() { // TODO: Add your control notification handler code here-------------------乘方 UpdateData(true); equal=pow(m_1,m_2); m_string="^"; UpdateData(false); } void CMy1Dlg::OnButton26() { // TODO: Add your control notification handler code here----------------阶乘 UpdateData(true); int j=1,k=int(m_1); for(;j<m_1;j++) {k=k*j;} equal=k; m_2=equal; m_string="!="; UpdateData(false); } void CMy1Dlg::OnButton30() { // TODO: Add your control notification handler code here---------------pi if(focus==1) m_1=3.1415926; else if(focus==2) m_2=3.1415926; UpdateData(false); } void CMy1Dlg::OnButton31() { // TODO: Add your control notification handler code here-------------00 m_string3="00"; UpdateData(false); } void CMy1Dlg::OnButton32() { // TODO: Add your control notification handler code here-----------------%(百分号) m_string3="%"; UpdateData(false); } void CMy1Dlg::OnButton10() { // TODO: Add your control notification handler code here-------------------复原MR focus=0,point1=0,point2=0,i=0,j=0,temp1=1,temp2=1; m_1=0;m_2=0;m_result=0; m_string=" ";m_string2=" ";m_string3=" "; UpdateData(false); } void CMy1Dlg::OnRadio1() { // TODO: Add your control notification handler code here----------------十进制转二进制 int change(int); m_2=change(int(m_1)); m_string="--->"; UpdateData(false); } int change(int c) {int h[100],k=0,x=0; for(;c!=0;) {h[k]=c%2; c=c/2; k++; } k=k-1; for(;k>=0;k--) {x=x*10+h[k]; } return x; } void CMy1Dlg::OnRadio2() { // TODO: Add your control notification handler code here------------二进制转十进制(Two to Ten) int q,num=int(m_1),shi=0; int TtT(int); q=TtT(num); for(;num>1;) {num=num-pow(10,q); shi=pow(2,q)+shi; q=TtT(num); } if(num==1) shi=shi+1; m_2=shi; m_string="--->"; UpdateData(false); } int TtT(int m) {int k,j=0; double n; n=m; for(k=0;n>2;k++) {n=n/10;} if(m==1) k=0; return k; } void CMy1Dlg::OnMenuitem32792() //------------------------菜单。加 { // TODO: Add your command handler code here CMy1Dlg::OnButton14() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32793() //----------------------菜单。减 { // TODO: Add your command handler code here CMy1Dlg::OnButton15() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32794() { // TODO: Add your command handler code here//---------------菜单。乘 CMy1Dlg::OnButton16() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32795() //-------------------------------菜单。除 { // TODO: Add your command handler code here CMy1Dlg::OnButton17() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32796() //------------------------------菜单。 { // TODO: Add your command handler code here CMy1Dlg::OnButton18() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32797() //------------------------------菜单。或 { // TODO: Add your command handler code here CMy1Dlg::OnButton19() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32798() //------------------------------菜单。非 { // TODO: Add your command handler code here CMy1Dlg::OnButton20() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32799() //------------------------------菜单。异或 { // TODO: Add your command handler code here CMy1Dlg::OnButton21() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32800() //-------------------------------菜单。正弦 { // TODO: Add your command handler code here CMy1Dlg::OnButton22() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32801() //-------------------------------菜单。余弦 { // TODO: Add your command handler code here CMy1Dlg::OnButton23() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32802() //-------------------------------菜单。正切 { // TODO: Add your command handler code here CMy1Dlg::OnButton24() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32791() //-------------------------------菜单。求余 { // TODO: Add your command handler code here CMy1Dlg::OnButton25() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32790() //---------------------------------菜单。阶乘 { // TODO: Add your command handler code here CMy1Dlg::OnButton26() ; CMy1Dlg::OnBUTTONequal(); } void CMy1Dlg::OnMenuitem32789() //--------------------------------菜单。复位 { // TODO: Add your command handler code here CMy1Dlg::OnButton10() ; } void CMy1Dlg::OnMenuitem32788() //---------------------------------菜单。退格 { // TODO: Add your command handler code here CMy1Dlg::OnBUTTONdelete(); } void CMy1Dlg::OnMenuitem32803() //----------------------------------菜单。十进制转二进制 { // TODO: Add your command handler code here CMy1Dlg::OnRadio1() ; } void CMy1Dlg::OnMenuitem32804() //---------------------------------菜单。二进制转十进制 { // TODO: Add your command handler code here CMy1Dlg::OnRadio2() ; } void CMy1Dlg::OnButton33() //--------------------------------------求倒数 { // TODO: Add your control notification handler code here UpdateData(true); m_2=1/m_1; m_string="->"; UpdateData(false); } void CMy1Dlg::OnMenuitem32809() //----------------------------------菜单求倒数 { // TODO: Add your command handler code here CMy1Dlg::OnButton33(); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值