You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1245 lines
52 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <graphics.h>
#include <conio.h>
#include <iostream>
#include <string.h>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <windows.h>
#include <tchar.h>
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<course>& getCourseList();
};
// 学生类
class student : public info {
private:
string sex; // 性别
string grade; // 年级
long scredit; // 总学分
vector<course> 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<course>& 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<student>& getStudentList();
static void addCourseToStudent(long stuNum, long courseNum);
static void delCourseFromStudent(long stuNum, long courseNum);
};
// 全局容器
vector<course> courseList;
vector<student> studentList;
// 课程类静态方法实现
vector<course>& 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>& 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;
}