#include #include #include #include #include #include #include #include #include #include using namespace std; // 全局常量定义 #define WIN_WIDTH 800 #define WIN_HEIGHT 600 #define FONT_SIZE 16 #define COLOR_BG RGB(245, 245, 245) // 背景色 #define COLOR_MENU RGB(60, 179, 113) // 菜单底色 #define COLOR_TEXT RGB(255, 255, 255) // 文字白色 #define COLOR_BLACK RGB(0, 0, 0) // 黑色 #define COLOR_RED RGB(255, 0, 0) // 红色 #define COLOR_BLUE RGB(0, 0, 255) // 蓝色 // 输入焦点枚举(统一管理所有输入框焦点) enum InputFocusType { FOCUS_NONE, // 无焦点 FOCUS_LOGIN_PWD, // 登录密码框 FOCUS_COURSE_NUM, // 课程编号(添加/修改) FOCUS_COURSE_NAME, // 课程名称 FOCUS_COURSE_CREDIT,// 课程学分 FOCUS_COURSE_TEACHER,// 授课教师 FOCUS_DEL_COURSE_NUM,// 删除课程编号 FOCUS_EDIT_COURSE_NUM,// 修改课程-查询编号 FOCUS_STU_NUM, // 学生学号 FOCUS_STU_NAME, // 学生姓名 FOCUS_STU_SEX, // 学生性别 FOCUS_STU_GRADE, // 学生年级 FOCUS_STU_SELECT_STU_NUM,// 选课-学生学号 FOCUS_STU_SELECT_COURSE_NUM,// 选课-课程编号 FOCUS_CHANGE_PWD1, // 修改密码-新密码 FOCUS_CHANGE_PWD2 // 修改密码-确认密码 }; // 全局变量 string adminPwd = "1234"; // 管理员密码 bool isLogin = false; // 登录状态 string inputBuffer = ""; // 通用输入缓冲区 string tempStr1 = ""; // 临时输入1(课程名称/学生姓名等) string tempStr2 = ""; // 临时输入2(学分/性别等) string tempStr3 = ""; // 临时输入3(教师/年级等) int currentMenu = 0; // 当前菜单:0-登录 1-主菜单 2-课程管理 3-学生管理 InputFocusType currentFocus = FOCUS_NONE; // 当前输入焦点 DWORD lastCursorTime = 0; // 光标闪烁计时 bool showCursor = true; // 光标显示状态 // 键盘输入防抖标记 bool keyBackPressed = false; bool keyEnterPressed = false; bool charKeysPressed[95] = { false }; // 32-126可打印字符防抖 // 信息基类 class info { protected: long number; // 编号 string name; // 名称 public: info() {} info(long num, string name) : number(num), name(name) {} long getNumber() { return number; } string getName() { return name; } void setName(string n) { name = n; } }; // 课程类 class course : public info { private: int credit; // 学分 string teachername; // 授课教师 public: course() {} course(long num, string name, int cre, string tea) : info(num, name) { credit = cre; teachername = tea; } int getCredit() { return credit; } string getTeacher() { return teachername; } void setCredit(int c) { credit = c; } void setTeacher(string t) { teachername = t; } // 静态方法声明 static void addCourse(long num, string name, int cre, string tea); static void delCourse(long num); static void editCourse(long num, string name, int cre, string tea); static bool isHave(long num); static course* getCourse(long num); static vector& getCourseList(); }; // 学生类 class student : public info { private: string sex; // 性别 string grade; // 年级 long scredit; // 总学分 vector havec;// 已选课程 public: student() {} student(long num, string name, string se, string gra, long scr = 0) : info(num, name) { sex = se; grade = gra; scredit = scr; } string getSex() { return sex; } string getGrade() { return grade; } long getSCredit() { return scredit; } vector& getHaveC() { return havec; } void setSex(string s) { sex = s; } void setGrade(string g) { grade = g; } void setSCredit(long sc) { scredit = sc; } // 静态方法声明 static void addStudent(long num, string name, string se, string gra); static void delStudent(long num); static void editStudent(long num, string name, string se, string gra); static bool isHave(long num); static student* getStudent(long num); static vector& getStudentList(); static void addCourseToStudent(long stuNum, long courseNum); static void delCourseFromStudent(long stuNum, long courseNum); }; // 全局容器 vector courseList; vector studentList; // 课程类静态方法实现 vector& course::getCourseList() { return courseList; } void course::addCourse(long num, string name, int cre, string tea) { courseList.push_back(course(num, name, cre, tea)); } void course::delCourse(long num) { for (auto it = courseList.begin(); it != courseList.end(); it++) { if (it->getNumber() == num) { courseList.erase(it); break; } } } void course::editCourse(long num, string name, int cre, string tea) { for (auto& c : courseList) { if (c.getNumber() == num) { if (!name.empty()) c.setName(name); if (cre > 0) c.setCredit(cre); if (!tea.empty()) c.setTeacher(tea); break; } } } bool course::isHave(long num) { for (auto& c : courseList) { if (c.getNumber() == num) return true; } return false; } course* course::getCourse(long num) { for (auto& c : courseList) { if (c.getNumber() == num) return &c; } return nullptr; } // 学生类静态方法实现 vector& student::getStudentList() { return studentList; } void student::addStudent(long num, string name, string se, string gra) { studentList.push_back(student(num, name, se, gra)); } void student::delStudent(long num) { for (auto it = studentList.begin(); it != studentList.end(); it++) { if (it->getNumber() == num) { studentList.erase(it); break; } } } void student::editStudent(long num, string name, string se, string gra) { for (auto& s : studentList) { if (s.getNumber() == num) { if (!name.empty()) s.setName(name); if (!se.empty()) s.setSex(se); if (!gra.empty()) s.setGrade(gra); break; } } } bool student::isHave(long num) { for (auto& s : studentList) { if (s.getNumber() == num) return true; } return false; } student* student::getStudent(long num) { for (auto& s : studentList) { if (s.getNumber() == num) return &s; } return nullptr; } void student::addCourseToStudent(long stuNum, long courseNum) { student* stu = getStudent(stuNum); course* crs = course::getCourse(courseNum); if (stu && crs) { // 检查是否已选 for (auto& c : stu->getHaveC()) { if (c.getNumber() == courseNum) return; } stu->getHaveC().push_back(*crs); } } void student::delCourseFromStudent(long stuNum, long courseNum) { student* stu = getStudent(stuNum); if (stu) { for (auto it = stu->getHaveC().begin(); it != stu->getHaveC().end(); it++) { if (it->getNumber() == courseNum) { stu->getHaveC().erase(it); break; } } } } // 工具函数:绘制按钮 void drawButton(int x, int y, int w, int h, const TCHAR* text, COLORREF bgColor, COLORREF textColor) { setfillcolor(bgColor); solidroundrect(x, y, x + w, y + h, 10, 10); settextcolor(textColor); setbkmode(TRANSPARENT); settextstyle(FONT_SIZE, 0, _T("微软雅黑")); outtextxy(x + w / 2 - textwidth(text) / 2, y + h / 2 - textheight(text) / 2, text); } // 工具函数:检查鼠标是否点击按钮/输入框 bool isClickArea(int x, int y, int w, int h, int mouseX, int mouseY) { return (mouseX >= x && mouseX <= x + w && mouseY >= y && mouseY <= y + h); } // 工具函数:数字转字符串 string num2str(long num) { stringstream ss; ss << num; return ss.str(); } // 工具函数:字符串转数字 long str2num(string str) { if (str.empty()) return 0; long num; stringstream ss(str); ss >> num; return num; } // 工具函数:更新光标闪烁状态 void updateCursor() { DWORD currentTime = GetTickCount(); if (currentTime - lastCursorTime > 500) { // 500ms闪烁一次 showCursor = !showCursor; lastCursorTime = currentTime; } } // 工具函数:绘制输入框(带焦点和光标) void drawInputBox(int x, int y, int w, int h, const TCHAR* hint, string& inputStr, bool isFocused, bool isPassword = false) { // 绘制输入框边框 setlinecolor(COLOR_BLACK); rectangle(x, y, x + w, y + h); // 绘制提示文字/输入内容 settextcolor(isFocused ? COLOR_BLACK : RGB(160, 160, 160)); settextstyle(FONT_SIZE, 0, _T("微软雅黑")); TCHAR showBuf[256] = { 0 }; if (inputStr.empty()) { outtextxy(x + 10, y + h / 2 - textheight(hint) / 2, hint); } else { if (isPassword) { // 密码框显示星号 string pwdStars(inputStr.length(), '*'); MultiByteToWideChar(CP_ACP, 0, pwdStars.c_str(), -1, showBuf, 256); } else { MultiByteToWideChar(CP_ACP, 0, inputStr.c_str(), -1, showBuf, 256); } outtextxy(x + 10, y + h / 2 - textheight(showBuf) / 2, showBuf); } // 绘制闪烁光标(仅焦点时) if (isFocused && showCursor) { int cursorX = x + 10 + (inputStr.empty() ? textwidth(hint) : textwidth(showBuf)) + 2; line(cursorX, y + 5, cursorX, y + h - 5); } } // 工具函数:重置所有键盘防抖标记 void resetKeyFlags() { keyBackPressed = false; keyEnterPressed = false; memset(charKeysPressed, 0, sizeof(charKeysPressed)); } // 工具函数:统一处理键盘输入(适配所有输入框) void handleKeyboardInput() { // 退格键(所有焦点通用)- 防抖处理 if ((GetAsyncKeyState(VK_BACK) & 0x8000) && !keyBackPressed) { keyBackPressed = true; switch (currentFocus) { case FOCUS_LOGIN_PWD: if (!inputBuffer.empty()) inputBuffer.pop_back(); break; case FOCUS_COURSE_NUM: if (!inputBuffer.empty()) inputBuffer.pop_back(); break; case FOCUS_COURSE_NAME: if (!tempStr1.empty()) tempStr1.pop_back(); break; case FOCUS_COURSE_CREDIT: if (!tempStr2.empty()) tempStr2.pop_back(); break; case FOCUS_COURSE_TEACHER: if (!tempStr3.empty()) tempStr3.pop_back(); break; case FOCUS_DEL_COURSE_NUM: if (!inputBuffer.empty()) inputBuffer.pop_back(); break; case FOCUS_EDIT_COURSE_NUM: if (!inputBuffer.empty()) inputBuffer.pop_back(); break; case FOCUS_STU_NUM: if (!inputBuffer.empty()) inputBuffer.pop_back(); break; case FOCUS_STU_NAME: if (!tempStr1.empty()) tempStr1.pop_back(); break; case FOCUS_STU_SEX: if (!tempStr2.empty()) tempStr2.pop_back(); break; case FOCUS_STU_GRADE: if (!tempStr3.empty()) tempStr3.pop_back(); break; case FOCUS_STU_SELECT_STU_NUM: if (!inputBuffer.empty()) inputBuffer.pop_back(); break; case FOCUS_STU_SELECT_COURSE_NUM: if (!tempStr1.empty()) tempStr1.pop_back(); break; case FOCUS_CHANGE_PWD1: if (!inputBuffer.empty()) inputBuffer.pop_back(); break; case FOCUS_CHANGE_PWD2: if (!tempStr1.empty()) tempStr1.pop_back(); break; default: break; } } else if (!(GetAsyncKeyState(VK_BACK) & 0x8000)) { keyBackPressed = false; } // 仅处理可打印字符(32-126)- 防抖处理 for (int i = 0; i < 95; i++) { char c = 32 + i; if ((GetAsyncKeyState(c) & 0x8000) && !charKeysPressed[i]) { charKeysPressed[i] = true; // 根据焦点过滤字符类型 switch (currentFocus) { // 仅允许数字 case FOCUS_COURSE_NUM: case FOCUS_DEL_COURSE_NUM: case FOCUS_EDIT_COURSE_NUM: case FOCUS_STU_NUM: case FOCUS_STU_SELECT_STU_NUM: case FOCUS_STU_SELECT_COURSE_NUM: case FOCUS_COURSE_CREDIT: if (c >= '0' && c <= '9') { if (currentFocus == FOCUS_COURSE_CREDIT) tempStr2 += c; else inputBuffer += c; } break; // 允许所有字符(密码框/名称/性别等) case FOCUS_LOGIN_PWD: inputBuffer += c; break; case FOCUS_COURSE_NAME: tempStr1 += c; break; case FOCUS_COURSE_TEACHER: tempStr3 += c; break; case FOCUS_STU_NAME: tempStr1 += c; break; case FOCUS_STU_SEX: tempStr2 += c; break; case FOCUS_STU_GRADE: tempStr3 += c; break; case FOCUS_CHANGE_PWD1: inputBuffer += c; break; case FOCUS_CHANGE_PWD2: tempStr1 += c; break; default: break; } break; } else if (!(GetAsyncKeyState(c) & 0x8000)) { charKeysPressed[i] = false; } } } // 登录界面 void drawLogin() { BeginBatchDraw(); cleardevice(); setbkcolor(COLOR_BG); // 绘制标题 settextcolor(COLOR_MENU); settextstyle(30, 0, _T("微软雅黑")); const TCHAR* title = _T("学生选课管理系统-管理员端"); outtextxy(WIN_WIDTH / 2 - textwidth(title) / 2, 100, title); // 绘制密码输入框 int inputX = WIN_WIDTH / 2 - 150; int inputY = 200; int inputW = 300; int inputH = 40; drawInputBox(inputX, inputY, inputW, inputH, _T("请输入管理员密码"), inputBuffer, currentFocus == FOCUS_LOGIN_PWD, true); // 绘制登录按钮 drawButton(WIN_WIDTH / 2 - 80, 280, 160, 40, _T("登录"), COLOR_MENU, COLOR_TEXT); // 处理鼠标事件 if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (msg.uMsg == WM_LBUTTONDOWN) { resetKeyFlags(); if (isClickArea(WIN_WIDTH / 2 - 80, 280, 160, 40, msg.x, msg.y)) { if (inputBuffer == adminPwd) { isLogin = true; currentMenu = 1; inputBuffer = ""; currentFocus = FOCUS_NONE; } else { settextcolor(COLOR_RED); const TCHAR* err = _T("密码错误!请输入1234"); outtextxy(WIN_WIDTH / 2 - textwidth(err) / 2, 350, err); inputBuffer = ""; } Sleep(200); } else if (isClickArea(inputX, inputY, inputW, inputH, msg.x, msg.y)) { currentFocus = FOCUS_LOGIN_PWD; lastCursorTime = GetTickCount(); } else { currentFocus = FOCUS_NONE; } } } // 处理键盘输入 if (currentFocus == FOCUS_LOGIN_PWD) { handleKeyboardInput(); if ((GetAsyncKeyState(VK_RETURN) & 0x8000) && !keyEnterPressed) { keyEnterPressed = true; if (inputBuffer == adminPwd) { isLogin = true; currentMenu = 1; inputBuffer = ""; currentFocus = FOCUS_NONE; } else { settextcolor(COLOR_RED); const TCHAR* err = _T("密码错误!请输入1234"); outtextxy(WIN_WIDTH / 2 - textwidth(err) / 2, 350, err); inputBuffer = ""; } Sleep(200); } else if (!(GetAsyncKeyState(VK_RETURN) & 0x8000)) { keyEnterPressed = false; } } FlushBatchDraw(); EndBatchDraw(); Sleep(10); } // 主菜单 void drawMainMenu() { BeginBatchDraw(); cleardevice(); setbkcolor(COLOR_BG); // 标题 settextcolor(COLOR_MENU); settextstyle(30, 0, _T("微软雅黑")); const TCHAR* title = _T("主菜单"); outtextxy(WIN_WIDTH / 2 - textwidth(title) / 2, 50, title); // 功能按钮 drawButton(WIN_WIDTH / 2 - 100, 150, 200, 50, _T("课程信息管理"), COLOR_MENU, COLOR_TEXT); drawButton(WIN_WIDTH / 2 - 100, 230, 200, 50, _T("学生信息管理"), COLOR_MENU, COLOR_TEXT); drawButton(WIN_WIDTH / 2 - 100, 310, 200, 50, _T("修改密码"), COLOR_MENU, COLOR_TEXT); drawButton(WIN_WIDTH / 2 - 100, 390, 200, 50, _T("退出系统"), COLOR_MENU, COLOR_TEXT); // 处理鼠标事件 if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (msg.uMsg == WM_LBUTTONDOWN) { resetKeyFlags(); currentFocus = FOCUS_NONE; if (isClickArea(WIN_WIDTH / 2 - 100, 150, 200, 50, msg.x, msg.y)) { currentMenu = 2; inputBuffer = tempStr1 = tempStr2 = tempStr3 = ""; } else if (isClickArea(WIN_WIDTH / 2 - 100, 230, 200, 50, msg.x, msg.y)) { currentMenu = 3; inputBuffer = tempStr1 = tempStr2 = tempStr3 = ""; } else if (isClickArea(WIN_WIDTH / 2 - 100, 310, 200, 50, msg.x, msg.y)) { // 修改密码逻辑 inputBuffer = tempStr1 = ""; bool waitInput = true; while (waitInput) { BeginBatchDraw(); cleardevice(); settextcolor(COLOR_BLACK); int pwd1X = 100, pwd1Y = 130; int pwd2X = 100, pwd2Y = 220; int pwdW = 200, pwdH = 40; outtextxy(100, 100, _T("请输入新密码:")); drawInputBox(pwd1X, pwd1Y, pwdW, pwdH, _T("新密码"), inputBuffer, currentFocus == FOCUS_CHANGE_PWD1, true); outtextxy(100, 190, _T("请确认新密码:")); drawInputBox(pwd2X, pwd2Y, pwdW, pwdH, _T("确认密码"), tempStr1, currentFocus == FOCUS_CHANGE_PWD2, true); drawButton(100, 280, 100, 40, _T("确认"), COLOR_MENU, COLOR_TEXT); drawButton(220, 280, 100, 40, _T("取消"), RGB(200, 200, 200), COLOR_BLACK); FlushBatchDraw(); EndBatchDraw(); if (MouseHit()) { MOUSEMSG msg2 = GetMouseMsg(); if (msg2.uMsg == WM_LBUTTONDOWN) { resetKeyFlags(); if (isClickArea(pwd1X, pwd1Y, pwdW, pwdH, msg2.x, msg2.y)) { currentFocus = FOCUS_CHANGE_PWD1; lastCursorTime = GetTickCount(); } else if (isClickArea(pwd2X, pwd2Y, pwdW, pwdH, msg2.x, msg2.y)) { currentFocus = FOCUS_CHANGE_PWD2; lastCursorTime = GetTickCount(); } else if (isClickArea(100, 280, 100, 40, msg2.x, msg2.y)) { if (inputBuffer == tempStr1 && !inputBuffer.empty()) { adminPwd = inputBuffer; cleardevice(); outtextxy(100, 350, _T("密码修改成功!")); FlushBatchDraw(); } else { cleardevice(); outtextxy(100, 350, _T("两次密码不一致!")); FlushBatchDraw(); } Sleep(1000); waitInput = false; currentMenu = 1; currentFocus = FOCUS_NONE; } else if (isClickArea(220, 280, 100, 40, msg2.x, msg2.y)) { waitInput = false; currentMenu = 1; currentFocus = FOCUS_NONE; } } } handleKeyboardInput(); updateCursor(); Sleep(10); } } else if (isClickArea(WIN_WIDTH / 2 - 100, 390, 200, 50, msg.x, msg.y)) { closegraph(); exit(0); } } } FlushBatchDraw(); EndBatchDraw(); Sleep(10); } // 课程管理界面(核心修复:查看课程、修改课程功能) void drawCourseMenu() { BeginBatchDraw(); cleardevice(); setbkcolor(COLOR_BG); // 标题与返回按钮 settextcolor(COLOR_MENU); settextstyle(30, 0, _T("微软雅黑")); const TCHAR* title = _T("课程信息管理"); outtextxy(WIN_WIDTH / 2 - textwidth(title) / 2, 30, title); drawButton(20, 20, 80, 30, _T("返回"), RGB(200, 200, 200), COLOR_BLACK); // 功能按钮 drawButton(50, 100, 120, 40, _T("添加课程"), COLOR_MENU, COLOR_TEXT); drawButton(200, 100, 120, 40, _T("删除课程"), COLOR_MENU, COLOR_TEXT); drawButton(350, 100, 120, 40, _T("修改课程"), COLOR_MENU, COLOR_TEXT); drawButton(500, 100, 120, 40, _T("查看所有课程"), COLOR_MENU, COLOR_TEXT); // 处理鼠标事件 if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (msg.uMsg == WM_LBUTTONDOWN) { resetKeyFlags(); currentFocus = FOCUS_NONE; if (isClickArea(20, 20, 80, 30, msg.x, msg.y)) { currentMenu = 1; inputBuffer = tempStr1 = tempStr2 = tempStr3 = ""; return; } // 添加课程 else if (isClickArea(50, 100, 120, 40, msg.x, msg.y)) { inputBuffer = tempStr1 = tempStr2 = tempStr3 = ""; bool waitInput = true; while (waitInput) { BeginBatchDraw(); cleardevice(); settextcolor(COLOR_BLACK); int numX = 150, numY = 95; int nameX = 150, nameY = 155; int creditX = 150, creditY = 215; int teacherX = 150, teacherY = 275; int inputW = 200, inputH = 40; outtextxy(50, 50, _T("添加课程")); outtextxy(50, 100, _T("课程编号:")); drawInputBox(numX, numY, inputW, inputH, _T("数字编号"), inputBuffer, currentFocus == FOCUS_COURSE_NUM); outtextxy(50, 160, _T("课程名称:")); drawInputBox(nameX, nameY, inputW, inputH, _T("如:数据结构"), tempStr1, currentFocus == FOCUS_COURSE_NAME); outtextxy(50, 220, _T("课程学分:")); drawInputBox(creditX, creditY, inputW, inputH, _T("数字"), tempStr2, currentFocus == FOCUS_COURSE_CREDIT); outtextxy(50, 280, _T("授课教师:")); drawInputBox(teacherX, teacherY, inputW, inputH, _T("教师姓名"), tempStr3, currentFocus == FOCUS_COURSE_TEACHER); drawButton(150, 350, 100, 40, _T("确认添加"), COLOR_MENU, COLOR_TEXT); drawButton(270, 350, 100, 40, _T("取消"), RGB(200, 200, 200), COLOR_BLACK); FlushBatchDraw(); EndBatchDraw(); if (MouseHit()) { MOUSEMSG msg2 = GetMouseMsg(); if (msg2.uMsg == WM_LBUTTONDOWN) { resetKeyFlags(); if (isClickArea(numX, numY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_COURSE_NUM; lastCursorTime = GetTickCount(); } else if (isClickArea(nameX, nameY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_COURSE_NAME; lastCursorTime = GetTickCount(); } else if (isClickArea(creditX, creditY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_COURSE_CREDIT; lastCursorTime = GetTickCount(); } else if (isClickArea(teacherX, teacherY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_COURSE_TEACHER; lastCursorTime = GetTickCount(); } else if (isClickArea(150, 350, 100, 40, msg2.x, msg2.y)) { long num = str2num(inputBuffer); int credit = str2num(tempStr2); if (!course::isHave(num) && !inputBuffer.empty() && !tempStr1.empty()) { course::addCourse(num, tempStr1, credit, tempStr3); cleardevice(); outtextxy(50, 420, _T("课程添加成功!")); } else { cleardevice(); outtextxy(50, 420, _T("编号重复或信息为空!")); } FlushBatchDraw(); Sleep(1000); waitInput = false; currentMenu = 2; currentFocus = FOCUS_NONE; } else if (isClickArea(270, 350, 100, 40, msg2.x, msg2.y)) { waitInput = false; currentMenu = 2; currentFocus = FOCUS_NONE; } } } handleKeyboardInput(); updateCursor(); Sleep(10); } } // 删除课程 else if (isClickArea(200, 100, 120, 40, msg.x, msg.y)) { inputBuffer = ""; bool waitInput = true; while (waitInput) { BeginBatchDraw(); cleardevice(); settextcolor(COLOR_BLACK); int numX = 150, numY = 95; int inputW = 200, inputH = 40; outtextxy(50, 50, _T("删除课程")); outtextxy(50, 100, _T("课程编号:")); drawInputBox(numX, numY, inputW, inputH, _T("输入要删除的编号"), inputBuffer, currentFocus == FOCUS_DEL_COURSE_NUM); drawButton(150, 180, 100, 40, _T("确认删除"), COLOR_MENU, COLOR_TEXT); drawButton(270, 180, 100, 40, _T("取消"), RGB(200, 200, 200), COLOR_BLACK); FlushBatchDraw(); EndBatchDraw(); if (MouseHit()) { MOUSEMSG msg2 = GetMouseMsg(); if (msg2.uMsg == WM_LBUTTONDOWN) { resetKeyFlags(); if (isClickArea(numX, numY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_DEL_COURSE_NUM; lastCursorTime = GetTickCount(); } else if (isClickArea(150, 180, 100, 40, msg2.x, msg2.y)) { long num = str2num(inputBuffer); if (course::isHave(num)) { course::delCourse(num); cleardevice(); outtextxy(50, 250, _T("课程删除成功!")); } else { cleardevice(); outtextxy(50, 250, _T("课程不存在!")); } FlushBatchDraw(); Sleep(1000); waitInput = false; currentMenu = 2; currentFocus = FOCUS_NONE; } else if (isClickArea(270, 180, 100, 40, msg2.x, msg2.y)) { waitInput = false; currentMenu = 2; currentFocus = FOCUS_NONE; } } } handleKeyboardInput(); updateCursor(); Sleep(10); } } // 修改课程(新增完整逻辑) else if (isClickArea(350, 100, 120, 40, msg.x, msg.y)) { inputBuffer = tempStr1 = tempStr2 = tempStr3 = ""; bool waitInput = true; bool isEditMode = false; // 是否进入编辑模式 course* targetCourse = nullptr; while (waitInput) { BeginBatchDraw(); cleardevice(); settextcolor(COLOR_BLACK); if (!isEditMode) { // 第一步:输入要修改的课程编号 int numX = 150, numY = 95; int inputW = 200, inputH = 40; outtextxy(50, 50, _T("修改课程-查询")); outtextxy(50, 100, _T("课程编号:")); drawInputBox(numX, numY, inputW, inputH, _T("输入要修改的编号"), inputBuffer, currentFocus == FOCUS_EDIT_COURSE_NUM); drawButton(150, 180, 100, 40, _T("查询"), COLOR_MENU, COLOR_TEXT); drawButton(270, 180, 100, 40, _T("取消"), RGB(200, 200, 200), COLOR_BLACK); // 显示提示 if (!inputBuffer.empty() && !course::isHave(str2num(inputBuffer))) { settextcolor(COLOR_RED); outtextxy(150, 240, _T("课程编号不存在!")); } } else { // 第二步:编辑课程信息(回显原有数据) int numX = 150, numY = 95; int nameX = 150, nameY = 155; int creditX = 150, creditY = 215; int teacherX = 150, teacherY = 275; int inputW = 200, inputH = 40; outtextxy(50, 50, _T("修改课程-编辑")); outtextxy(50, 100, _T("课程编号:")); // 编号不可修改,仅显示 TCHAR numBuf[32] = { 0 }; MultiByteToWideChar(CP_ACP, 0, num2str(targetCourse->getNumber()).c_str(), -1, numBuf, 32); rectangle(numX, numY, numX + inputW, numY + inputH); outtextxy(numX + 10, numY + inputH / 2 - textheight(numBuf) / 2, numBuf); outtextxy(50, 160, _T("课程名称:")); // 回显原有名称 if (tempStr1.empty()) tempStr1 = targetCourse->getName(); drawInputBox(nameX, nameY, inputW, inputH, _T("如:数据结构"), tempStr1, currentFocus == FOCUS_COURSE_NAME); outtextxy(50, 220, _T("课程学分:")); // 回显原有学分 if (tempStr2.empty()) tempStr2 = num2str(targetCourse->getCredit()); drawInputBox(creditX, creditY, inputW, inputH, _T("数字"), tempStr2, currentFocus == FOCUS_COURSE_CREDIT); outtextxy(50, 280, _T("授课教师:")); // 回显原有教师 if (tempStr3.empty()) tempStr3 = targetCourse->getTeacher(); drawInputBox(teacherX, teacherY, inputW, inputH, _T("教师姓名"), tempStr3, currentFocus == FOCUS_COURSE_TEACHER); drawButton(150, 350, 100, 40, _T("确认修改"), COLOR_MENU, COLOR_TEXT); drawButton(270, 350, 100, 40, _T("取消"), RGB(200, 200, 200), COLOR_BLACK); } FlushBatchDraw(); EndBatchDraw(); if (MouseHit()) { MOUSEMSG msg2 = GetMouseMsg(); if (msg2.uMsg == WM_LBUTTONDOWN) { resetKeyFlags(); if (!isEditMode) { // 查询阶段 int numX = 150, numY = 95, inputW = 200, inputH = 40; if (isClickArea(numX, numY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_EDIT_COURSE_NUM; lastCursorTime = GetTickCount(); } else if (isClickArea(150, 180, 100, 40, msg2.x, msg2.y)) { long num = str2num(inputBuffer); if (course::isHave(num)) { targetCourse = course::getCourse(num); isEditMode = true; currentFocus = FOCUS_NONE; } } else if (isClickArea(270, 180, 100, 40, msg2.x, msg2.y)) { waitInput = false; currentMenu = 2; currentFocus = FOCUS_NONE; } } else { // 编辑阶段 int nameX = 150, nameY = 155; int creditX = 150, creditY = 215; int teacherX = 150, teacherY = 275; int inputW = 200, inputH = 40; if (isClickArea(nameX, nameY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_COURSE_NAME; lastCursorTime = GetTickCount(); } else if (isClickArea(creditX, creditY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_COURSE_CREDIT; lastCursorTime = GetTickCount(); } else if (isClickArea(teacherX, teacherY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_COURSE_TEACHER; lastCursorTime = GetTickCount(); } else if (isClickArea(150, 350, 100, 40, msg2.x, msg2.y)) { // 确认修改 int credit = str2num(tempStr2); course::editCourse(targetCourse->getNumber(), tempStr1, credit, tempStr3); cleardevice(); outtextxy(50, 420, _T("课程修改成功!")); FlushBatchDraw(); Sleep(1000); waitInput = false; currentMenu = 2; currentFocus = FOCUS_NONE; } else if (isClickArea(270, 350, 100, 40, msg2.x, msg2.y)) { waitInput = false; currentMenu = 2; currentFocus = FOCUS_NONE; } } } } handleKeyboardInput(); updateCursor(); Sleep(10); } } // 查看所有课程(核心修复:持续监听返回事件) else if (isClickArea(500, 100, 120, 40, msg.x, msg.y)) { bool showList = true; while (showList) { BeginBatchDraw(); cleardevice(); settextcolor(COLOR_BLACK); outtextxy(50, 50, _T("所有课程信息")); // 绘制表头 int y = 100; settextstyle(16, 0, _T("微软雅黑")); outtextxy(50, y, _T("编号")); outtextxy(150, y, _T("名称")); outtextxy(280, y, _T("学分")); outtextxy(350, y, _T("授课教师")); y += 30; // 绘制课程列表 settextstyle(14, 0, _T("微软雅黑")); if (courseList.empty()) { outtextxy(50, y, _T("暂无课程数据!")); } else { for (auto& c : course::getCourseList()) { if (y > WIN_HEIGHT - 80) break; // 防止超出界面 TCHAR numBuf[32] = { 0 }; MultiByteToWideChar(CP_ACP, 0, num2str(c.getNumber()).c_str(), -1, numBuf, 32); outtextxy(50, y, numBuf); TCHAR nameBuf[64] = { 0 }; MultiByteToWideChar(CP_ACP, 0, c.getName().c_str(), -1, nameBuf, 64); outtextxy(150, y, nameBuf); TCHAR creditBuf[32] = { 0 }; MultiByteToWideChar(CP_ACP, 0, num2str(c.getCredit()).c_str(), -1, creditBuf, 32); outtextxy(280, y, creditBuf); TCHAR teacherBuf[64] = { 0 }; MultiByteToWideChar(CP_ACP, 0, c.getTeacher().c_str(), -1, teacherBuf, 64); outtextxy(350, y, teacherBuf); y += 25; } } // 绘制返回按钮(固定在底部) drawButton(50, WIN_HEIGHT - 60, 80, 30, _T("返回"), RGB(200, 200, 200), COLOR_BLACK); FlushBatchDraw(); EndBatchDraw(); // 持续监听返回按钮点击 if (MouseHit()) { MOUSEMSG msg2 = GetMouseMsg(); if (msg2.uMsg == WM_LBUTTONDOWN && isClickArea(50, WIN_HEIGHT - 60, 80, 30, msg2.x, msg2.y)) { showList = false; currentMenu = 2; currentFocus = FOCUS_NONE; } } Sleep(10); // 降低CPU占用 } } } } FlushBatchDraw(); EndBatchDraw(); Sleep(10); } // 学生管理界面(核心修复:查看所有学生) void drawStudentMenu() { BeginBatchDraw(); cleardevice(); setbkcolor(COLOR_BG); // 标题与返回按钮 settextcolor(COLOR_MENU); settextstyle(30, 0, _T("微软雅黑")); const TCHAR* title = _T("学生信息管理"); outtextxy(WIN_WIDTH / 2 - textwidth(title) / 2, 30, title); drawButton(20, 20, 80, 30, _T("返回"), RGB(200, 200, 200), COLOR_BLACK); // 功能按钮 drawButton(50, 100, 120, 40, _T("添加学生"), COLOR_MENU, COLOR_TEXT); drawButton(200, 100, 120, 40, _T("删除学生"), COLOR_MENU, COLOR_TEXT); drawButton(350, 100, 120, 40, _T("学生选课"), COLOR_MENU, COLOR_TEXT); drawButton(500, 100, 120, 40, _T("查看所有学生"), COLOR_MENU, COLOR_TEXT); // 处理鼠标事件 if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (msg.uMsg == WM_LBUTTONDOWN) { resetKeyFlags(); currentFocus = FOCUS_NONE; if (isClickArea(20, 20, 80, 30, msg.x, msg.y)) { currentMenu = 1; inputBuffer = tempStr1 = tempStr2 = tempStr3 = ""; return; } // 添加学生 else if (isClickArea(50, 100, 120, 40, msg.x, msg.y)) { inputBuffer = tempStr1 = tempStr2 = tempStr3 = ""; bool waitInput = true; while (waitInput) { BeginBatchDraw(); cleardevice(); settextcolor(COLOR_BLACK); int numX = 150, numY = 95; int nameX = 150, nameY = 155; int sexX = 150, sexY = 215; int gradeX = 150, gradeY = 275; int inputW = 200, inputH = 40; outtextxy(50, 50, _T("添加学生")); outtextxy(50, 100, _T("学生学号:")); drawInputBox(numX, numY, inputW, inputH, _T("数字学号"), inputBuffer, currentFocus == FOCUS_STU_NUM); outtextxy(50, 160, _T("学生姓名:")); drawInputBox(nameX, nameY, inputW, inputH, _T("姓名"), tempStr1, currentFocus == FOCUS_STU_NAME); outtextxy(50, 220, _T("学生性别:")); drawInputBox(sexX, sexY, inputW, inputH, _T("男/女"), tempStr2, currentFocus == FOCUS_STU_SEX); outtextxy(50, 280, _T("学生年级:")); drawInputBox(gradeX, gradeY, inputW, inputH, _T("如:2023级"), tempStr3, currentFocus == FOCUS_STU_GRADE); drawButton(150, 350, 100, 40, _T("确认添加"), COLOR_MENU, COLOR_TEXT); drawButton(270, 350, 100, 40, _T("取消"), RGB(200, 200, 200), COLOR_BLACK); FlushBatchDraw(); EndBatchDraw(); if (MouseHit()) { MOUSEMSG msg2 = GetMouseMsg(); if (msg2.uMsg == WM_LBUTTONDOWN) { resetKeyFlags(); if (isClickArea(numX, numY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_STU_NUM; lastCursorTime = GetTickCount(); } else if (isClickArea(nameX, nameY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_STU_NAME; lastCursorTime = GetTickCount(); } else if (isClickArea(sexX, sexY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_STU_SEX; lastCursorTime = GetTickCount(); } else if (isClickArea(gradeX, gradeY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_STU_GRADE; lastCursorTime = GetTickCount(); } else if (isClickArea(150, 350, 100, 40, msg2.x, msg2.y)) { long num = str2num(inputBuffer); if (!student::isHave(num) && !inputBuffer.empty() && !tempStr1.empty()) { student::addStudent(num, tempStr1, tempStr2, tempStr3); cleardevice(); outtextxy(50, 420, _T("学生添加成功!")); } else { cleardevice(); outtextxy(50, 420, _T("学号重复或信息为空!")); } FlushBatchDraw(); Sleep(1000); waitInput = false; currentMenu = 3; currentFocus = FOCUS_NONE; } else if (isClickArea(270, 350, 100, 40, msg2.x, msg2.y)) { waitInput = false; currentMenu = 3; currentFocus = FOCUS_NONE; } } } handleKeyboardInput(); updateCursor(); Sleep(10); } } // 学生选课 else if (isClickArea(350, 100, 120, 40, msg.x, msg.y)) { inputBuffer = tempStr1 = ""; bool waitInput = true; while (waitInput) { BeginBatchDraw(); cleardevice(); settextcolor(COLOR_BLACK); int stuX = 150, stuY = 95; int courseX = 150, courseY = 155; int inputW = 200, inputH = 40; outtextxy(50, 50, _T("学生选课")); outtextxy(50, 100, _T("学生学号:")); drawInputBox(stuX, stuY, inputW, inputH, _T("输入学号"), inputBuffer, currentFocus == FOCUS_STU_SELECT_STU_NUM); outtextxy(50, 160, _T("课程编号:")); drawInputBox(courseX, courseY, inputW, inputH, _T("输入课程编号"), tempStr1, currentFocus == FOCUS_STU_SELECT_COURSE_NUM); drawButton(150, 220, 100, 40, _T("确认选课"), COLOR_MENU, COLOR_TEXT); drawButton(270, 220, 100, 40, _T("取消"), RGB(200, 200, 200), COLOR_BLACK); FlushBatchDraw(); EndBatchDraw(); if (MouseHit()) { MOUSEMSG msg2 = GetMouseMsg(); if (msg2.uMsg == WM_LBUTTONDOWN) { resetKeyFlags(); if (isClickArea(stuX, stuY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_STU_SELECT_STU_NUM; lastCursorTime = GetTickCount(); } else if (isClickArea(courseX, courseY, inputW, inputH, msg2.x, msg2.y)) { currentFocus = FOCUS_STU_SELECT_COURSE_NUM; lastCursorTime = GetTickCount(); } else if (isClickArea(150, 220, 100, 40, msg2.x, msg2.y)) { long stuNum = str2num(inputBuffer); long courseNum = str2num(tempStr1); if (student::isHave(stuNum) && course::isHave(courseNum)) { student::addCourseToStudent(stuNum, courseNum); cleardevice(); outtextxy(50, 290, _T("选课成功!")); } else { cleardevice(); outtextxy(50, 290, _T("学生或课程不存在!")); } FlushBatchDraw(); Sleep(1000); waitInput = false; currentMenu = 3; currentFocus = FOCUS_NONE; } else if (isClickArea(270, 220, 100, 40, msg2.x, msg2.y)) { waitInput = false; currentMenu = 3; currentFocus = FOCUS_NONE; } } } handleKeyboardInput(); updateCursor(); Sleep(10); } } // 查看所有学生(核心修复:持续监听返回事件) else if (isClickArea(500, 100, 120, 40, msg.x, msg.y)) { bool showList = true; while (showList) { BeginBatchDraw(); cleardevice(); settextcolor(COLOR_BLACK); outtextxy(50, 50, _T("所有学生信息")); // 绘制表头 int y = 100; settextstyle(16, 0, _T("微软雅黑")); outtextxy(50, y, _T("学号")); outtextxy(150, y, _T("姓名")); outtextxy(250, y, _T("性别")); outtextxy(300, y, _T("年级")); outtextxy(400, y, _T("已选课程数")); y += 30; // 绘制学生列表 settextstyle(14, 0, _T("微软雅黑")); if (studentList.empty()) { outtextxy(50, y, _T("暂无学生数据!")); } else { for (auto& s : student::getStudentList()) { if (y > WIN_HEIGHT - 80) break; // 防止超出界面 TCHAR numBuf[32] = { 0 }; MultiByteToWideChar(CP_ACP, 0, num2str(s.getNumber()).c_str(), -1, numBuf, 32); outtextxy(50, y, numBuf); TCHAR nameBuf[64] = { 0 }; MultiByteToWideChar(CP_ACP, 0, s.getName().c_str(), -1, nameBuf, 64); outtextxy(150, y, nameBuf); TCHAR sexBuf[32] = { 0 }; MultiByteToWideChar(CP_ACP, 0, s.getSex().c_str(), -1, sexBuf, 32); outtextxy(250, y, sexBuf); TCHAR gradeBuf[32] = { 0 }; MultiByteToWideChar(CP_ACP, 0, s.getGrade().c_str(), -1, gradeBuf, 32); outtextxy(300, y, gradeBuf); TCHAR courseCntBuf[32] = { 0 }; MultiByteToWideChar(CP_ACP, 0, num2str(s.getHaveC().size()).c_str(), -1, courseCntBuf, 32); outtextxy(400, y, courseCntBuf); y += 25; } } // 绘制返回按钮(固定在底部) drawButton(50, WIN_HEIGHT - 60, 80, 30, _T("返回"), RGB(200, 200, 200), COLOR_BLACK); FlushBatchDraw(); EndBatchDraw(); // 持续监听返回按钮点击 if (MouseHit()) { MOUSEMSG msg2 = GetMouseMsg(); if (msg2.uMsg == WM_LBUTTONDOWN && isClickArea(50, WIN_HEIGHT - 60, 80, 30, msg2.x, msg2.y)) { showList = false; currentMenu = 3; currentFocus = FOCUS_NONE; } } Sleep(10); } } } } FlushBatchDraw(); EndBatchDraw(); Sleep(10); } // 主函数 int main() { initgraph(WIN_WIDTH, WIN_HEIGHT); setbkcolor(COLOR_BG); cleardevice(); lastCursorTime = GetTickCount(); resetKeyFlags(); while (true) { updateCursor(); if (!isLogin) { drawLogin(); } else { switch (currentMenu) { case 1: drawMainMenu(); break; case 2: drawCourseMenu(); break; case 3: drawStudentMenu(); break; default: currentMenu = 1; break; } } } closegraph(); return 0; }