#include <graphics.h> // EasyX图形库
#include <fstream>
#include <string>
#include <vector>
#include <iomanip>
#include <algorithm>
using namespace std;;
// 全局常量定义
const int WIDTH = 800; // 窗口宽度
const int HEIGHT = 600; // 窗口高度
const int MARGIN = 20; // 边距
const int BUTTON_HEIGHT = 40;// 按钮高度
const int INPUT_HEIGHT = 30; // 输入框高度
class InputBox;
// 用户信息结构
class User {
public:
string nickname;
string account;
string password;
int levelsCleared;
};
// 按钮类,用于封装界面按钮
class Button {
private:
int x, y, width, height;
string text;
bool isHovered;
COLORREF normalColor, hoverColor, textColor;
public:
Button(int _x, int _y, int _width, int _height, string _text)
: x(_x), y(_y), width(_width), height(_height), text(_text), isHovered(false) {
normalColor = RGB(200, 200, 200);
hoverColor = RGB(150, 150, 150);
textColor = RGB(0, 0, 0);
}
// 绘制按钮
void draw() {
setfillcolor(isHovered ? hoverColor : normalColor);
fillrectangle(x, y, x + width, y + height);
settextcolor(textColor);
settextstyle(20, 0, _T("宋体"));
int textWidth = textwidth(text.c_str());
int textHeight = textheight(text.c_str());
outtextxy(x + (width - textWidth) / 2, y + (height - textHeight) / 2, text.c_str());
}
// 检查鼠标是否在按钮上
bool isMouseOver(int mx, int my) {
return mx >= x && mx <= x + width && my >= y && my <= y + height;
}
// 设置鼠标悬停状态
void setHovered(bool hover) {
isHovered = hover;
}
string getText() const {
return text;
}
};
// 输入框类
class InputBox {
private:
int x, y, width, height;
string text;
string placeholder;
bool isFocused;
COLORREF bgColor, borderColor, textColor, placeholderColor;
public:
InputBox(int _x, int _y, int _width, int _height, string _placeholder)
: x(_x), y(_y), width(_width), height(_height), placeholder(_placeholder), isFocused(false) {
bgColor = RGB(255, 255, 255);
borderColor = RGB(150, 150, 150);
textColor = RGB(0, 0, 0);
placeholderColor = RGB(180, 180, 180);
}
// 绘制输入框
void draw() {
// 绘制背景和边框
setfillcolor(bgColor);
fillrectangle(x, y, x + width, y + height);
setlinecolor(borderColor);
rectangle(x, y, x + width, y + height);
// 绘制文本或占位符
settextcolor(isFocused || !text.empty() ? textColor : placeholderColor);
settextstyle(16, 0, _T("宋体"));
if (text.empty() && !isFocused) {
outtextxy(x + 5, y + (height - textheight(placeholder.c_str())) / 2, placeholder.c_str());
}
else {
outtextxy(x + 5, y + (height - textheight(text.c_str())) / 2, text.c_str());
}
// 绘制光标
if (isFocused) {
int cursorX = x + 5 + textwidth(text.c_str());
int cursorY = y + 5;
int cursorHeight = height - 10;
solidrectangle(cursorX, cursorY, cursorX + 2, cursorY + cursorHeight);
}
}
// 处理键盘输入
void handleKey(int key) {
if (!isFocused) return;
if (key == VK_BACK) { // 退格键
if (!text.empty()) text.pop_back();
}
else if (key == VK_RETURN) { // 回车键
isFocused = false;
}
else if (key >= 32 && key <= 126) { // 可打印字符
text += (char)key;
}
}
// 设置焦点
void setFocus(bool focus) {
isFocused = focus;
}
// 获取输入文本
string getText() const {
return text;
}
// 清空输入文本
void clear() {
text = "";
}
bool isMouseOver(int mx, int my) const {
return (mx >= x && mx <= x + width && my >= y && my <= y + height);
}
};
// 读取所有用户信息
vector<User> readUsers() {
vector<User> users;
ifstream file("users.txt");
if (file.is_open()) {
string line;
// 跳过标题行
if (getline(file, line)) {
while (getline(file, line)) {
User user;
size_t pos1 = line.find('\t');
size_t pos2 = line.find('\t', pos1 + 1);
size_t pos3 = line.find('\t', pos2 + 1);
if (pos1 != string::npos && pos2 != string::npos && pos3 != string::npos) {
user.nickname = line.substr(0, pos1);
user.account = line.substr(pos1 + 1, pos2 - pos1 - 1);
user.password = line.substr(pos2 + 1, pos3 - pos2 - 1);
user.levelsCleared = stoi(line.substr(pos3 + 1));
users.push_back(user);
}
}
}
file.close();
}
return users;
}
// 保存用户信息到文件
bool saveUsers(const vector<User>& users) {
ofstream file("users.txt");
if (!file.is_open()) {
return false;
}
// 写入标题行
file << "nickname\taccount\tpassword\tlevelsCleared" << endl;
// 写入所有用户
for (const auto& user : users) {
file << user.nickname << "\t" << user.account << "\t"
<< user.password << "\t" << user.levelsCleared << endl;
}
file.close();
return true;
}
// 主窗口类
class MainWindow {
private:
vector<Button> buttons;
vector<InputBox> inputBoxes;
vector<User> users;
int currentPage;
bool isAddingUser;
string currentAccount;
public:
MainWindow() : currentPage(0), isAddingUser(false) {
// 初始化图形窗口
initgraph(WIDTH, HEIGHT);
setbkcolor(RGB(240, 240, 240));
cleardevice();
// 确保文件存在并写入标题行
ifstream checkFile("users.txt");
if (!checkFile.good()) {
ofstream createFile("users.txt");
if (createFile.is_open()) {
createFile << "nickname\taccount\tpassword\tlevelsCleared" << endl;
createFile.close();
}
}
checkFile.close();
// 初始化界面元素
initUI();
}
~MainWindow() {
closegraph();
}
// 初始化用户界面
void initUI() {
buttons.clear();
inputBoxes.clear();
if (isAddingUser) {
// 添加用户界面
initAddUserUI();
}
else {
// 主菜单界面
initMainMenuUI();
}
}
// 初始化主菜单界面
void initMainMenuUI() {
// 标题
settextcolor(RGB(50, 50, 200));
settextstyle(30, 0, _T("宋体"));
outtextxy((WIDTH - textwidth(_T("用户信息管理系统"))) / 2, 50, _T("用户信息管理系统"));
// 按钮
int buttonWidth = 200;
int yPos = 150;
buttons.push_back(Button((WIDTH - buttonWidth) / 2, yPos, buttonWidth, BUTTON_HEIGHT, "添加用户信息")); yPos += 80;
buttons.push_back(Button((WIDTH - buttonWidth) / 2, yPos, buttonWidth, BUTTON_HEIGHT, "查看所有用户")); yPos += 80;
buttons.push_back(Button((WIDTH - buttonWidth) / 2, yPos, buttonWidth, BUTTON_HEIGHT, "修改用户信息")); yPos += 80;
buttons.push_back(Button((WIDTH - buttonWidth) / 2, yPos, buttonWidth, BUTTON_HEIGHT, "删除用户信息")); yPos += 80;
buttons.push_back(Button((WIDTH - buttonWidth) / 2, yPos, buttonWidth, BUTTON_HEIGHT, "退出系统"));
}
// 初始化添加用户界面
void initAddUserUI() {
// 标题
settextcolor(RGB(50, 50, 200));
settextstyle(24, 0, _T("宋体"));
outtextxy((WIDTH - textwidth(_T("添加用户信息"))) / 2, 30, _T("添加用户信息"));
// 输入框
int inputWidth = 300;
char buffer[32];
_itoa_s((WIDTH - inputWidth) / 2, buffer, 10);
int yPos = 100;
inputBoxes.push_back(InputBox(buffer, yPos, _T("inputWidth"), _T("INPUT_HEIGHT"), "请输入昵称")); yPos += 60;
inputBoxes.push_back(InputBox(buffer, yPos, _T("inputWidth"), _T("INPUT_HEIGHT"), "请输入账号")); yPos += 60;
inputBoxes.push_back(InputBox(buffer, yPos, _T("inputWidth"), _T("INPUT_HEIGHT"), "请输入密码")); yPos += 60;
inputBoxes.push_back(InputBox(buffer, yPos, _T("inputWidth"), _T("INPUT_HEIGHT"), "请输入通关数"));
// 按钮
int buttonWidth = 120;
yPos += 80;
buttons.push_back(Button((WIDTH - buttonWidth * 2 - 20) / 2, yPos, buttonWidth, BUTTON_HEIGHT, "确认添加"));
buttons.push_back(Button((WIDTH + buttonWidth * 2 + 20) / 2, yPos, buttonWidth, BUTTON_HEIGHT, "取消"));
}
// 绘制用户列表界面
void drawUserList() {
cleardevice();
// 标题
settextcolor(RGB(50, 50, 200));
settextstyle(24, 0, _T("宋体"));
outtextxy((WIDTH - textwidth(_T("用户信息列表"))) / 2, 30, _T("用户信息列表"));
// 读取用户数据
users = readUsers();
if (users.empty()) {
settextcolor(RGB(0, 0, 0));
settextstyle(18, 0, _T("宋体"));
outtextxy((WIDTH - textwidth(_T("暂无用户信息"))) / 2, 100, _T("暂无用户信息"));
// 返回按钮
int buttonWidth = 120;
buttons.clear();
buttons.push_back(Button((WIDTH - buttonWidth) / 2, 180, buttonWidth, BUTTON_HEIGHT, "返回主菜单"));
return;
}
// 绘制表头
settextcolor(RGB(0, 0, 0));
settextstyle(16, 0, _T("宋体"));
outtextxy(MARGIN, 80, _T("昵称"));
outtextxy(MARGIN + 120, 80, _T("账号"));
outtextxy(MARGIN + 240, 80, _T("密码"));
outtextxy(MARGIN + 360, 80, _T("通关数"));
line(MARGIN, 100, WIDTH - MARGIN, 100);
// 绘制用户数据
int yPos = 120;
for (size_t i = 0; i < users.size(); i++) {
if (yPos > HEIGHT - 100) break;
outtextxy(MARGIN, yPos, users[i].nickname.c_str());
outtextxy(MARGIN + 120, yPos, users[i].account.c_str());
outtextxy(MARGIN + 240, yPos, users[i].password.c_str());
outtextxy(MARGIN + 360, yPos, to_string(users[i].levelsCleared).c_str());
yPos += 30;
}
// 按钮
int buttonWidth = 120;
buttons.clear();
buttons.push_back(Button(MARGIN, HEIGHT - 80, buttonWidth, BUTTON_HEIGHT, "返回主菜单"));
}
// 处理修改用户界面
void processModifyUser() {
cleardevice();
// 标题
settextcolor(RGB(50, 50, 200));
settextstyle(24, 0, _T("宋体"));
outtextxy((WIDTH - textwidth(_T("修改用户信息"))) / 2, 30, _T("修改用户信息"));
// 输入框 - 账号
int inputWidth = 300;
char buffer[32];
_itoa_s((WIDTH - inputWidth) / 2, buffer, 10);
inputBoxes.clear();
inputBoxes.push_back(InputBox(buffer, 100, "inputWidth", "INPUT_HEIGHT", "请输入要修改的用户账号"));
// 按钮
int buttonWidth = 120;
buttons.clear();
buttons.push_back(Button((WIDTH - buttonWidth) / 2, 180, buttonWidth, BUTTON_HEIGHT, "查找用户"));
buttons.push_back(Button((WIDTH - buttonWidth) / 2, 240, buttonWidth, BUTTON_HEIGHT, "返回主菜单"));
}
// 显示用户修改界面
void showModifyUserInterface(const string& account) {
cleardevice();
// 查找用户
users = readUsers();
User* userToModify = nullptr;
for (auto& user : users) {
if (user.account == account) {
userToModify = &user;
break;
}
}
if (!userToModify) {
settextcolor(RGB(200, 0, 0));
settextstyle(18, 0, _T("宋体"));
outtextxy((WIDTH - textwidth(_T("未找到该用户!"))) / 2, 100, _T("未找到该用户!"));
// 返回按钮
int buttonWidth = 120;
buttons.clear();
buttons.push_back(Button((WIDTH - buttonWidth) / 2, 180, buttonWidth, BUTTON_HEIGHT, "返回主菜单"));
return;
}
// 标题
settextcolor(RGB(50, 50, 200));
settextstyle(24, 0, _T("宋体"));
outtextxy((WIDTH - textwidth(_T("修改用户信息"))) / 2, 30, _T("修改用户信息"));
// 显示当前信息
settextcolor(RGB(0, 0, 0));
settextstyle(16, 0, _T("宋体"));
outtextxy(MARGIN, 80, _T("当前用户信息:"));
outtextxy(MARGIN, 110, ("昵称: " + userToModify->nickname).c_str());
outtextxy(MARGIN, 140, ("账号: " + userToModify->account).c_str());
outtextxy(MARGIN, 170, ("密码: " + userToModify->password).c_str());
outtextxy(MARGIN, 200, ("通关数: " + to_string(userToModify->levelsCleared)).c_str());
// 输入框
int inputWidth = 300;
char buffer[32];
_itoa_s((WIDTH - inputWidth) / 2, buffer, 10);
int yPos = 250;
inputBoxes.clear();
inputBoxes.push_back(InputBox(buffer, yPos, _T("inputWidth"), _T("INPUT_HEIGHT"), "新昵称 (留空保持不变)")); yPos += 60;
inputBoxes.push_back(InputBox(buffer, yPos, _T("inputWidth"), _T("INPUT_HEIGHT"), "新密码 (留空保持不变)")); yPos += 60;
inputBoxes.push_back(InputBox(buffer, yPos, _T("inputWidth"), _T("INPUT_HEIGHT"), "新通关数 (留空保持不变)"));
// 保存用户账号
currentAccount = account;
// 按钮
int buttonWidth = 120;
yPos += 80;
buttons.push_back(Button((WIDTH - buttonWidth * 2 - 20) / 2, yPos, buttonWidth, BUTTON_HEIGHT, "确认修改"));
buttons.push_back(Button((WIDTH + buttonWidth * 2 + 20) / 2, yPos, buttonWidth, BUTTON_HEIGHT, "取消"));
}
// 处理删除用户界面
void processDeleteUser() {
cleardevice();
// 标题
settextcolor(RGB(50, 50, 200));
settextstyle(24, 0, _T("宋体"));
outtextxy((WIDTH - textwidth(_T("删除用户信息"))) / 2, 30, _T("删除用户信息"));
// 输入框 - 账号
int inputWidth = 300;
char buffer[32];
_itoa_s((WIDTH - inputWidth) / 2, buffer, 10);
inputBoxes.clear();
inputBoxes.push_back(InputBox(buffer, 100, "inputWidth", "INPUT_HEIGHT", "请输入要删除的用户账号"));
// 按钮
int buttonWidth = 120;
buttons.clear();
buttons.push_back(Button((WIDTH - buttonWidth) / 2, 180, buttonWidth, BUTTON_HEIGHT, "确认删除"));
buttons.push_back(Button((WIDTH - buttonWidth) / 2, 240, buttonWidth, BUTTON_HEIGHT, "返回主菜单"));
}
// 运行主循环
void run() {
ExMessage msg; // 消息结构
while (true) {
cleardevice();
// 根据当前状态绘制界面
if (isAddingUser) {
initAddUserUI();
}
else {
initMainMenuUI();
}
// 绘制所有按钮
for (auto& button : buttons) {
button.draw();
}
// 绘制所有输入框
for (auto& input : inputBoxes) {
input.draw();
}
// 处理消息
if (peekmessage(&msg, EM_MOUSE | EM_KEY)) {
// 鼠标消息
if (msg.message == WM_LBUTTONDOWN) {
// 处理按钮点击
bool buttonClicked = false;
for (auto& button : buttons) {
if (button.isMouseOver(msg.x, msg.y)) {
buttonClicked = true;
string text = button.getText();
if (text == "添加用户信息") {
isAddingUser = true;
initUI();
}
else if (text == "查看所有用户") {
drawUserList();
}
else if (text == "修改用户信息") {
processModifyUser();
}
else if (text == "删除用户信息") {
processDeleteUser();
}
else if (text == "退出系统") {
closegraph();
return;
}
else if (text == "确认添加") {
if (inputBoxes.size() >= 4) {
User newUser;
newUser.nickname = inputBoxes[0].getText();
newUser.account = inputBoxes[1].getText();
newUser.password = inputBoxes[2].getText();
string levelsText = inputBoxes[3].getText();
newUser.levelsCleared = levelsText.empty() ? 0 : stoi(levelsText);
// 保存到文件
ofstream file("users.txt", ios::app);
if (file.is_open()) {
file << newUser.nickname << "\t" << newUser.account << "\t"
<< newUser.password << "\t" << newUser.levelsCleared << endl;
file.close();
isAddingUser = false;
}
else {
settextcolor(RGB(200, 0, 0));
outtextxy(100, 300, _T("保存失败!"));
}
}
}
else if (text == "取消") {
isAddingUser = false;
initUI();
}
else if (text == "查找用户" && inputBoxes.size() > 0) {
string account = inputBoxes[0].getText();
if (!account.empty()) {
showModifyUserInterface(account);
}
}
else if (text == "确认修改" && !currentAccount.empty() && inputBoxes.size() >= 3) {
users = readUsers();
for (auto& user : users) {
if (user.account == currentAccount) {
string newNickname = inputBoxes[0].getText();
if (!newNickname.empty()) user.nickname = newNickname;
string newPassword = inputBoxes[1].getText();
if (!newPassword.empty()) user.password = newPassword;
string newLevels = inputBoxes[2].getText();
if (!newLevels.empty()) user.levelsCleared = stoi(newLevels);
break;
}
}
saveUsers(users);
currentAccount = "";
initMainMenuUI();
}
else if (text == "确认删除" && inputBoxes.size() > 0) {
string account = inputBoxes[0].getText();
if (!account.empty()) {
users = readUsers();
vector<User> newUsers;
bool found = false;
for (const auto& user : users) {
if (user.account == account) {
found = true;
}
else {
newUsers.push_back(user);
}
}
if (found) {
saveUsers(newUsers);
}
else {
settextcolor(RGB(200, 0, 0));
outtextxy(100, 300, _T("未找到该用户!"));
}
initMainMenuUI();
}
}
else if (text == "返回主菜单") {
initMainMenuUI();
}
break;
}
}
// 处理输入框焦点
if (!buttonClicked) {
for (auto& input : inputBoxes) {
input.setFocus(input.isMouseOver(msg.x, msg.y));
}
}
}
// 键盘消息
else if (msg.message == WM_KEYDOWN) {
for (auto& input : inputBoxes) {
input.handleKey(msg.vkcode);
}
}
}
FlushBatchDraw(); // 批量绘制,提高性能
Sleep(10); // 短暂休眠,降低CPU占用
}
}
};
int main() {
MainWindow window;
window.run();
return 0;
}为什么在vector<InputBox> inputBoxes;中显示函数 "InputBox" 不是类型名,InputBox明明声明定义在MainWindow前
最新发布