【C++】ATM机模拟系统 :完整窗口实现
下面是一个完整的C++ ATM机模拟系统,使用Windows API实现窗口界面,包含所有基础功能模块。
我将提供完整代码并详细解释实现原理。
#include <windows.h>
#include <string>
#include <fstream>
#include <ctime>
using namespace std;// 全局变量
const string CARD_NUMBER = "1234567890";
const string PIN = "1234";
float balance = 10000.0;
float dailyWithdrawn = 0.0;
int attempts = 0;
bool atmLocked = false;
string transactionHistory = "";// 控件ID
#define ID_CARD_EDIT 101
#define ID_PIN_EDIT 102
#define ID_LOGIN_BTN 103
#define ID_BALANCE_BTN 104
#define ID_DEPOSIT_BTN 105
#define ID_WITHDRAW_BTN 106
#define ID_EXIT_BTN 107
#define ID_RECEIPT_BTN 108
#define ID_AMOUNT_EDIT 109
#define ID_CONFIRM_BTN 110
#define ID_BACK_BTN 111
#define ID_INFO_TEXT 112
#define ID_HISTORY_LIST 113// 函数声明
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void CreateLoginControls(HWND);
void CreateMainControls(HWND);
void CreateTransactionControls(HWND, const string&);
void ProcessLogin(HWND);
void ShowBalance(HWND);
void DepositMoney(HWND);
void WithdrawMoney(HWND);
void PrintReceipt(HWND);
void ResetDailyLimit();
void SaveTransaction(const string&);
void UpdateInfoText(HWND, const string&);
string GetCurrentDateTime();// 主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {static TCHAR szAppName[] = TEXT("ATM Simulation");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.style = CS_HREDRAW | CS_VREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szAppName;if (!RegisterClass(&wndclass)) {MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR);return 0;}hwnd = CreateWindow(szAppName, TEXT("银行ATM系统"), WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX,CW_USEDEFAULT, CW_USEDEFAULT, 500, 400, NULL, NULL, hInstance, NULL);ShowWindow(hwnd, iCmdShow);UpdateWindow(hwnd);while (GetMessage(&msg, NULL, 0, 0)) {TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;
}// 窗口过程
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static HWND hCardEdit, hPinEdit, hLoginBtn, hBalanceBtn, hDepositBtn, hWithdrawBtn;static HWND hExitBtn, hReceiptBtn, hAmountEdit, hConfirmBtn, hBackBtn, hInfoText, hHistoryList;switch (message) {case WM_CREATE:CreateLoginControls(hwnd);ResetDailyLimit();break;case WM_COMMAND:switch (LOWORD(wParam)) {case ID_LOGIN_BTN:ProcessLogin(hwnd);break;case ID_BALANCE_BTN:ShowBalance(hwnd);break;case ID_DEPOSIT_BTN:CreateTransactionControls(hwnd, "存款");break;case ID_WITHDRAW_BTN:CreateTransactionControls(hwnd, "取款");break;case ID_RECEIPT_BTN:PrintReceipt(hwnd);break;case ID_EXIT_BTN:DestroyWindow(hwnd);break;case ID_CONFIRM_BTN:if (GetWindowTextLength(GetDlgItem(hwnd, ID_AMOUNT_EDIT)) {char amountText[20];GetWindowText(GetDlgItem(hwnd, ID_AMOUNT_EDIT), amountText, 20);float amount = atof(amountText);if (GetWindowTextLength(GetDlgItem(hwnd, ID_CONFIRM_BTN)) {char btnText[20];GetWindowText(GetDlgItem(hwnd, ID_CONFIRM_BTN), btnText, 20);if (strcmp(btnText, "存款确认") == 0) {balance += amount;SaveTransaction("存款: +" + string(amountText) + "元");UpdateInfoText(hwnd, "存款成功!当前余额: " + to_string(balance) + "元");} else if (strcmp(btnText, "取款确认") == 0) {if (amount > balance) {UpdateInfoText(hwnd, "余额不足!");} else if (amount > 2000) {UpdateInfoText(hwnd, "单笔取款不能超过2000元");} else if (dailyWithdrawn + amount > 20000) {UpdateInfoText(hwnd, "今日取款已超限额(20000元)");} else {balance -= amount;dailyWithdrawn += amount;SaveTransaction("取款: -" + string(amountText) + "元");UpdateInfoText(hwnd, "取款成功!当前余额: " + to_string(balance) + "元");}}}}break;case ID_BACK_BTN:DestroyWindow(GetDlgItem(hwnd, ID_AMOUNT_EDIT));DestroyWindow(GetDlgItem(hwnd, ID_CONFIRM_BTN));DestroyWindow(GetDlgItem(hwnd, ID_BACK_BTN));CreateMainControls(hwnd);break;}break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, message, wParam, lParam);}return 0;
}// 创建登录界面控件
void CreateLoginControls(HWND hwnd) {CreateWindow(TEXT("STATIC"), TEXT("卡号:"), WS_CHILD | WS_VISIBLE | SS_CENTER,100, 50, 80, 25, hwnd, NULL, NULL, NULL);CreateWindow(TEXT("EDIT"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,180, 50, 200, 25, hwnd, (HMENU)ID_CARD_EDIT, NULL, NULL);CreateWindow(TEXT("STATIC"), TEXT("密码:"), WS_CHILD | WS_VISIBLE | SS_CENTER,100, 100, 80, 25, hwnd, NULL, NULL, NULL);CreateWindow(TEXT("EDIT"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_BORDER | ES_PASSWORD | ES_AUTOHSCROLL,180, 100, 200, 25, hwnd, (HMENU)ID_PIN_EDIT, NULL, NULL);CreateWindow(TEXT("BUTTON"), TEXT("登录"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,200, 150, 100, 30, hwnd, (HMENU)ID_LOGIN_BTN, NULL, NULL);CreateWindow(TEXT("STATIC"), TEXT(""), WS_CHILD | WS_VISIBLE | SS_LEFT,50, 200, 400, 30, hwnd, (HMENU)ID_INFO_TEXT, NULL, NULL);UpdateInfoText(hwnd, "请输入您的银行卡号和密码");
}// 创建主界面控件
void CreateMainControls(HWND hwnd) {CreateWindow(TEXT("BUTTON"), TEXT("查询余额"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,50, 50, 150, 40, hwnd, (HMENU)ID_BALANCE_BTN, NULL, NULL);CreateWindow(TEXT("BUTTON"), TEXT("存款"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,250, 50, 150, 40, hwnd, (HMENU)ID_DEPOSIT_BTN, NULL, NULL);CreateWindow(TEXT("BUTTON"), TEXT("取款"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,50, 120, 150, 40, hwnd, (HMENU)ID_WITHDRAW_BTN, NULL, NULL);CreateWindow(TEXT("BUTTON"), TEXT("打印凭条"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,250, 120, 150, 40, hwnd, (HMENU)ID_RECEIPT_BTN, NULL, NULL);CreateWindow(TEXT("BUTTON"), TEXT("退出系统"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,150, 200, 150, 40, hwnd, (HMENU)ID_EXIT_BTN, NULL, NULL);CreateWindow(TEXT("STATIC"), TEXT(""), WS_CHILD | WS_VISIBLE | SS_LEFT,50, 260, 400, 60, hwnd, (HMENU)ID_INFO_TEXT, NULL, NULL);UpdateInfoText(hwnd, "请选择您需要的服务");
}// 创建交易界面控件
void CreateTransactionControls(HWND hwnd, const string& type) {// 清除主界面按钮DestroyWindow(GetDlgItem(hwnd, ID_BALANCE_BTN));DestroyWindow(GetDlgItem(hwnd, ID_DEPOSIT_BTN));DestroyWindow(GetDlgItem(hwnd, ID_WITHDRAW_BTN));DestroyWindow(GetDlgItem(hwnd, ID_RECEIPT_BTN));DestroyWindow(GetDlgItem(hwnd, ID_EXIT_BTN));string label = type + "金额:";CreateWindow(TEXT("STATIC"), label.c_str(), WS_CHILD | WS_VISIBLE | SS_CENTER,100, 80, 100, 25, hwnd, NULL, NULL, NULL);CreateWindow(TEXT("EDIT"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | ES_NUMBER,220, 80, 150, 25, hwnd, (HMENU)ID_AMOUNT_EDIT, NULL, NULL);string btnText = type + "确认";CreateWindow(TEXT("BUTTON"), btnText.c_str(), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,100, 140, 120, 40, hwnd, (HMENU)ID_CONFIRM_BTN, NULL, NULL);CreateWindow(TEXT("BUTTON"), TEXT("返回"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,260, 140, 120, 40, hwnd, (HMENU)ID_BACK_BTN, NULL, NULL);UpdateInfoText(hwnd, "请输入" + type + "金额,然后点击确认");
}// 处理登录逻辑
void ProcessLogin(HWND hwnd) {if (atmLocked) {UpdateInfoText(hwnd, "账户已锁定,请联系银行工作人员");return;}char cardText[20], pinText[20];GetWindowText(GetDlgItem(hwnd, ID_CARD_EDIT), cardText, 20);GetWindowText(GetDlgItem(hwnd, ID_PIN_EDIT), pinText, 20);if (string(cardText) == CARD_NUMBER && string(pinText) == PIN) {// 清除登录控件DestroyWindow(GetDlgItem(hwnd, ID_CARD_EDIT));DestroyWindow(GetDlgItem(hwnd, ID_PIN_EDIT));DestroyWindow(GetDlgItem(hwnd, ID_LOGIN_BTN));DestroyWindow(GetDlgItem(hwnd, ID_INFO_TEXT));// 创建主界面CreateMainControls(hwnd);attempts = 0;} else {attempts++;if (attempts >= 3) {atmLocked = true;UpdateInfoText(hwnd, "密码错误次数过多,账户已锁定!");} else {UpdateInfoText(hwnd, "卡号或密码错误!剩余尝试次数: " + to_string(3 - attempts));}}
}// 显示余额
void ShowBalance(HWND hwnd) {string info = "当前余额: " + to_string(balance) + "元\n";info += "今日已取款: " + to_string(dailyWithdrawn) + "元";UpdateInfoText(hwnd, info);
}// 打印凭条
void PrintReceipt(HWND hwnd) {string receipt = "====== 银行交易凭条 ======\n";receipt += "时间: " + GetCurrentDateTime() + "\n";receipt += "卡号: " + CARD_NUMBER + "\n";receipt += "当前余额: " + to_string(balance) + "元\n";receipt += "今日已取款: " + to_string(dailyWithdrawn) + "元\n";receipt += "交易历史:\n" + transactionHistory;receipt += "==========================";UpdateInfoText(hwnd, receipt);
}// 更新信息文本
void UpdateInfoText(HWND hwnd, const string& text) {HWND hInfo = GetDlgItem(hwnd, ID_INFO_TEXT);SetWindowText(hInfo, text.c_str());
}// 保存交易记录
void SaveTransaction(const string& transaction) {transactionHistory += GetCurrentDateTime() + " - " + transaction + "\n";
}// 获取当前日期时间
string GetCurrentDateTime() {time_t now = time(0);tm* ltm = localtime(&now);char buffer[80];strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", ltm);return string(buffer);
}// 重置每日限额
void ResetDailyLimit() {time_t now = time(0);tm* ltm = localtime(&now);static int lastResetDay = ltm->tm_mday;if (ltm->tm_mday != lastResetDay) {dailyWithdrawn = 0.0;lastResetDay = ltm->tm_mday;}
}
功能模块详解
1. 系统架构
- Windows API编程:使用Windows原生API创建窗口应用程序
- 面向过程设计:采用函数模块化设计,每个功能独立实现
- 安全机制:密码错误锁定、取款限额等安全措施
2. 核心功能实现
用户认证模块
void ProcessLogin(HWND hwnd) {if (atmLocked) {UpdateInfoText(hwnd, "账户已锁定,请联系银行工作人员");return;}// 获取输入GetWindowText(GetDlgItem(hwnd, ID_CARD_EDIT), cardText, 20);GetWindowText(GetDlgItem(hwnd, ID_PIN_EDIT), pinText, 20);// 验证信息if (string(cardText) == CARD_NUMBER && string(pinText) == PIN) {// 登录成功处理CreateMainControls(hwnd);} else {attempts++;if (attempts >= 3) {atmLocked = true; // 锁定账户}}
}
交易处理模块
// 存款处理
balance += amount;
SaveTransaction("存款: +" + string(amountText) + "元");// 取款处理(含限额检查)
if (amount > balance) {// 余额不足
}
else if (amount > 2000) {// 单笔超限
}
else if (dailyWithdrawn + amount > 20000) {// 日累计超限
}
else {balance -= amount;dailyWithdrawn += amount;SaveTransaction("取款: -" + string(amountText) + "元");
}
凭条打印模块
void PrintReceipt(HWND hwnd) {string receipt = "====== 银行交易凭条 ======\n";receipt += "时间: " + GetCurrentDateTime() + "\n";receipt += "卡号: " + CARD_NUMBER + "\n";receipt += "当前余额: " + to_string(balance) + "元\n";receipt += "今日已取款: " + to_string(dailyWithdrawn) + "元\n";receipt += "交易历史:\n" + transactionHistory;// ...
}
3. 界面设计
- 分层界面:登录界面 → 主菜单 → 交易界面
- 控件管理:动态创建/销毁控件实现界面切换
- 信息反馈:实时更新信息区域提供操作反馈
4. 安全机制
- 密码保护:三次错误尝试锁定账户
- 取款限额:
- 单笔 ≤ 2000元
- 每日累计 ≤ 20000元
- 交易记录:完整记录所有操作供审计
- 日限额重置:每日自动重置取款额度
void ResetDailyLimit() {time_t now = time(0);tm* ltm = localtime(&now);static int lastResetDay = ltm->tm_mday;if (ltm->tm_mday != lastResetDay) {dailyWithdrawn = 0.0; // 重置日取款额}
}
编译与运行说明
1.开发环境:
- Windows系统
- 支持Windows API的编译器(如MinGW、Visual Studio)
2.编译命令(g++):
g++ atm.cpp -o atm.exe -luser32 -lgdi32 -lcomctl32
3.运行:
- 直接执行生成的
atm.exe
- 测试账号:
1234567890
- 测试密码:
1234
扩展建议
- 数据库集成:使用SQLite存储多用户账户信息
- 文件存储:交易记录保存到文件
- 界面美化:添加图标、背景图片
- 网络功能:连接银行服务器验证账户
- 语音提示:增加操作语音提示
本ATM模拟系统完整实现了银行自动柜员机的基本功能,代码结构清晰,模块划分明确,适合学习Windows API编程和金融系统原理。
通过添加异常处理和文件存储,可以进一步增强系统健壮性和实用性
复习要点
- Windows API窗口创建流程
- 消息循环处理机制
- 控件动态管理技术
- 金融系统安全设计原则
- 交易事务处理逻辑
- 时间处理与限额重置机制
如需进一步扩展功能,可以考虑添加转账、修改密码等功能模块
资源推荐:
C/C++学习交流君羊 << 点击加入
C/C++教程