MFC学习——简易计算器以及跨应用通信

对于一个MFC程序来说,在vs2019下做开发的话,可能比较重要的就四个文件,分别是应用程序类c文件和对话框类c文件,应用程序类.h文件和对话框类.h文件

其中

应用程序类负责 程序入口、初始化、主消息循环

对话框类负责 界面控件、业务逻辑、用户交互

命名规则:如果你新建项目时取名FlashTool,那么VS会自动生成:

CFlashToolApp → FlashTool.h / FlashTool.cpp

CFlashToolDlg → FlashToolDlg.h / FlashToolDlg.cpp

其中具体界面控件摆放,可以在编辑器里可视化操作

cpp 复制代码
// MFCApplicationMathDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "MFCApplicationMath.h"
#include "MFCApplicationMathDlg.h"
#include "afxdialogex.h"
#include <atlimage.h>
#include <gdiplus.h>  // 添加 GDI+ 头文件
#include <vector>  // 如果使用 vector

#pragma comment(lib, "gdiplus.lib")  // 链接 GDI+ 库

using namespace Gdiplus;

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序"关于"菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

	// 添加这个方法:用于设置主窗口指针
	void SetMainDialog(CMFCApplicationMathDlg* pMainDlg)
	{
		m_pMainDlg = pMainDlg;
	}

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

protected:
	virtual void DoDataExchange(CDataExchange* pDX);
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);

protected:
	DECLARE_MESSAGE_MAP()

private:
	Gdiplus::Image* m_pImage;  // 图片指针
	CMFCApplicationMathDlg* m_pMainDlg;  // 主窗口指针

public:
	afx_msg void OnBnClickedClearSon();
	afx_msg void OnBnClickedOk();
};

// CAboutDlg 构造函数 - 初始化所有成员变量
CAboutDlg::CAboutDlg()
	: CDialogEx(IDD_ABOUTBOX)
	, m_pImage(nullptr)
	, m_pMainDlg(nullptr)  // 初始化主窗口指针为 nullptr
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BOOL CAboutDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 使用 GDI+ 加载图片
	m_pImage = Gdiplus::Image::FromFile(_T("E:\\test.png"));

	if (m_pImage == nullptr || m_pImage->GetLastStatus() != Gdiplus::Ok)
	{
		delete m_pImage;
		m_pImage = nullptr;
		TRACE(_T("图片加载失败: E:\\test.png\n"));
	}

	return TRUE;
}

BOOL CAboutDlg::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;  // 不擦除背景,避免闪烁
}

void CAboutDlg::OnPaint()
{
	CPaintDC dc(this);

	// 获取对话框客户区大小
	CRect rect;
	GetClientRect(&rect);

	// 创建 GDI+ 图形对象
	Gdiplus::Graphics graphics(dc.m_hDC);

	// 用对话框背景色填充
	Gdiplus::SolidBrush brush(Gdiplus::Color(240, 240, 240));  // 浅灰色背景
	graphics.FillRectangle(&brush, 0, 0, rect.Width(), rect.Height());

	if (m_pImage != nullptr)
	{
		// 获取图片原始尺寸
		int imgWidth = m_pImage->GetWidth();
		int imgHeight = m_pImage->GetHeight();

		// 计算居中位置
		int x = (rect.Width() - imgWidth) / 2;
		int y = (rect.Height() - imgHeight) / 2;

		// 绘制图片
		graphics.DrawImage(m_pImage, x, y, imgWidth, imgHeight);
	}
	else
	{
		// 图片加载失败,显示文字
		CFont* pOldFont = dc.SelectObject(GetFont());
		dc.SetBkMode(TRANSPARENT);

		CString strMsg;
		strMsg.Format(_T("图片加载失败\n\n请检查路径: E:\\test.png\n\n图片格式: 支持 PNG、JPG、BMP"));

		CRect textRect = rect;
		textRect.DeflateRect(20, 20);
		dc.DrawText(strMsg, textRect, DT_CENTER | DT_WORDBREAK);

		dc.SelectObject(pOldFont);
	}
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
	ON_BN_CLICKED(IDC_CLEAR_SON, &CAboutDlg::OnBnClickedClearSon)
	ON_BN_CLICKED(IDOK, &CAboutDlg::OnBnClickedOk)
END_MESSAGE_MAP()

// CAboutDlg 清除按钮响应函数
void CAboutDlg::OnBnClickedClearSon()
{
	// 检查主窗口指针是否有效
	if (m_pMainDlg != nullptr && ::IsWindow(m_pMainDlg->GetSafeHwnd()))
	{
		// 清除主窗口中的编辑框内容(计算器显示屏)
		m_pMainDlg->SetDlgItemText(IDC_EDIT1, _T(""));

		// 重新启用编辑框(如果之前被禁用了)
		m_pMainDlg->GetDlgItem(IDC_EDIT1)->EnableWindow(TRUE);
	}
	else
	{
		MessageBox(_T("主窗口指针无效,无法清除"), _T("错误"), MB_OK | MB_ICONERROR);
	}
}


// CMFCApplicationMathDlg 对话框

CMFCApplicationMathDlg::CMFCApplicationMathDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_MFCAPPLICATIONMATH_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMFCApplicationMathDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CMFCApplicationMathDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON19, &CMFCApplicationMathDlg::OnBnClickedButton19)
	ON_BN_CLICKED(IDC_BUTTON10, &CMFCApplicationMathDlg::OnBnClickedButton10)
	ON_BN_CLICKED(IDC_BUTTON11, &CMFCApplicationMathDlg::OnBnClickedButton11)
	ON_BN_CLICKED(IDC_BUTTON12, &CMFCApplicationMathDlg::OnBnClickedButton12)
	ON_BN_CLICKED(IDC_BUTTON13, &CMFCApplicationMathDlg::OnBnClickedButton13)
	ON_BN_CLICKED(IDC_BUTTON14, &CMFCApplicationMathDlg::OnBnClickedButton14)
	ON_BN_CLICKED(IDC_BUTTON15, &CMFCApplicationMathDlg::OnBnClickedButton15)
	ON_BN_CLICKED(IDC_BUTTON16, &CMFCApplicationMathDlg::OnBnClickedButton16)
	ON_BN_CLICKED(IDC_BUTTON17, &CMFCApplicationMathDlg::OnBnClickedButton17)
	ON_BN_CLICKED(IDC_BUTTON18, &CMFCApplicationMathDlg::OnBnClickedButton18)
	ON_BN_CLICKED(IDC_BUTTON20, &CMFCApplicationMathDlg::OnBnClickedButton20)
	ON_BN_CLICKED(IDC_BUTTON21, &CMFCApplicationMathDlg::OnBnClickedButton21)
	ON_BN_CLICKED(IDC_BUTTON22, &CMFCApplicationMathDlg::OnBnClickedButton22)
	ON_BN_CLICKED(IDC_BUTTON23, &CMFCApplicationMathDlg::OnBnClickedButton23)
	ON_BN_CLICKED(IDC_BUTTON24, &CMFCApplicationMathDlg::OnBnClickedButton24)
	ON_COMMAND(ID_32771, &CMFCApplicationMathDlg::On_author)
	ON_BN_CLICKED(IDC_BUTTON25, &CMFCApplicationMathDlg::OnBnClickedButton25)
	ON_BN_CLICKED(IDC_BUTTON1, &CMFCApplicationMathDlg::OnBnClickedButton1)
END_MESSAGE_MAP()


// CMFCApplicationMathDlg 消息处理程序

BOOL CMFCApplicationMathDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 注意:GDI+ 的初始化建议移到 CWinApp::InitInstance() 中
	// 这里仅作为示例,实际使用时可能会重复初始化
	static bool bGdiPlusStarted = false;
	if (!bGdiPlusStarted)
	{
		GdiplusStartupInput gdiplusStartupInput;
		ULONG_PTR gdiplusToken;
		GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
		bGdiPlusStarted = true;
	}

	// 将"关于..."菜单项添加到系统菜单中。
	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);

	// 加载菜单
	CMenu menu;
	menu.LoadMenuW(IDR_MENU1);
	SetMenu(&menu);
	menu.Detach();

	return TRUE;
}

void CMFCApplicationMathDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.SetMainDialog(this);  // 传递主窗口指针给关于对话框
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

void CMFCApplicationMathDlg::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 CMFCApplicationMathDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

// 数字按钮处理函数
void CMFCApplicationMathDlg::OnBnClickedButton10()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("0");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton11()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("1");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton12()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("2");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton13()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("3");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton14()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("4");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton15()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("5");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton16()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("6");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton17()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("7");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton18()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("8");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton19()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("9");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton20()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("+");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton21()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("-");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton22()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("*");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton23()
{
	CString strCurrent;
	GetDlgItemText(IDC_EDIT1, strCurrent);
	strCurrent += _T("/");
	SetDlgItemText(IDC_EDIT1, strCurrent);
}

void CMFCApplicationMathDlg::OnBnClickedButton24()
{
	CString strExpression;
	GetDlgItemText(IDC_EDIT1, strExpression);

	if (strExpression.IsEmpty())
		return;

	strExpression.TrimRight(_T("="));

	double result = 0;
	TCHAR op = 0;
	double firstNum = 0, secondNum = 0;

	int opPos = -1;
	for (int i = 0; i < strExpression.GetLength(); i++)
	{
		TCHAR ch = strExpression[i];
		if (ch == '+' || ch == '-' || ch == '*' || ch == '/')
		{
			op = ch;
			opPos = i;
			break;
		}
	}

	if (opPos != -1)
	{
		CString strFirst = strExpression.Left(opPos);
		CString strSecond = strExpression.Mid(opPos + 1);

		firstNum = _ttof(strFirst);
		secondNum = _ttof(strSecond);

		switch (op)
		{
		case '+': result = firstNum + secondNum; break;
		case '-': result = firstNum - secondNum; break;
		case '*': result = firstNum * secondNum; break;
		case '/':
			if (secondNum == 0)
			{
				SetDlgItemText(IDC_EDIT1, _T("错误:除数不能为0"));
				return;
			}
			result = firstNum / secondNum;
			break;
		}

		CString strResult;
		if (result == (int)result)
			strResult.Format(_T("%d"), (int)result);
		else
			strResult.Format(_T("%g"), result);

		SetDlgItemText(IDC_EDIT1, strResult);
	}
	else
	{
		SetDlgItemText(IDC_EDIT1, _T("表达式错误"));
	}
}

// 菜单"关于"响应函数
void CMFCApplicationMathDlg::On_author()
{
	// 在堆上创建对话框(不能用局部变量)
	CAboutDlg* pDlg = new CAboutDlg();

	// 传递主窗口指针
	pDlg->SetMainDialog(this);

	// 创建非模态对话框(IDD_ABOUTBOX 是你的对话框资源ID)
	pDlg->Create(IDD_ABOUTBOX, this);

	// 显示窗口
	pDlg->ShowWindow(SW_SHOW);
}

// 清除按钮响应函数
void CMFCApplicationMathDlg::OnBnClickedButton25()
{
	SetDlgItemText(IDC_EDIT1, _T(""));
	GetDlgItem(IDC_EDIT1)->SetFocus();
}

// 禁用编辑框按钮(示例功能)
void CMFCApplicationMathDlg::OnBnClickedButton1()
{
	GetDlgItem(IDC_EDIT1)->EnableWindow(FALSE);
}

void CAboutDlg::OnBnClickedOk()
{
	std::vector<HWND> vecNotepads;

	// 找到所有记事本
	EnumWindows([](HWND hWnd, LPARAM lParam) -> BOOL {
		TCHAR szClass[256];
		GetClassName(hWnd, szClass, 256);
		if (_tcscmp(szClass, _T("Notepad")) == 0)
		{
			((std::vector<HWND>*)lParam)->push_back(hWnd);
		}
		return TRUE;
		}, (LPARAM)&vecNotepads);

	if (vecNotepads.empty())
	{
		MessageBox(_T("没有找到任何记事本窗口"), _T("提示"), MB_OK);
		return;
	}

	// 获取当前时间
	CTime now = CTime::GetCurrentTime();
	CString strTime = now.Format(_T("%Y-%m-%d %H:%M:%S"));

	// 要追加的内容
	CString strText;
	strText.Format(_T("[%s] 批量追加的内容"), strTime);

	int nCount = 0;
	for (HWND hNotepad : vecNotepads)
	{
		if (::IsWindow(hNotepad))
		{
			::SetForegroundWindow(hNotepad);
			::BringWindowToTop(hNotepad);
			Sleep(150);

			// Ctrl+End
			keybd_event(VK_CONTROL, 0, 0, 0);
			keybd_event(VK_END, 0, 0, 0);
			Sleep(20);
			keybd_event(VK_END, 0, KEYEVENTF_KEYUP, 0);
			keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);

			Sleep(50);

			// 换行
			keybd_event(VK_RETURN, 0, 0, 0);
			Sleep(10);
			keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);

			Sleep(50);

			// 输入内容
			for (int i = 0; i < strText.GetLength(); i++)
			{
				INPUT ip = { 0 };
				ip.type = INPUT_KEYBOARD;
				ip.ki.wVk = 0;
				ip.ki.wScan = strText[i];
				ip.ki.dwFlags = KEYEVENTF_UNICODE;
				SendInput(1, &ip, sizeof(INPUT));

				ip.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
				SendInput(1, &ip, sizeof(INPUT));
				Sleep(5);
			}

			nCount++;
		}
	}

	CString strMsg;
	strMsg.Format(_T("已向 %d 个记事本追加内容\n时间戳:%s"), nCount, strTime);
	MessageBox(strMsg, _T("完成"), MB_OK);
}

这是一个简易计算器的对话框类c文件

相关推荐
星恒讯工业路由器3 小时前
星恒讯便携移动路由器的好处
网络·5g·智能路由器·信息与通信·wifi6·便携
踏着七彩祥云的小丑4 小时前
Go学习第1天:入门
开发语言·学习·golang·go
憧憬成为web高手4 小时前
[0CTF 2016]piapiapia
学习
imDwAaY4 小时前
贝叶斯网络到粒子滤波Python算法实现 CS188 Proj4 学习笔记
网络·人工智能·笔记·python·学习·算法
我想我不够好。5 小时前
挖掘机技能介绍
学习
咸甜适中5 小时前
rust语言学习笔记Trait(十五)Drop(释放资源)
笔记·学习·rust
IT笔记6 小时前
【Rust】 Rust宏学习笔记
笔记·学习·rust
写代码写到手抽筋6 小时前
天线极化方向核心原理及工程
5g