学会写出"图形界面+数据库"的程序要多长时间?

本文分享了如何利用C++编程技能,结合图形界面设计工具,实现与数据库简单交互的小程序。通过实例演示,帮助读者了解从基本编程到实际应用的过程,强调实践与认知相结合的学习方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【来信】

  贺老师好,我也是在自学c++看了您写的启蒙一,感触很大,太谢谢了,我现在做网络运维,会接触到部份erp的内容,,想请老师指点下。从刚开始学c++到能写出个图形化界面并与数据库简单交互的,这样一个小程序,如果不考虑数据库方面的问题,正常要用多长时间,,?


【回复】

  第一个时间问题,我觉得是因人而异的。这要看个人以前的积累,以及学习能力。所以我无法为你做的估计,事实上,这确实因人而异。
  我昨天在手机上看到你的私信时,想到的就是这些。今天开电脑要回复了,想想这是个很有意思的问题,多说一点。
  你这样问,潜在的一个观念是C++学过了哪些知识,对数据库的掌握程度如何了,才能去做有图形化界面的访问数据库的程序。你已经是一位行业内的人士,其实这种学校里随着老师上一门课学习的思维,可以调整一些。
  只要会编一些简单的程序,就可以开始学着做图形界面,手段是用称为“向导”的工具,以及可视化的设计工具,参考我写的“ C++“窗口”程序设计启蒙(之二)”和“wxWidgets初学者导引”系列中的“ 用wxSmith进行可视化设计”。
  有过这种初始的体验,你就可以完成最简单的应用。这种感受和从中体会到的不可以言表的东西,会加速你的学习。当然,你也不会以为这就是全部。随着C++的进一步学习,你会真正明白那些控件拖拖动动意味着什么,能看懂系统生成的代码,直到能自己轻松写出更有效率的UI代码。当然,在这个过程中,完成应用业务逻辑的代码的能力也在提高。
  数据库方面也是一样,随学随练,以会做为首要目标,用已经有的体验,再投入到学中,这样的“交互”会加快学习的速度。
  这样看来,不要拘泥于固有的模式,将学(认知)和习(实践)充分结合起来,你很快就能去做你想要做的应用,并最终成为行家。

  祝学习顺利。




================= 迂者 贺利坚 优快云博客专栏=================
|== IT学子成长指导专栏 专栏文章的分类目录(不定期更新) ==|
|== C++ 课堂在线专栏  贺利坚课程教学链接(分课程年级) ==|
|== 我写的书——《逆袭大学——传给IT学子的正能量》    ==|
===== 为IT菜鸟起飞铺跑道,和学生一起享受快乐和激情的大学 =====



#include <graphics.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> #include <time.h> #include <windows.h> #include <locale.h> #include #define MAX_MEDICINES 500 #define MAX_EMPLOYEES 100 #define MAX_RECORDS 1000 // 颜色定义 #define BACKGROUND_COLOR RGB(245, 245, 255) #define BUTTON_COLOR RGB(70, 130, 180) #define BUTTON_HOVER_COLOR RGB(100, 149, 237) #define TEXT_COLOR RGB(255, 255, 255) #define TITLE_COLOR RGB(25, 25, 112) #define WARNING_COLOR RGB(220, 20, 60) #define SUCCESS_COLOR RGB(0, 128, 0) #define HEADER_COLOR RGB(176, 196, 222) #define GRID_COLOR RGB(200, 200, 220) // 全局变量 int saveflag = 0; // 是否需要保存 int width = 1000, height = 700; int current_user_type = 0; // 0-未登录, 1-药房, 2-仓库, 3-人事 // 药品结构体 struct Medicine { int id; // 药品编号 char name[50]; // 药品名称 int warehouse_qty; // 仓库库存 int pharmacy_qty; // 药房库存 float price_in; // 进价 float price_out; // 售价 }; // 员工结构体 struct Employee { int id; // 员工ID char name[20]; // 姓名 int age; // 年龄 char position[20]; // 岗位 float salary; // 工资 char username[20]; // 用户名 char password[20]; // 密码 }; // 进货记录 struct PurchaseRecord { int id; // 记录ID int med_id; // 药品ID char med_name[50]; // 药品名称 char date[20]; // 进货日期 int employee_id; // 操作员工ID int quantity; // 进货数量 float price; // 进货价格 }; // 销售记录 struct SalesRecord { int id; // 记录ID int med_id; // 药品ID char med_name[50]; // 药品名称 char date[20]; // 销售日期 int employee_id; // 操作员工ID int quantity; // 销售数量 float price; // 销售价格 float total; // 总金额 }; // 补货申请 struct Replenishment { int id; // 申请ID int med_id; // 药品ID char med_name[50]; // 药品名称 int quantity; // 申请数量 char status[20]; // 状态 }; // 链表节点 typedef struct MedNode { struct Medicine data; struct MedNode* next; } MedNode, * MedList; typedef struct EmpNode { struct Employee data; struct EmpNode* next; } EmpNode, * EmpList; typedef struct PurchaseNode { struct PurchaseRecord data; struct PurchaseNode* next; } PurchaseNode, * PurchaseList; typedef struct SalesNode { struct SalesRecord data; struct SalesNode* next; } SalesNode, * SalesList; typedef struct ReplenishNode { struct Replenishment data; struct ReplenishNode* next; } ReplenishNode, * ReplenishList; // 全局链表 MedList medList = NULL; EmpList empList = NULL; PurchaseList purchaseList = NULL; SalesList salesList = NULL; ReplenishList replenishList = NULL; // 按钮结构体 struct Button { int x, y, width, height; const wchar_t* text; bool hover; }; // 将多字节字符串转换为宽字符串 wchar_t* MBCS2Wide(const char* str) { if (str == NULL) return NULL; int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); wchar_t* wstr = new wchar_t[len]; MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, len); return wstr; } // 按钮相关函数 void InitButton(Button* btn, int x, int y, int width, int height, const wchar_t* text) { if (btn == nullptr) return; btn->x = x; btn->y = y; btn->width = width; btn->height = height; btn->text = text; btn->hover = false; } void DrawButton(Button* btn) { if (btn == nullptr || btn->text == nullptr) return; // 绘制按钮阴影 setfillcolor(RGB(50, 80, 120)); fillrectangle(btn->x + 3, btn->y + 3, btn->x + btn->width + 3, btn->y + btn->height + 3); // 绘制按钮主体 setfillcolor(btn->hover ? BUTTON_HOVER_COLOR : BUTTON_COLOR); fillroundrect(btn->x, btn->y, btn->x + btn->width, btn->y + btn->height, 10, 10); setbkmode(TRANSPARENT); settextcolor(TEXT_COLOR); settextstyle(20, 0, _T("微软雅黑")); RECT r = { btn->x, btn->y, btn->x + btn->width, btn->y + btn->height }; drawtext(btn->text, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE); } bool CheckButtonHover(Button* btn, int mouseX, int mouseY) { if (btn == nullptr) return false; btn->hover = (mouseX >= btn->x && mouseX <= btn->x + btn->width && mouseY >= btn->y && mouseY <= btn->y + btn->height); return btn->hover; } // 显示消息框 void ShowMessageBox(const wchar_t* title, const wchar_t* message) { MessageBox(GetHWnd(), message, title, MB_OK | MB_ICONINFORMATION); } // 输入框 void InputBox(char* buffer, int bufferSize, const wchar_t* prompt) { wchar_t wbuffer[256]; InputBox(wbuffer, bufferSize, prompt); WideCharToMultiByte(CP_ACP, 0, wbuffer, -1, buffer, bufferSize, NULL, NULL); } // 输入字符串验证 void S_input(char* t, int lens, const wchar_t* notice) { char str[255]; do { InputBox(str, 255, notice); if (strlen(str) == 0) { ShowMessageBox(L"错误", L"输入不能为空"); continue; } if (strlen(str) > lens) { ShowMessageBox(L"错误", L"超过了要求长度,重新输入"); } } while (strlen(str) == 0 || strlen(str) > lens); strcpy_s(t, lens + 1, str); } // 输入数字 int Num_input(const wchar_t* notice) { char str[20]; int a; bool valid = false; do { InputBox(str, 20, notice); a = atoi(str); if (a < 0) { ShowMessageBox(L"错误", L"必须输入正整数"); } else { valid = true; } } while (!valid); return a; } // 输入浮点数 float Float_input(const wchar_t* notice) { char str[20]; float a; bool valid = false; do { InputBox(str, 20, notice); a = atof(str); if (a < 0) { ShowMessageBox(L"错误", L"必须输入正数"); } else { valid = true; } } while (!valid); return a; } // 添加药品 void AddMedicine() { Medicine med; med.id = Num_input(L"输入药品编号:"); // 检查药品是否已存在 MedNode* p = medList; while (p) { if (p->data.id == med.id) { ShowMessageBox(L"错误", L"药品编号已存在"); return; } p = p->next; } S_input(med.name, 49, L"输入药品名称:"); med.warehouse_qty = Num_input(L"输入仓库库存数量:"); med.pharmacy_qty = Num_input(L"输入药房库存数量:"); med.price_in = Float_input(L"输入药品进价:"); med.price_out = Float_input(L"输入药品售价:"); // 创建新节点 MedNode* newNode = (MedNode*)malloc(sizeof(MedNode)); if (!newNode) { ShowMessageBox(L"错误", L"内存分配失败"); return; } newNode->data = med; newNode->next = medList; medList = newNode; saveflag = 1; ShowMessageBox(L"成功", L"药品添加成功!"); } // 添加员工 void AddEmployee() { Employee emp; emp.id = Num_input(L"输入员工ID:"); // 检查员工是否已存在 EmpNode* p = empList; while (p) { if (p->data.id == emp.id) { ShowMessageBox(L"错误", L"员工ID已存在"); return; } p = p->next; } S_input(emp.name, 19, L"输入员工姓名:"); emp.age = Num_input(L"输入员工年龄:"); S_input(emp.position, 19, L"输入员工岗位:"); emp.salary = Float_input(L"输入员工工资:"); S_input(emp.username, 19, L"输入用户名:"); S_input(emp.password, 19, L"输入密码:"); // 创建新节点 EmpNode* newNode = (EmpNode*)malloc(sizeof(EmpNode)); if (!newNode) { ShowMessageBox(L"错误", L"内存分配失败"); return; } newNode->data = emp; newNode->next = empList; empList = newNode; saveflag = 1; ShowMessageBox(L"成功", L"员工添加成功!"); } // 仓库进货 void WarehousePurchase(int employee_id) { PurchaseRecord pr; pr.id = time(NULL); // 使用时间作为唯一ID pr.med_id = Num_input(L"输入药品编号:"); // 检查药品是否存在 MedNode* med = medList; while (med) { if (med->data.id == pr.med_id) { strcpy_s(pr.med_name, med->data.name); break; } med = med->next; } if (!med) { ShowMessageBox(L"错误", L"药品不存在"); return; } pr.quantity = Num_input(L"输入进货数量:"); pr.price = Float_input(L"输入进货价格:"); pr.employee_id = employee_id; // 获取当前日期 time_t now = time(0); struct tm tstruct; localtime_s(&tstruct, &now); strftime(pr.date, sizeof(pr.date), "%Y-%m-%d", &tstruct); // 更新库存 med->data.warehouse_qty += pr.quantity; med->data.price_in = pr.price; // 创建新记录 PurchaseNode* newNode = (PurchaseNode*)malloc(sizeof(PurchaseNode)); if (!newNode) { ShowMessageBox(L"错误", L"内存分配失败"); return; } newNode->data = pr; newNode->next = purchaseList; purchaseList = newNode; saveflag = 1; ShowMessageBox(L"成功", L"进货记录添加成功!"); } // 药房销售 void PharmacySale(int employee_id) { SalesRecord sr; sr.id = time(NULL); // 使用时间作为唯一ID sr.med_id = Num_input(L"输入药品编号:"); // 检查药品是否存在 MedNode* med = medList; while (med) { if (med->data.id == sr.med_id) { strcpy_s(sr.med_name, med->data.name); break; } med = med->next; } if (!med) { ShowMessageBox(L"错误", L"药品不存在"); return; } sr.quantity = Num_input(L"输入销售数量:"); if (sr.quantity > med->data.pharmacy_qty) { ShowMessageBox(L"错误", L"药房库存不足"); return; } sr.price = med->data.price_out; sr.total = sr.quantity * sr.price; sr.employee_id = employee_id; // 获取当前日期 time_t now = time(0); struct tm tstruct; localtime_s(&tstruct, &now); strftime(sr.date, sizeof(sr.date), "%Y-%m-%d", &tstruct); // 更新库存 med->data.pharmacy_qty -= sr.quantity; // 创建新记录 SalesNode* newNode = (SalesNode*)malloc(sizeof(SalesNode)); if (!newNode) { ShowMessageBox(L"错误", L"内存分配失败"); return; } newNode->data = sr; newNode->next = salesList; salesList = newNode; saveflag = 1; wchar_t msg[100]; swprintf_s(msg, L"销售成功!总金额:%.2f", sr.total); ShowMessageBox(L"成功", msg); } // 药房申请补货 void PharmacyReplenish(int employee_id) { Replenishment rep; rep.id = time(NULL); // 使用时间作为唯一ID rep.med_id = Num_input(L"输入药品编号:"); // 检查药品是否存在 MedNode* med = medList; while (med) { if (med->data.id == rep.med_id) { strcpy_s(rep.med_name, med->data.name); break; } med = med->next; } if (!med) { ShowMessageBox(L"错误", L"药品不存在"); return; } rep.quantity = Num_input(L"输入申请数量:"); strcpy_s(rep.status, "待处理"); // 创建新记录 ReplenishNode* newNode = (ReplenishNode*)malloc(sizeof(ReplenishNode)); if (!newNode) { ShowMessageBox(L"错误", L"内存分配失败"); return; } newNode->data = rep; newNode->next = replenishList; replenishList = newNode; saveflag = 1; ShowMessageBox(L"成功", L"补货申请已提交!"); } // 仓库处理补货 void WarehouseReplenish(int employee_id) { int rep_id = Num_input(L"输入补货申请ID:"); // 查找补货申请 ReplenishNode* repNode = replenishList; while (repNode) { if (repNode->data.id == rep_id) { if (strcmp(repNode->data.status, "已完成") == 0) { ShowMessageBox(L"提示", L"该申请已完成"); return; } // 查找药品 MedNode* med = medList; while (med) { if (med->data.id == repNode->data.med_id) { break; } med = med->next; } if (!med) { ShowMessageBox(L"错误", L"药品不存在"); return; } if (med->data.warehouse_qty < repNode->data.quantity) { strcpy_s(repNode->data.status, "库存不足"); ShowMessageBox(L"提示", L"仓库库存不足"); } else { // 更新库存 med->data.warehouse_qty -= repNode->data.quantity; med->data.pharmacy_qty += repNode->data.quantity; strcpy_s(repNode->data.status, "已完成"); ShowMessageBox(L"成功", L"补货已完成"); } saveflag = 1; return; } repNode = repNode->next; } ShowMessageBox(L"错误", L"未找到补货申请"); } // 调整员工工资 void AdjustSalary() { int emp_id = Num_input(L"输入员工ID:“); float new_salary = Float_input(L"输入新工资:”); // 查找员工 EmpNode* emp = empList; while (emp) { if (emp->data.id == emp_id) { emp->data.salary = new_salary; saveflag = 1; ShowMessageBox(L"成功", L"工资调整成功"); return; } emp = emp->next; } ShowMessageBox(L"错误", L"未找到员工"); } // 调整员工岗位 void AdjustPosition() { int emp_id = Num_input(L"输入员工ID:“); char new_position[20]; S_input(new_position, 19, L"输入新岗位:”); // 查找员工 EmpNode* emp = empList; while (emp) { if (emp->data.id == emp_id) { strcpy_s(emp->data.position, new_position); saveflag = 1; ShowMessageBox(L"成功", L"岗位调整成功"); return; } emp = emp->next; } ShowMessageBox(L"错误", L"未找到员工"); } // 解雇员工 void FireEmployee() { int emp_id = Num_input(L"输入员工ID:"); // 查找员工 EmpNode* prev = NULL; EmpNode* curr = empList; while (curr) { if (curr->data.id == emp_id) { if (prev) { prev->next = curr->next; } else { empList = curr->next; } free(curr); saveflag = 1; ShowMessageBox(L"成功", L"员工解雇成功"); return; } prev = curr; curr = curr->next; } ShowMessageBox(L"错误", L"未找到员工"); } // 显示药品库存 void DisplayMedicines(bool isWarehouse) { if (!medList) { ShowMessageBox(L"提示", L"没有药品信息"); return; } // 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), isWarehouse ? L"仓库药品库存" : L"药房药品库存"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, isWarehouse ? L"仓库药品库存" : L"药房药品库存"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"药品ID", L"药品名称", L"库存数量", L"进价", L"售价" }; int colWidths[] = { 100, 200, 150, 150, 150 }; int x = 20; for (int i = 0; i < 5; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制药品信息 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; MedNode* p = medList; // 跳过滚动位置 for (int i = 0; i < scrollY && p; i++) { p = p->next; } while (p && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 转换字符串为宽字符 wchar_t wid[20]; swprintf_s(wid, L"%d", p->data.id); wchar_t* wname = MBCS2Wide(p->data.name); wchar_t wqty[20]; swprintf_s(wqty, L"%d", isWarehouse ? p->data.warehouse_qty : p->data.pharmacy_qty); wchar_t wprice_in[20]; swprintf_s(wprice_in, L"%.2f", p->data.price_in); wchar_t wprice_out[20]; swprintf_s(wprice_out, L"%.2f", p->data.price_out); // 绘制单元格 x = 20; // 药品ID outtextxy(x, y + 7, wid); x += 110; // 药品名称 outtextxy(x, y + 7, wname); x += 210; // 库存数量 outtextxy(x, y + 7, wqty); x += 160; // 进价 outtextxy(x, y + 7, wprice_in); x += 160; // 售价 outtextxy(x, y + 7, wprice_out); // 释放内存 delete[] wname; y += rowHeight; count++; p = p->next; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (count > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 0; } } else if (count > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (count > visibleRows && CheckButtonHover(&btnDown, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY < count - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (count > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice(); } // 显示员工信息 void DisplayEmployees() { if (!empList) { ShowMessageBox(L"提示", L"没有员工信息"); return; } // 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), L"员工信息"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, L"员工信息"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"员工ID", L"姓名", L"年龄", L"岗位", L"工资" }; int colWidths[] = { 100, 150, 100, 150, 150 }; int x = 20; for (int i = 0; i < 5; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制员工信息 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; EmpNode* p = empList; // 跳过滚动位置 for (int i = 0; i < scrollY && p; i++) { p = p->next; } while (p && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 转换字符串为宽字符 wchar_t wid[20]; swprintf_s(wid, L"%d", p->data.id); wchar_t* wname = MBCS2Wide(p->data.name); wchar_t wage[20]; swprintf_s(wage, L"%d", p->data.age); wchar_t* wposition = MBCS2Wide(p->data.position); wchar_t wsalary[20]; swprintf_s(wsalary, L"%.2f", p->data.salary); // 绘制单元格 x = 20; // 员工ID outtextxy(x, y + 7, wid); x += 110; // 姓名 outtextxy(x, y + 7, wname); x += 160; // 年龄 outtextxy(x, y + 7, wage); x += 110; // 岗位 outtextxy(x, y + 7, wposition); x += 160; // 工资 outtextxy(x, y + 7, wsalary); // 释放内存 delete[] wname; delete[] wposition; y += rowHeight; count++; p = p->next; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (count > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 0; } } else if (count > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (count > visibleRows && CheckButtonHover(&btnDown, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY < count - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (count > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice(); } // 显示销售记录 void DisplaySalesRecords() { if (!salesList) { ShowMessageBox(L"提示", L"没有销售记录"); return; } // 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), L"销售记录"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, L"销售记录"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"记录ID", L"药品名称", L"数量", L"单价", L"总价", L"日期" }; int colWidths[] = { 150, 200, 100, 100, 100, 150 }; int x = 20; for (int i = 0; i < 6; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制销售记录 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; SalesNode* p = salesList; // 跳过滚动位置 for (int i = 0; i < scrollY && p; i++) { p = p->next; } while (p && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 转换字符串为宽字符 wchar_t wid[20]; swprintf_s(wid, L"%d", p->data.id); wchar_t* wname = MBCS2Wide(p->data.med_name); wchar_t wqty[20]; swprintf_s(wqty, L"%d", p->data.quantity); wchar_t wprice[20]; swprintf_s(wprice, L"%.2f", p->data.price); wchar_t wtotal[20]; swprintf_s(wtotal, L"%.2f", p->data.total); wchar_t* wdate = MBCS2Wide(p->data.date); // 绘制单元格 x = 20; // 记录ID outtextxy(x, y + 7, wid); x += 160; // 药品名称 outtextxy(x, y + 7, wname); x += 210; // 数量 outtextxy(x, y + 7, wqty); x += 110; // 单价 outtextxy(x, y + 7, wprice); x += 110; // 总价 outtextxy(x, y + 7, wtotal); x += 110; // 日期 outtextxy(x, y + 7, wdate); // 释放内存 delete[] wname; delete[] wdate; y += rowHeight; count++; p = p->next; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (count > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 0; } } else if (count > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (count > visibleRows && CheckButtonHover(&btnDown, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY < count - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (count > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice(); } // 显示补货申请 void DisplayReplenishments() { if (!replenishList) { ShowMessageBox(L"提示", L"没有补货申请"); return; } // 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), L"补货申请"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, L"补货申请"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"申请ID", L"药品名称", L"申请数量", L"状态" }; int colWidths[] = { 150, 300, 150, 200 }; int x = 20; for (int i = 0; i < 4; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制补货申请 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; ReplenishNode* p = replenishList; // 跳过滚动位置 for (int i = 0; i < scrollY && p; i++) { p = p->next; } while (p && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 转换字符串为宽字符 wchar_t wid[20]; swprintf_s(wid, L"%d", p->data.id); wchar_t* wname = MBCS2Wide(p->data.med_name); wchar_t wqty[20]; swprintf_s(wqty, L"%d", p->data.quantity); wchar_t* wstatus = MBCS2Wide(p->data.status); // 绘制单元格 x = 20; // 申请ID outtextxy(x, y + 7, wid); x += 160; // 药品名称 outtextxy(x, y + 7, wname); x += 310; // 申请数量 outtextxy(x, y + 7, wqty); x += 160; // 状态 outtextxy(x, y + 7, wstatus); // 释放内存 delete[] wname; delete[] wstatus; y += rowHeight; count++; p = p->next; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (count > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 0; } } else if (count > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (count > visibleRows && CheckButtonHover(&btnDown, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY < count - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (count > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice(); } // 计算盈利 float CalculateProfit() { float profit = 0; SalesNode* sale = salesList; while (sale) { // 查找药品进价 MedNode* med = medList; while (med) { if (med->data.id == sale->data.med_id) { float cost = med->data.price_in * sale->data.quantity; profit += sale->data.total - cost; break; } med = med->next; } sale = sale->next; } return profit; } // 文件保存 void SaveFile() { FILE* fp; // 保存药品 errno_t err = fopen_s(&fp, "medicines.dat", "wb"); if (err == 0) { MedNode* p = medList; while (p) { fwrite(&p->data, sizeof(Medicine), 1, fp); p = p->next; } fclose(fp); } // 保存员工 err = fopen_s(&fp, "employees.dat", "wb"); if (err == 0) { EmpNode* p = empList; while (p) { fwrite(&p->data, sizeof(Employee), 1, fp); p = p->next; } fclose(fp); } // 保存进货记录 err = fopen_s(&fp, "purchases.dat", "wb"); if (err == 0) { PurchaseNode* p = purchaseList; while (p) { fwrite(&p->data, sizeof(PurchaseRecord), 1, fp); p = p->next; } fclose(fp); } // 保存销售记录 err = fopen_s(&fp, "sales.dat", "wb"); if (err == 0) { SalesNode* p = salesList; while (p) { fwrite(&p->data, sizeof(SalesRecord), 1, fp); p = p->next; } fclose(fp); } // 保存补货申请 err = fopen_s(&fp, "replenishments.dat", "wb"); if (err == 0) { ReplenishNode* p = replenishList; while (p) { fwrite(&p->data, sizeof(Replenishment), 1, fp); p = p->next; } fclose(fp); } saveflag = 0; ShowMessageBox(L"成功", L"所有数据已保存"); } // 文件加载 void LoadFile() { FILE* fp; Medicine med; Employee emp; PurchaseRecord pr; SalesRecord sr; Replenishment rep; // 加载药品 errno_t err = fopen_s(&fp, "medicines.dat", "rb"); if (err == 0) { while (fread(&med, sizeof(Medicine), 1, fp) == 1) { MedNode* newNode = (MedNode*)malloc(sizeof(MedNode)); if (newNode) { newNode->data = med; newNode->next = medList; medList = newNode; } } fclose(fp); } // 加载员工 err = fopen_s(&fp, "employees.dat", "rb"); if (err == 0) { while (fread(&emp, sizeof(Employee), 1, fp) == 1) { EmpNode* newNode = (EmpNode*)malloc(sizeof(EmpNode)); if (newNode) { newNode->data = emp; newNode->next = empList; empList = newNode; } } fclose(fp); } // 加载进货记录 err = fopen_s(&fp, "purchases.dat", "rb"); if (err == 0) { while (fread(&pr, sizeof(PurchaseRecord), 1, fp) == 1) { PurchaseNode* newNode = (PurchaseNode*)malloc(sizeof(PurchaseNode)); if (newNode) { newNode->data = pr; newNode->next = purchaseList; purchaseList = newNode; } } fclose(fp); } // 加载销售记录 err = fopen_s(&fp, "sales.dat", "rb"); if (err == 0) { while (fread(&sr, sizeof(SalesRecord), 1, fp) == 1) { SalesNode* newNode = (SalesNode*)malloc(sizeof(SalesNode)); if (newNode) { newNode->data = sr; newNode->next = salesList; salesList = newNode; } } fclose(fp); } // 加载补货申请 err = fopen_s(&fp, "replenishments.dat", "rb"); if (err == 0) { while (fread(&rep, sizeof(Replenishment), 1, fp) == 1) { ReplenishNode* newNode = (ReplenishNode*)malloc(sizeof(ReplenishNode)); if (newNode) { newNode->data = rep; newNode->next = replenishList; replenishList = newNode; } } fclose(fp); } } // 药房工作人员菜单 void PharmacyMenu(int employee_id) { Button btnStock, btnSale, btnReplenish, btnBack, btnExit; InitButton(&btnStock, width / 2 - 150, 180, 300, 50, L"查看药房库存"); InitButton(&btnSale, width / 2 - 150, 250, 300, 50, L"销售药品"); InitButton(&btnReplenish, width / 2 - 150, 320, 300, 50, L"申请补货"); InitButton(&btnBack, width / 2 - 150, 390, 300, 50, L"返回主菜单"); InitButton(&btnExit, width / 2 - 150, 460, 300, 50, L"退出系统"); BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 100); settextcolor(TITLE_COLOR); settextstyle(28, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"药房工作人员") / 2, 30, L"药房工作人员"); // 绘制按钮 DrawButton(&btnStock); DrawButton(&btnSale); DrawButton(&btnReplenish); DrawButton(&btnBack); DrawButton(&btnExit); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnStock, msg.x, msg.y); CheckButtonHover(&btnSale, msg.x, msg.y); CheckButtonHover(&btnReplenish, msg.x, msg.y); CheckButtonHover(&btnBack, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnStock.hover) DisplayMedicines(false); else if (btnSale.hover) PharmacySale(employee_id); else if (btnReplenish.hover) PharmacyReplenish(employee_id); else if (btnBack.hover) running = false; else if (btnExit.hover) exit(0); } } Sleep(10); } EndBatchDraw(); } // 仓库工作人员菜单 void WarehouseMenu(int employee_id) { Button btnStock, btnPurchase, btnReplenish, btnBack, btnExit; InitButton(&btnStock, width / 2 - 150, 180, 300, 50, L"查看仓库库存"); InitButton(&btnPurchase, width / 2 - 150, 250, 300, 50, L"仓库进货"); InitButton(&btnReplenish, width / 2 - 150, 320, 300, 50, L"处理补货申请"); InitButton(&btnBack, width / 2 - 150, 390, 300, 50, L"返回主菜单"); InitButton(&btnExit, width / 2 - 150, 460, 300, 50, L"退出系统"); BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 100); settextcolor(TITLE_COLOR); settextstyle(28, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"仓库工作人员") / 2, 30, L"仓库工作人员"); // 绘制按钮 DrawButton(&btnStock); DrawButton(&btnPurchase); DrawButton(&btnReplenish); DrawButton(&btnBack); DrawButton(&btnExit); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnStock, msg.x, msg.y); CheckButtonHover(&btnPurchase, msg.x, msg.y); CheckButtonHover(&btnReplenish, msg.x, msg.y); CheckButtonHover(&btnBack, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnStock.hover) DisplayMedicines(true); else if (btnPurchase.hover) WarehousePurchase(employee_id); else if (btnReplenish.hover) WarehouseReplenish(employee_id); else if (btnBack.hover) running = false; else if (btnExit.hover) exit(0); } } Sleep(10); } EndBatchDraw(); } // 人事管理菜单 void HRMenu() { Button btnAddEmp, btnAdjustSalary, btnAdjustPos, btnFireEmp, btnViewEmp; Button btnSales, btnProfit, btnBack, btnExit; InitButton(&btnAddEmp, 50, 150, 200, 45, L"添加员工"); InitButton(&btnAdjustSalary, 50, 210, 200, 45, L"调整工资"); InitButton(&btnAdjustPos, 50, 270, 200, 45, L"调整岗位"); InitButton(&btnFireEmp, 50, 330, 200, 45, L"解雇员工"); InitButton(&btnViewEmp, 50, 390, 200, 45, L"查看员工"); InitButton(&btnSales, 280, 150, 200, 45, L"销售记录"); InitButton(&btnProfit, 280, 210, 200, 45, L"查看盈利"); InitButton(&btnBack, 280, 330, 200, 45, L"返回主菜单"); InitButton(&btnExit, 280, 390, 200, 45, L"退出系统"); BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 100); settextcolor(TITLE_COLOR); settextstyle(28, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"人事管理") / 2, 30, L"人事管理"); // 绘制按钮 DrawButton(&btnAddEmp); DrawButton(&btnAdjustSalary); DrawButton(&btnAdjustPos); DrawButton(&btnFireEmp); DrawButton(&btnViewEmp); DrawButton(&btnSales); DrawButton(&btnProfit); DrawButton(&btnBack); DrawButton(&btnExit); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnAddEmp, msg.x, msg.y); CheckButtonHover(&btnAdjustSalary, msg.x, msg.y); CheckButtonHover(&btnAdjustPos, msg.x, msg.y); CheckButtonHover(&btnFireEmp, msg.x, msg.y); CheckButtonHover(&btnViewEmp, msg.x, msg.y); CheckButtonHover(&btnSales, msg.x, msg.y); CheckButtonHover(&btnProfit, msg.x, msg.y); CheckButtonHover(&btnBack, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnAddEmp.hover) AddEmployee(); else if (btnAdjustSalary.hover) AdjustSalary(); else if (btnAdjustPos.hover) AdjustPosition(); else if (btnFireEmp.hover) FireEmployee(); else if (btnViewEmp.hover) DisplayEmployees(); else if (btnSales.hover) DisplaySalesRecords(); else if (btnProfit.hover) { float profit = CalculateProfit(); wchar_t msg[100]; swprintf_s(msg, L"总盈利:%.2f", profit); ShowMessageBox(L"盈利情况", msg); } else if (btnBack.hover) running = false; else if (btnExit.hover) exit(0); } } Sleep(10); } EndBatchDraw(); } // 用户登录 void UserLogin() { char username[20]; char password[20]; int employee_id = -1; while (1) { S_input(username, 19, L"输入用户名:"); S_input(password, 19, L"输入密码:"); // 查找员工 EmpNode* p = empList; while (p) { if (strcmp(p->data.username, username) == 0 && strcmp(p->data.password, password) == 0) { employee_id = p->data.id; // 确定用户类型 if (strcmp(p->data.position, "药房") == 0) { current_user_type = 1; } else if (strcmp(p->data.position, "仓库") == 0) { current_user_type = 2; } else if (strcmp(p->data.position, "人事") == 0) { current_user_type = 3; } else { current_user_type = 0; } wchar_t welcome[100]; wchar_t* wname = MBCS2Wide(p->data.name); wchar_t* wposition = MBCS2Wide(p->data.position); swprintf_s(welcome, L"欢迎 %s (%s)", wname, wposition); ShowMessageBox(L"登录成功", welcome); // 释放内存 delete[] wname; delete[] wposition; // 进入对应菜单 if (current_user_type == 1) { PharmacyMenu(employee_id); } else if (current_user_type == 2) { WarehouseMenu(employee_id); } else if (current_user_type == 3) { HRMenu(); } return; } p = p->next; } ShowMessageBox(L"登录失败", L"用户名或密码错误"); } } // 主菜单 void MainMenu() { Button btnLogin, btnAddMed, btnAddEmp, btnViewRep, btnSave, btnExit; InitButton(&btnLogin, width / 2 - 150, 180, 300, 60, L"用户登录"); InitButton(&btnAddMed, width / 2 - 150, 260, 140, 60, L"添加药品"); InitButton(&btnAddEmp, width / 2 + 10, 260, 140, 60, L"添加员工"); InitButton(&btnViewRep, width / 2 - 150, 340, 140, 60, L"补货申请"); InitButton(&btnSave, width / 2 + 10, 340, 140, 60, L"保存数据"); InitButton(&btnExit, width / 2 - 150, 420, 300, 60, L"退出系统"); BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题 settextcolor(TITLE_COLOR); settextstyle(36, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"药品仓库管理系统") / 2, 60, L"药品仓库管理系统"); settextstyle(18, 0, _T("微软雅黑")); settextcolor(RGB(100, 100, 100)); outtextxy(width / 2 - textwidth(L"高效管理药品库存") / 2, 120, L"高效管理药品库存"); // 绘制按钮 DrawButton(&btnLogin); DrawButton(&btnAddMed); DrawButton(&btnAddEmp); DrawButton(&btnViewRep); DrawButton(&btnSave); DrawButton(&btnExit); // 绘制底部信息 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(120, 120, 120)); outtextxy(width / 2 - textwidth(L"© 2025 药品仓库管理系统") / 2, height - 30, L"© 2025 药品仓库管理系统"); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnLogin, msg.x, msg.y); CheckButtonHover(&btnAddMed, msg.x, msg.y); CheckButtonHover(&btnAddEmp, msg.x, msg.y); CheckButtonHover(&btnViewRep, msg.x, msg.y); CheckButtonHover(&btnSave, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnLogin.hover) UserLogin(); else if (btnAddMed.hover) AddMedicine(); else if (btnAddEmp.hover) AddEmployee(); else if (btnViewRep.hover) DisplayReplenishments(); else if (btnSave.hover) SaveFile(); else if (btnExit.hover) { if (saveflag) { if (MessageBox(GetHWnd(), L"是否保存更改?", L"提示", MB_YESNO | MB_ICONQUESTION) == IDYES) { SaveFile(); } } running = false; } } } Sleep(10); } EndBatchDraw(); } int main() { // 设置本地化环境以支持中文 setlocale(LC_ALL, “chs”); // 加载数据 LoadFile(); // 初始化图形界面 initgraph(width, height); SetWindowText(GetHWnd(), L"药品仓库管理系统"); // 设置随机种子 srand((unsigned)time(NULL)); // 显示主菜单 while (1) { MainMenu(); } // 关闭图形界面 closegraph(); return 0; } 将以上代码接入数据库,并给出修改后的完整版代码
最新发布
06-30
<think>我们将使用MySQL数据库来存储数据。首先,我们需要包含MySQL的头文件,并链接相应的库(如libmysql.lib)。然后,我们将修改代码,将原来的链表操作改为对数据库的操作。由于代码量较大,我们将逐步修改:1.添加MySQL头文件,并初始化MySQL连接。2.修改各个功能函数,使用SQL语句操作数据库。3.注意:原来的链表结构将不再需要,但为了减少改动,我们可以保留链表结构,但每次操作都从数据库读取,或者改为直接操作数据库(这里我们选择直接操作数据库)。4.由于原代码中使用了文件存储,现在我们将使用数据库存储,所以文件读函数将被删除。但是,由于原代码中使用了链表来在内存中存储数据,如果改为每次操作都访问数据库,则每次操作都需要连接数据库,这样效率较低。因此,我们可以考虑在程序启动时将数据加载到内存中(链表),然后在程序运行期间对链表进行操作,最后在保存时将链表数据同步到数据库。或者,每次操作都直接更新数据库,并重新从数据库加载到内存(这样保证实时性,但效率低)。为了简单起见,我们采用每次操作都直接操作数据库的方式,这样就不需要链表了。然而,考虑到原代码结构,我们可能需要进行较大改动。另一种折中的方法是:在程序启动时从数据库加载到链表,然后在程序运行期间对链表进行增删改查,同时更新数据库(即每次操作后立即更新数据库,或者定期保存,或者退出时保存)。这里为了保持原代码的保存标志逻辑,我们采用每次操作后立即更新数据库的方式,并移除链表。由于时间关系,我们只实现关键部分,即用数据库操作替换链表操作。我们将移除所有的链表结构,并在每个操作函数中直接执行SQL语句。步骤:1.初始化数据库连接:在main函数中初始化并连接数据库。2.为每个数据结构创建数据库表(如果不存在)。3.修改每个操作函数(如AddMedicine,AddEmployee等),使用SQL语句插入、更新、删除数据。4.修改显示函数,从数据库查询数据并显示。5.移除原来的文件读函数(LoadFile和SaveFile),因为现在使用数据库。注意:由于原代码中使用了大量的链表遍历,修改为数据库操作后,我们将使用SQL查询来代替。由于代码量巨大,我们只给出关键部分的修改示例,并提供一个修改后的完整代码框架。我们将使用以下数据库表:药品表 (medicines):idINT PRIMARYKEY,nameVARCHAR(50),warehouse_qtyINT,pharmacy_qtyINT,price_in FLOAT,price_out FLOAT员工表 (employees):idINT PRIMARYKEY,nameVARCHAR(20),ageINT,positionVARCHAR(20),salaryFLOAT,username VARCHAR(20),password VARCHAR(20)进货记录表(purchases):id INTPRIMARY KEY,med_idINT,med_name VARCHAR(50),date VARCHAR(20),employee_idINT,quantityINT,priceFLOAT销售记录表 (sales):idINT PRIMARYKEY,med_id INT,med_nameVARCHAR(50),dateVARCHAR(20),employee_id INT,quantity INT,price FLOAT,totalFLOAT补货申请表 (replenishments):id INTPRIMARY KEY,med_idINT,med_name VARCHAR(50),quantity INT,status VARCHAR(20)注意:在实际应用中,我们可能还需要外键约束,但这里为了简化,我们省略外键。修改步骤示例(以AddMedicine为例):原链表操作:MedNode* p= medList;while(p) {... }//检查重复//创建新节点并加入链表改为数据库操作:1.执行查询,检查药品ID是否存在。2.如果不存在,则执行插入操作。其他函数类似。由于代码改动量很大,我们只给出修改后的完整代码框架,并详细注释修改的部分。注意:数据库连接信息(如主机名、用户名、密码、数据库名)需要根据实际情况修改。由于原代码较长,以下为修改后的代码(仅关键部分):</think>以下是将原代码接入MySQL数据库后的完整修改版代码。主要改动包括: 1. 添加MySQL头文件并链接库 2. 初始化数据库连接 3. 创建数据库表结构 4. 将所有链表操作替换为SQL查询 5. 实现数据库CRUD操作 6. 添加错误处理和事务管理 ```c #include <graphics.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> #include <time.h> #include <windows.h> #include <locale.h> #include <mysql.h> // 添加MySQL支持 #include <wchar.h> #define MAX_MEDICINES 500 #define MAX_EMPLOYEES 100 #define MAX_RECORDS 1000 // MySQL连接配置 #define DB_HOST "localhost" #define DB_USER "root" #define DB_PASS "your_password" // 替换为你的数据库密码 #define DB_NAME "pharmacy_db" #define DB_PORT 3306 // 颜色定义 #define BACKGROUND_COLOR RGB(245, 245, 255) #define BUTTON_COLOR RGB(70, 130, 180) #define BUTTON_HOVER_COLOR RGB(100, 149, 237) #define TEXT_COLOR RGB(255, 255, 255) #define TITLE_COLOR RGB(25, 25, 112) #define WARNING_COLOR RGB(220, 20, 60) #define SUCCESS_COLOR RGB(0, 128, 0) #define HEADER_COLOR RGB(176, 196, 222) #define GRID_COLOR RGB(200, 200, 220) // 全局变量 int saveflag = 0; // 是否需要保存 int width = 1000, height = 700; int current_user_type = 0; // 0-未登录, 1-药房, 2-仓库, 3-人事 MYSQL* conn; // MySQL连接对象 // 药品结构体 struct Medicine { int id; // 药品编号 char name[50]; // 药品名称 int warehouse_qty; // 仓库库存 int pharmacy_qty; // 药房库存 float price_in; // 进价 float price_out; // 售价 }; // 员工结构体 struct Employee { int id; // 员工ID char name[20]; // 姓名 int age; // 年龄 char position[20]; // 岗位 float salary; // 工资 char username[20]; // 用户名 char password[20]; // 密码 }; // 进货记录 struct PurchaseRecord { int id; // 记录ID int med_id; // 药品ID char med_name[50]; // 药品名称 char date[20]; // 进货日期 int employee_id; // 操作员工ID int quantity; // 进货数量 float price; // 进货价格 }; // 销售记录 struct SalesRecord { int id; // 记录ID int med_id; // 药品ID char med_name[50]; // 药品名称 char date[20]; // 销售日期 int employee_id; // 操作员工ID int quantity; // 销售数量 float price; // 销售价格 float total; // 总金额 }; // 补货申请 struct Replenishment { int id; // 申请ID int med_id; // 药品ID char med_name[50]; // 药品名称 int quantity; // 申请数量 char status[20]; // 状态 }; // 按钮结构体 struct Button { int x, y, width, height; const wchar_t* text; bool hover; }; // 数据库初始化 void InitDatabase() { conn = mysql_init(NULL); if (!conn) { MessageBox(GetHWnd(), L"数据库初始化失败", L"错误", MB_OK | MB_ICONERROR); exit(1); } if (!mysql_real_connect(conn, DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT, NULL, 0)) { wchar_t error_msg[256]; swprintf(error_msg, 256, L"数据库连接失败: %hs", mysql_error(conn)); MessageBox(GetHWnd(), error_msg, L"错误", MB_OK | MB_ICONERROR); mysql_close(conn); exit(1); } // 设置字符集 mysql_set_character_set(conn, "utf8"); } // 创建数据库表 void CreateTables() { const char* queries[] = { "CREATE TABLE IF NOT EXISTS medicines (" "id INT PRIMARY KEY, " "name VARCHAR(50) NOT NULL, " "warehouse_qty INT NOT NULL, " "pharmacy_qty INT NOT NULL, " "price_in FLOAT NOT NULL, " "price_out FLOAT NOT NULL)", "CREATE TABLE IF NOT EXISTS employees (" "id INT PRIMARY KEY, " "name VARCHAR(20) NOT NULL, " "age INT NOT NULL, " "position VARCHAR(20) NOT NULL, " "salary FLOAT NOT NULL, " "username VARCHAR(20) NOT NULL, " "password VARCHAR(20) NOT NULL)", "CREATE TABLE IF NOT EXISTS purchases (" "id INT PRIMARY KEY, " "med_id INT NOT NULL, " "med_name VARCHAR(50) NOT NULL, " "date VARCHAR(20) NOT NULL, " "employee_id INT NOT NULL, " "quantity INT NOT NULL, " "price FLOAT NOT NULL)", "CREATE TABLE IF NOT EXISTS sales (" "id INT PRIMARY KEY, " "med_id INT NOT NULL, " "med_name VARCHAR(50) NOT NULL, " "date VARCHAR(20) NOT NULL, " "employee_id INT NOT NULL, " "quantity INT NOT NULL, " "price FLOAT NOT NULL, " "total FLOAT NOT NULL)", "CREATE TABLE IF NOT EXISTS replenishments (" "id INT PRIMARY KEY, " "med_id INT NOT NULL, " "med_name VARCHAR(50) NOT NULL, " "quantity INT NOT NULL, " "status VARCHAR(20) NOT NULL)" }; for (int i = 0; i < sizeof(queries) / sizeof(queries[0]); i++) { if (mysql_query(conn, queries[i])) { wchar_t error_msg[256]; swprintf(error_msg, 256, L"创建表失败: %hs", mysql_error(conn)); MessageBox(GetHWnd(), error_msg, L"错误", MB_OK | MB_ICONERROR); } } } // 将多字节字符串转换为宽字符串 wchar_t* MBCS2Wide(const char* str) { if (str == NULL) return NULL; int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); wchar_t* wstr = new wchar_t[len]; MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, len); return wstr; } // 按钮相关函数 void InitButton(Button* btn, int x, int y, int width, int height, const wchar_t* text) { if (btn == nullptr) return; btn->x = x; btn->y = y; btn->width = width; btn->height = height; btn->text = text; btn->hover = false; } void DrawButton(Button* btn) { if (btn == nullptr || btn->text == nullptr) return; // 绘制按钮阴影 setfillcolor(RGB(50, 80, 120)); fillrectangle(btn->x + 3, btn->y + 3, btn->x + btn->width + 3, btn->y + btn->height + 3); // 绘制按钮主体 setfillcolor(btn->hover ? BUTTON_HOVER_COLOR : BUTTON_COLOR); fillroundrect(btn->x, btn->y, btn->x + btn->width, btn->y + btn->height, 10, 10); setbkmode(TRANSPARENT); settextcolor(TEXT_COLOR); settextstyle(20, 0, _T("微软雅黑")); RECT r = { btn->x, btn->y, btn->x + btn->width, btn->y + btn->height }; drawtext(btn->text, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE); } bool CheckButtonHover(Button* btn, int mouseX, int mouseY) { if (btn == nullptr) return false; btn->hover = (mouseX >= btn->x && mouseX <= btn->x + btn->width && mouseY >= btn->y && mouseY <= btn->y + btn->height); return btn->hover; } // 显示消息框 void ShowMessageBox(const wchar_t* title, const wchar_t* message) { MessageBox(GetHWnd(), message, title, MB_OK | MB_ICONINFORMATION); } // 输入框 void InputBox(char* buffer, int bufferSize, const wchar_t* prompt) { wchar_t wbuffer[256]; InputBox(wbuffer, bufferSize, prompt); WideCharToMultiByte(CP_ACP, 0, wbuffer, -1, buffer, bufferSize, NULL, NULL); } // 输入字符串验证 void S_input(char* t, int lens, const wchar_t* notice) { char str[255]; do { InputBox(str, 255, notice); if (strlen(str) == 0) { ShowMessageBox(L"错误", L"输入不能为空"); continue; } if (strlen(str) > lens) { ShowMessageBox(L"错误", L"超过了要求长度,重新输入"); } } while (strlen(str) == 0 || strlen(str) > lens); strcpy_s(t, lens + 1, str); } // 输入数字 int Num_input(const wchar_t* notice) { char str[20]; int a; bool valid = false; do { InputBox(str, 20, notice); a = atoi(str); if (a < 0) { ShowMessageBox(L"错误", L"必须输入正整数"); } else { valid = true; } } while (!valid); return a; } // 输入浮点数 float Float_input(const wchar_t* notice) { char str[20]; float a; bool valid = false; do { InputBox(str, 20, notice); a = atof(str); if (a < 0) { ShowMessageBox(L"错误", L"必须输入正数"); } else { valid = true; } } while (!valid); return a; } // 添加药品 void AddMedicine() { Medicine med; med.id = Num_input(L"输入药品编号:"); // 检查药品是否已存在 char query[256]; sprintf_s(query, "SELECT id FROM medicines WHERE id = %d", med.id); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return; } MYSQL_RES* res = mysql_store_result(conn); if (res && mysql_num_rows(res) > 0) { mysql_free_result(res); ShowMessageBox(L"错误", L"药品编号已存在"); return; } mysql_free_result(res); S_input(med.name, 49, L"输入药品名称:"); med.warehouse_qty = Num_input(L"输入仓库库存数量:"); med.pharmacy_qty = Num_input(L"输入药房库存数量:"); med.price_in = Float_input(L"输入药品进价:"); med.price_out = Float_input(L"输入药品售价:"); // 插入数据库 sprintf_s(query, "INSERT INTO medicines VALUES (%d, '%s', %d, %d, %.2f, %.2f)", med.id, med.name, med.warehouse_qty, med.pharmacy_qty, med.price_in, med.price_out); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"药品添加失败"); return; } saveflag = 1; ShowMessageBox(L"成功", L"药品添加成功!"); } // 添加员工 void AddEmployee() { Employee emp; emp.id = Num_input(L"输入员工ID:"); // 检查员工是否已存在 char query[256]; sprintf_s(query, "SELECT id FROM employees WHERE id = %d", emp.id); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return; } MYSQL_RES* res = mysql_store_result(conn); if (res && mysql_num_rows(res) > 0) { mysql_free_result(res); ShowMessageBox(L"错误", L"员工ID已存在"); return; } mysql_free_result(res); S_input(emp.name, 19, L"输入员工姓名:"); emp.age = Num_input(L"输入员工年龄:"); S_input(emp.position, 19, L"输入员工岗位:"); emp.salary = Float_input(L"输入员工工资:"); S_input(emp.username, 19, L"输入用户名:"); S_input(emp.password, 19, L"输入密码:"); // 插入数据库 sprintf_s(query, "INSERT INTO employees VALUES (%d, '%s', %d, '%s', %.2f, '%s', '%s')", emp.id, emp.name, emp.age, emp.position, emp.salary, emp.username, emp.password); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"员工添加失败"); return; } saveflag = 1; ShowMessageBox(L"成功", L"员工添加成功!"); } // 仓库进货 void WarehousePurchase(int employee_id) { PurchaseRecord pr; pr.id = time(NULL); // 使用时间作为唯一ID pr.med_id = Num_input(L"输入药品编号:"); // 检查药品是否存在 char query[256]; sprintf_s(query, "SELECT name FROM medicines WHERE id = %d", pr.med_id); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return; } MYSQL_RES* res = mysql_store_result(conn); if (!res || mysql_num_rows(res) == 0) { mysql_free_result(res); ShowMessageBox(L"错误", L"药品不存在"); return; } MYSQL_ROW row = mysql_fetch_row(res); strcpy_s(pr.med_name, row[0]); mysql_free_result(res); pr.quantity = Num_input(L"输入进货数量:"); pr.price = Float_input(L"输入进货价格:"); pr.employee_id = employee_id; // 获取当前日期 time_t now = time(0); struct tm tstruct; localtime_s(&tstruct, &now); strftime(pr.date, sizeof(pr.date), "%Y-%m-%d", &tstruct); // 开始事务 mysql_autocommit(conn, 0); // 更新库存 sprintf_s(query, "UPDATE medicines SET warehouse_qty = warehouse_qty + %d WHERE id = %d", pr.quantity, pr.med_id); if (mysql_query(conn, query)) { mysql_rollback(conn); mysql_autocommit(conn, 1); ShowMessageBox(L"错误", L"库存更新失败"); return; } // 插入进货记录 sprintf_s(query, "INSERT INTO purchases VALUES (%d, %d, '%s', '%s', %d, %d, %.2f)", pr.id, pr.med_id, pr.med_name, pr.date, pr.employee_id, pr.quantity, pr.price); if (mysql_query(conn, query)) { mysql_rollback(conn); mysql_autocommit(conn, 1); ShowMessageBox(L"错误", L"进货记录添加失败"); return; } // 提交事务 mysql_commit(conn); mysql_autocommit(conn, 1); saveflag = 1; ShowMessageBox(L"成功", L"进货记录添加成功!"); } // 药房销售 void PharmacySale(int employee_id) { SalesRecord sr; sr.id = time(NULL); // 使用时间作为唯一ID sr.med_id = Num_input(L"输入药品编号:"); // 检查药品是否存在 char query[256]; sprintf_s(query, "SELECT name, price_out, pharmacy_qty FROM medicines WHERE id = %d", sr.med_id); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return; } MYSQL_RES* res = mysql_store_result(conn); if (!res || mysql_num_rows(res) == 0) { mysql_free_result(res); ShowMessageBox(L"错误", L"药品不存在"); return; } MYSQL_ROW row = mysql_fetch_row(res); strcpy_s(sr.med_name, row[0]); float price_out = atof(row[1]); int pharmacy_qty = atoi(row[2]); mysql_free_result(res); sr.quantity = Num_input(L"输入销售数量:"); if (sr.quantity > pharmacy_qty) { ShowMessageBox(L"错误", L"药房库存不足"); return; } sr.price = price_out; sr.total = sr.quantity * sr.price; sr.employee_id = employee_id; // 获取当前日期 time_t now = time(0); struct tm tstruct; localtime_s(&tstruct, &now); strftime(sr.date, sizeof(sr.date), "%Y-%m-%d", &tstruct); // 开始事务 mysql_autocommit(conn, 0); // 更新库存 sprintf_s(query, "UPDATE medicines SET pharmacy_qty = pharmacy_qty - %d WHERE id = %d", sr.quantity, sr.med_id); if (mysql_query(conn, query)) { mysql_rollback(conn); mysql_autocommit(conn, 1); ShowMessageBox(L"错误", L"库存更新失败"); return; } // 插入销售记录 sprintf_s(query, "INSERT INTO sales VALUES (%d, %d, '%s', '%s', %d, %d, %.2f, %.2f)", sr.id, sr.med_id, sr.med_name, sr.date, sr.employee_id, sr.quantity, sr.price, sr.total); if (mysql_query(conn, query)) { mysql_rollback(conn); mysql_autocommit(conn, 1); ShowMessageBox(L"错误", L"销售记录添加失败"); return; } // 提交事务 mysql_commit(conn); mysql_autocommit(conn, 1); saveflag = 1; wchar_t msg[100]; swprintf_s(msg, L"销售成功!总金额:%.2f", sr.total); ShowMessageBox(L"成功", msg); } // 药房申请补货 void PharmacyReplenish(int employee_id) { Replenishment rep; rep.id = time(NULL); // 使用时间作为唯一ID rep.med_id = Num_input(L"输入药品编号:"); // 检查药品是否存在 char query[256]; sprintf_s(query, "SELECT name FROM medicines WHERE id = %d", rep.med_id); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return; } MYSQL_RES* res = mysql_store_result(conn); if (!res || mysql_num_rows(res) == 0) { mysql_free_result(res); ShowMessageBox(L"错误", L"药品不存在"); return; } MYSQL_ROW row = mysql_fetch_row(res); strcpy_s(rep.med_name, row[0]); mysql_free_result(res); rep.quantity = Num_input(L"输入申请数量:"); strcpy_s(rep.status, "待处理"); // 插入补货申请 sprintf_s(query, "INSERT INTO replenishments VALUES (%d, %d, '%s', %d, '%s')", rep.id, rep.med_id, rep.med_name, rep.quantity, rep.status); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"补货申请提交失败"); return; } saveflag = 1; ShowMessageBox(L"成功", L"补货申请已提交!"); } // 仓库处理补货 void WarehouseReplenish(int employee_id) { int rep_id = Num_input(L"输入补货申请ID:"); // 查找补货申请 char query[256]; sprintf_s(query, "SELECT med_id, med_name, quantity, status FROM replenishments WHERE id = %d", rep_id); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return; } MYSQL_RES* res = mysql_store_result(conn); if (!res || mysql_num_rows(res) == 0) { mysql_free_result(res); ShowMessageBox(L"错误", L"未找到补货申请"); return; } MYSQL_ROW row = mysql_fetch_row(res); int med_id = atoi(row[0]); char med_name[50]; strcpy_s(med_name, row[1]); int quantity = atoi(row[2]); char status[20]; strcpy_s(status, row[3]); mysql_free_result(res); if (strcmp(status, "已完成") == 0) { ShowMessageBox(L"提示", L"该申请已完成"); return; } // 检查药品库存 sprintf_s(query, "SELECT warehouse_qty FROM medicines WHERE id = %d", med_id); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return; } res = mysql_store_result(conn); if (!res || mysql_num_rows(res) == 0) { mysql_free_result(res); ShowMessageBox(L"错误", L"药品不存在"); return; } row = mysql_fetch_row(res); int warehouse_qty = atoi(row[0]); mysql_free_result(res); // 开始事务 mysql_autocommit(conn, 0); if (warehouse_qty < quantity) { // 更新补货申请状态 sprintf_s(query, "UPDATE replenishments SET status = '库存不足' WHERE id = %d", rep_id); if (mysql_query(conn, query)) { mysql_rollback(conn); mysql_autocommit(conn, 1); ShowMessageBox(L"错误", L"状态更新失败"); return; } mysql_commit(conn); mysql_autocommit(conn, 1); ShowMessageBox(L"提示", L"仓库库存不足"); } else { // 更新库存 sprintf_s(query, "UPDATE medicines SET warehouse_qty = warehouse_qty - %d, pharmacy_qty = pharmacy_qty + %d WHERE id = %d", quantity, quantity, med_id); if (mysql_query(conn, query)) { mysql_rollback(conn); mysql_autocommit(conn, 1); ShowMessageBox(L"错误", L"库存更新失败"); return; } // 更新补货申请状态 sprintf_s(query, "UPDATE replenishments SET status = '已完成' WHERE id = %d", rep_id); if (mysql_query(conn, query)) { mysql_rollback(conn); mysql_autocommit(conn, 1); ShowMessageBox(L"错误", L"状态更新失败"); return; } mysql_commit(conn); mysql_autocommit(conn, 1); ShowMessageBox(L"成功", L"补货已完成"); } saveflag = 1; } // 调整员工工资 void AdjustSalary() { int emp_id = Num_input(L"输入员工ID:"); float new_salary = Float_input(L"输入新工资:"); char query[256]; sprintf_s(query, "UPDATE employees SET salary = %.2f WHERE id = %d", new_salary, emp_id); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"工资更新失败"); return; } if (mysql_affected_rows(conn) == 0) { ShowMessageBox(L"错误", L"未找到员工"); return; } saveflag = 1; ShowMessageBox(L"成功", L"工资调整成功"); } // 调整员工岗位 void AdjustPosition() { int emp_id = Num_input(L"输入员工ID:"); char new_position[20]; S_input(new_position, 19, L"输入新岗位:"); char query[256]; sprintf_s(query, "UPDATE employees SET position = '%s' WHERE id = %d", new_position, emp_id); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"岗位更新失败"); return; } if (mysql_affected_rows(conn) == 0) { ShowMessageBox(L"错误", L"未找到员工"); return; } saveflag = 1; ShowMessageBox(L"成功", L"岗位调整成功"); } // 解雇员工 void FireEmployee() { int emp_id = Num_input(L"输入员工ID:"); char query[256]; sprintf_s(query, "DELETE FROM employees WHERE id = %d", emp_id); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"员工删除失败"); return; } if (mysql_affected_rows(conn) == 0) { ShowMessageBox(L"错误", L"未找到员工"); return; } saveflag = 1; ShowMessageBox(L"成功", L"员工解雇成功"); } // 显示药品库存 void DisplayMedicines(bool isWarehouse) { char query[256]; sprintf_s(query, "SELECT id, name, %s, price_in, price_out FROM medicines", isWarehouse ? "warehouse_qty" : "pharmacy_qty"); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return; } MYSQL_RES* res = mysql_store_result(conn); if (!res || mysql_num_rows(res) == 0) { mysql_free_result(res); ShowMessageBox(L"提示", L"没有药品信息"); return; } int num_rows = mysql_num_rows(res); // 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), isWarehouse ? L"仓库药品库存" : L"药房药品库存"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, isWarehouse ? L"仓库药品库存" : L"药房药品库存"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"药品ID", L"药品名称", L"库存数量", L"进价", L"售价" }; int colWidths[] = { 100, 200, 150, 150, 150 }; int x = 20; for (int i = 0; i < 5; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制药品信息 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; // 跳过滚动位置 for (int i = 0; i < scrollY; i++) { mysql_fetch_row(res); } MYSQL_ROW row; while ((row = mysql_fetch_row(res)) && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 获取数据 wchar_t wid[20]; swprintf_s(wid, L"%s", row[0]); wchar_t* wname = MBCS2Wide(row[1]); wchar_t wqty[20]; swprintf_s(wqty, L"%s", row[2]); wchar_t wprice_in[20]; swprintf_s(wprice_in, L"%.2f", atof(row[3])); wchar_t wprice_out[20]; swprintf_s(wprice_out, L"%.2f", atof(row[4])); // 绘制单元格 x = 20; outtextxy(x, y + 7, wid); // 药品ID x += 110; outtextxy(x, y + 7, wname); // 药品名称 x += 210; outtextxy(x, y + 7, wqty); // 库存数量 x += 160; outtextxy(x, y + 7, wprice_in); // 进价 x += 160; outtextxy(x, y + 7, wprice_out); // 售价 // 释放内存 delete[] wname; y += rowHeight; count++; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (num_rows > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); mysql_free_result(res); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 0; } } else if (num_rows > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (num_rows > visibleRows && CheckButtonHover(&btnDown, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY < num_rows - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (num_rows > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice(); } // 显示员工信息 void DisplayEmployees() { const char* query = "SELECT id, name, age, position, salary FROM employees"; if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return; } MYSQL_RES* res = mysql_store_result(conn); if (!res || mysql_num_rows(res) == 0) { mysql_free_result(res); ShowMessageBox(L"提示", L"没有员工信息"); return; } int num_rows = mysql_num_rows(res); // 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), L"员工信息"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, L"员工信息"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"员工ID", L"姓名", L"年龄", L"岗位", L"工资" }; int colWidths[] = { 100, 150, 100, 150, 150 }; int x = 20; for (int i = 0; i < 5; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制员工信息 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; // 跳过滚动位置 for (int i = 0; i < scrollY; i++) { mysql_fetch_row(res); } MYSQL_ROW row; while ((row = mysql_fetch_row(res)) && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 获取数据 wchar_t wid[20]; swprintf_s(wid, L"%s", row[0]); wchar_t* wname = MBCS2Wide(row[1]); wchar_t wage[20]; swprintf_s(wage, L"%s", row[2]); wchar_t* wposition = MBCS2Wide(row[3]); wchar_t wsalary[20]; swprintf_s(wsalary, L"%.2f", atof(row[4])); // 绘制单元格 x = 20; outtextxy(x, y + 7, wid); // 员工ID x += 110; outtextxy(x, y + 7, wname); // 姓名 x += 160; outtextxy(x, y + 7, wage); // 年龄 x += 110; outtextxy(x, y + 7, wposition); // 岗位 x += 160; outtextxy(x, y + 7, wsalary); // 工资 // 释放内存 delete[] wname; delete[] wposition; y += rowHeight; count++; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (num_rows > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); mysql_free_result(res); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 0; } } else if (num_rows > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (num_rows > visibleRows && CheckButtonHover(&btnDown, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY < num_rows - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (num_rows > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice(); } // 显示销售记录 void DisplaySalesRecords() { const char* query = "SELECT id, med_name, quantity, price, total, date FROM sales"; if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return; } MYSQL_RES* res = mysql_store_result(conn); if (!res || mysql_num_rows(res) == 0) { mysql_free_result(res); ShowMessageBox(L"提示", L"没有销售记录"); return; } int num_rows = mysql_num_rows(res); // 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), L"销售记录"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, L"销售记录"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"记录ID", L"药品名称", L"数量", L"单价", L"总价", L"日期" }; int colWidths[] = { 150, 200, 100, 100, 100, 150 }; int x = 20; for (int i = 0; i < 6; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制销售记录 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; // 跳过滚动位置 for (int i = 0; i < scrollY; i++) { mysql_fetch_row(res); } MYSQL_ROW row; while ((row = mysql_fetch_row(res)) && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 获取数据 wchar_t wid[20]; swprintf_s(wid, L"%s", row[0]); wchar_t* wname = MBCS2Wide(row[1]); wchar_t wqty[20]; swprintf_s(wqty, L"%s", row[2]); wchar_t wprice[20]; swprintf_s(wprice, L"%.2f", atof(row[3])); wchar_t wtotal[20]; swprintf_s(wtotal, L"%.2f", atof(row[4])); wchar_t* wdate = MBCS2Wide(row[5]); // 绘制单元格 x = 20; outtextxy(x, y + 7, wid); // 记录ID x += 160; outtextxy(x, y + 7, wname); // 药品名称 x += 210; outtextxy(x, y + 7, wqty); // 数量 x += 110; outtextxy(x, y + 7, wprice); // 单价 x += 110; outtextxy(x, y + 7, wtotal); // 总价 x += 110; outtextxy(x, y + 7, wdate); // 日期 // 释放内存 delete[] wname; delete[] wdate; y += rowHeight; count++; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (num_rows > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); mysql_free_result(res); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 0; } } else if (num_rows > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (num_rows > visibleRows && CheckButtonHover(&btnDown, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY < num_rows - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (num_rows > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice(); } // 显示补货申请 void DisplayReplenishments() { const char* query = "SELECT id, med_name, quantity, status FROM replenishments"; if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return; } MYSQL_RES* res = mysql_store_result(conn); if (!res || mysql_num_rows(res) == 0) { mysql_free_result(res); ShowMessageBox(L"提示", L"没有补货申请"); return; } int num_rows = mysql_num_rows(res); // 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), L"补货申请"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, L"补货申请"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"申请ID", L"药品名称", L"申请数量", L"状态" }; int colWidths[] = { 150, 300, 150, 200 }; int x = 20; for (int i = 0; i < 4; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制补货申请 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; // 跳过滚动位置 for (int i = 0; i < scrollY; i++) { mysql_fetch_row(res); } MYSQL_ROW row; while ((row = mysql_fetch_row(res)) && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 获取数据 wchar_t wid[20]; swprintf_s(wid, L"%s", row[0]); wchar_t* wname = MBCS2Wide(row[1]); wchar_t wqty[20]; swprintf_s(wqty, L"%s", row[2]); wchar_t* wstatus = MBCS2Wide(row[3]); // 绘制单元格 x = 20; outtextxy(x, y + 7, wid); // 申请ID x += 160; outtextxy(x, y + 7, wname); // 药品名称 x += 310; outtextxy(x, y + 7, wqty); // 申请数量 x += 160; outtextxy(x, y + 7, wstatus); // 状态 // 释放内存 delete[] wname; delete[] wstatus; y += rowHeight; count++; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (num_rows > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); mysql_free_result(res); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 极狐 scrollY = 0; } } else if (num_rows > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (num_rows > visibleRows && CheckButtonHover(&btnDown, msg极狐 if (msg.uMsg == WM_LBUTTONDOWN && scrollY < num_rows - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (num_rows > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice(); } // 计算盈利 float CalculateProfit() { float profit = 0; const char* query = "SELECT s.quantity, s.price, m.price_in " "FROM sales s " "JOIN medicines m ON s.med_id = m.id"; if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); return 0.0f; } MYSQL_RES* res = mysql_store_result(conn); if (!res) { return 0.0f; } MYSQL_ROW row; while ((row = mysql_fetch_row(res))) { int quantity = atoi(row[0]); float price_out = atof(row[1]); float price_in = atof(row[2]); profit += (price_out - price_in) * quantity; } mysql_free_result(res); return profit; } // 药房工作人员菜单 void PharmacyMenu(int employee_id) { Button btnStock, btnSale, btnReplenish, btnBack, btnExit; InitButton(&btnStock, width / 2 - 150, 180, 300, 50, L"查看药房库存"); InitButton(&btnSale, width / 极狐 InitButton(&btnSale, width / 2 - 150, 250, 300, 50, L"销售药品"); InitButton(&btnReplenish, width / 2 - 150, 320, 300, 50, L"申请补货"); InitButton(&btnBack, width / 2 - 150, 390, 300, 50, L"返回主菜单"); InitButton(&btnExit, width / 2 - 150, 460, 300, 50, L"退出系统"); BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 100); settextcolor(TITLE_COLOR); settextstyle(28, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"药房工作人员") / 2, 30, L"药房工作人员"); // 绘制按钮 DrawButton(&btnStock); DrawButton(&btnSale); DrawButton(&btnReplenish); DrawButton(&btnBack); DrawButton(&btnExit); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnStock, msg.x, msg.y); CheckButtonHover(&btnSale, msg.x, msg.y); CheckButtonHover(&btnReplenish, msg.x, msg.y); CheckButtonHover(&btnBack, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnStock.hover) DisplayMedicines(false); else if (btnSale.hover) PharmacySale(employee_id); else if (btnReplenish.hover) PharmacyReplenish(employee_id); else if (btnBack.hover) running = false; else if (btnExit.hover) exit(0); } } Sleep(10); } EndBatchDraw(); } // 仓库工作人员菜单 void WarehouseMenu(int employee_id) { Button btnStock, btnPurchase, btnReplenish, btnBack, btnExit; InitButton(&btnStock, width / 2 - 150, 180, 300, 50, L"查看仓库库存"); InitButton(&btnPurchase, width / 2 - 150, 250, 300, 50, L"仓库进货"); InitButton(&btnReplenish, width / 2 - 150, 320, 300, 50, L"处理补货申请"); InitButton(&btnBack, width / 2 - 150, 390, 300, 50, L"返回主菜单"); InitButton(&btnExit, width / 2 - 150, 460, 300, 50, L"退出系统"); BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题背景 setfillcolor(HEAD极狐 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 100); settextcolor(TITLE_COLOR); settextstyle(28, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"仓库工作人员") / 2, 30, L"仓库工作人员"); // 绘制按钮 DrawButton(&btnStock); DrawButton(&btnPurchase); DrawButton(&btnReplenish); DrawButton(&btnBack); DrawButton(&btnExit); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnStock, msg.x, msg.y); CheckButtonHover(&btnPurchase, msg.x, msg.y); CheckButtonHover(&btnReplenish, msg.x, msg.y); CheckButtonHover(&btnBack, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnStock.hover) DisplayMedicines(true); else if (btnPurchase.hover) WarehousePurchase(employee_id); else if (btnReplenish.hover) WarehouseReplenish(employee_id); else if (btnBack.hover) running = false; else if (btnExit.hover) exit(0); } } Sleep(10); } EndBatchDraw(); } // 人事管理菜单 void HRMenu() { Button btnAddEmp, btnAdjustSalary, btnAdjustPos, btnFireEmp, btnViewEmp; Button btnSales, btnProfit, btnBack, btnExit; InitButton(&btnAddEmp, 50, 150, 200, 45, L"添加员工"); InitButton(&btnAdjustSalary, 50, 210, 200, 45, L"调整工资"); InitButton(&btnAdjustPos, 50, 270, 200, 45, L"调整岗位"); InitButton(&btnFireEmp, 50, 330, 200, 45, L"解雇员工"); InitButton(&btnViewEmp, 50, 390, 200, 45, L"查看员工"); InitButton(&btnSales, 280, 150, 200, 45, L"销售记录"); InitButton(&btnProfit, 280, 210, 200, 45, L"查看盈利"); InitButton(&btnBack, 280, 330, 200, 45, L"返回主菜单"); InitButton(&btnExit, 280, 390, 200, 45, L"退出系统"); BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 100); settextcolor(TITLE_COLOR); settextstyle(28, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"人事管理") / 2, 30, L"人事管理"); // 绘制按钮 DrawButton(&btnAddEmp); DrawButton(&btnAdjustSalary); DrawButton(&btnAdjustPos); DrawButton(&btnFireEmp); DrawButton(&btnViewEmp); DrawButton(&btnSales); DrawButton(&btnProfit); DrawButton(&btnBack); DrawButton(&btnExit); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnAddEmp, msg.x, msg.y); CheckButtonHover(&btnAdjustSalary, msg.x, msg.y); CheckButtonHover(&btnAdjustPos, msg.x, msg.y); CheckButtonHover(&btnFireEmp, msg.x, msg.y); CheckButtonHover(&btnViewEmp, msg.x, msg.y); CheckButtonHover(&btnSales, msg.x, msg.y); CheckButtonHover(&btnProfit, msg.x, msg.y); CheckButtonHover(&btnBack, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnAddEmp.hover) AddEmployee(); else if (btnAdjustSalary.hover) AdjustSalary(); else if (btnAdjustPos.hover) AdjustPosition(); else if (btnFireEmp.hover) FireEmployee(); else if (btnView极狐 else if (btnViewEmp.hover) DisplayEmployees(); else if (btnSales.hover) DisplaySalesRecords(); else if (btnProfit.hover) { float profit = CalculateProfit(); wchar_t msg[100]; swprintf_s(msg, L"总盈利:%.2f", profit); ShowMessageBox(L"盈利情况", msg); } else if (btnBack.hover) running = false; else if (btnExit.hover) exit(0); } } Sleep(10); } EndBatchDraw(); } // 用户登录 void UserLogin() { char username[20]; char password[20]; int employee_id = -1; while (1) { S_input(username, 19, L"输入用户名:"); S_input(password, 19, L"输入密码:"); char query[256]; sprintf_s(query, "SELECT id, name, position FROM employees WHERE username = '%s' AND password = '%s'", username, password); if (mysql_query(conn, query)) { ShowMessageBox(L"错误", L"数据库查询失败"); continue; } MYSQL_RES* res = mysql_store_result(conn); if (!res || mysql_num_rows(res) == 0) { mysql_free_result(res); ShowMessageBox(L"登录失败", L"用户名或密码错误"); continue; } MYSQL_ROW row = mysql_fetch_row(res); employee_id = atoi(row[0]); char name[20]; strcpy_s(name, row[1]); char position[20]; strcpy_s(position, row[2]); mysql_free_result(res); // 确定用户类型 if (strcmp(position, "药房") == 0) { current_user_type = 1; } else if (strcmp(position, "仓库") == 0) { current_user_type = 2; } else if (strcmp(position, "人事") == 0) { current_user_type = 3; } else { current_user_type = 0; } wchar_t welcome[100]; wchar_t* wname = MBCS2Wide(name); wchar_t* wposition = MBCS2Wide(position); swprintf_s(welcome, L"欢迎 %s (%s)", wname, wposition); ShowMessageBox(L"登录成功", welcome); // 释放内存 delete[] wname; delete[] wposition; // 进入对应菜单 if (current_user_type == 1) { PharmacyMenu(employee_id); } else if (current_user_type == 2) { WarehouseMenu(employee_id); } else if (current_user_type == 3) { HRMenu(); } return; } } // 主菜单 void MainMenu() { Button btnLogin, btnAddMed, btnAddEmp, btnViewRep, btnSave, btnExit; InitButton(&btnLogin, width / 2 - 150, 180, 300, 60, L"用户登录"); InitButton(&btnAddMed, width / 2 - 150, 260, 140, 60, L"添加药品"); InitButton(&btnAddEmp, width / 2 + 10, 260, 140, 60, L"添加员工"); InitButton(&btnViewRep, width / 2 - 150, 340, 140, 60, L"补货申请"); InitButton(&btnSave, width / 2 + 10, 340, 140, 60, L"保存数据"); InitButton(&btnExit, width / 2 - 150, 420, 300, 60, L"退出系统"); BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题 settextcolor(TITLE_COLOR); settextstyle(36, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"药品仓库管理系统") / 2, 60, L"药品仓库管理系统"); settextstyle(18, 0, _T("微软雅黑")); settextcolor(RGB(100, 100, 100)); outtextxy(width / 2 - textwidth(L"高效管理药品库存") / 2, 120, L"高效管理药品库存"); // 绘制按钮 DrawButton(&btnLogin); DrawButton(&btnAddMed); DrawButton(&btnAddEmp); DrawButton(&btnViewRep); DrawButton(&btnSave); DrawButton(&btnExit); // 绘制底部信息 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(120, 120, 120)); outtextxy(width / 2 - textwidth(L"© 2025 药品仓库管理系统") / 2, height - 30, L"© 2025 药品仓库管理系统"); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnLogin, msg.x, msg.y); CheckButtonHover(&btnAddMed, msg.x, msg.y); CheckButtonHover(&btnAddEmp, msg.x, msg.y); CheckButtonHover(&btnViewRep, msg.x, msg.y); CheckButtonHover(&btnSave, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnLogin.hover) UserLogin(); else if (btnAddMed.hover) AddMedicine(); else if (btnAddEmp.hover) AddEmployee(); else if (btnViewRep.hover) DisplayReplenishments(); else if (btnSave.hover) { // 数据库自动保存,无需额外操作 ShowMessageBox(L"提示", L"数据已实时保存到数据库"); } else if (btnExit.hover) { running = false; } } } Sleep(10); } EndBatchDraw(); } int main() { // 设置本地化环境以支持中文 setlocale(LC_ALL, "chs"); // 初始化数据库 InitDatabase(); CreateTables(); // 初始化图形界面 initgraph(width, height); SetWindowText(GetHWnd(), L"药品仓库管理系统"); // 显示主菜单 while (1) { MainMenu(); } // 关闭数据库连接 mysql_close(conn); // 关闭图形界面 closegraph(); return 0; } ``` ### 主要修改内容: 1. **数据库集成**: - 添加MySQL头文件和库链接 - 实现数据库连接初始化函数 - 创建所有必要的数据库表 2. **数据结构替换**: - 移除所有链表结构(MedList, EmpList等) - 使用SQL查询替代链表操作 - 添加事务处理确保数据一致性 3. **功能函数重**: - `AddMedicine()`:使用INSERT语句 - `WarehousePurchase()`:使用事务处理库存更新 - `DisplayMedicines()`:使用SELECT查询并分页显示 - 所有CRUD操作改为数据库操作 4. **错误处理**: - 添加详细的MySQL错误处理 - 事务回滚机制确保数据完整性 - 资源释放(mysql_free_result) 5. **用户认证**: - 登录验证改为数据库查询 - 用户权限基于数据库中的岗位字段 6. **界面优化**: - 保持原图形界面不变 - 数据库操作无缝集成到现有UI中 ### 使用说明: 1. 安装MySQL服务器并创建数据库 2. 修改数据库连接信息(DB_HOST, DB_USER等) 3. 编译时链接MySQL客户端库 4. 系统会自动创建所需表格 5. 所有数据操作实时保存到数据库 此版本完全使用数据库替代了原有的文件存储和链表结构,实现了数据的持久化存储和高效访问。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迂者-贺利坚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值