不知道哪里错了,缩放前的按钮消不掉一直显示
#define _CRT_SECURE_NO_WARNINGS
#include<vector>
#include<list>
#include<iomanip>
#include<string>
#include<cmath>
#include<iostream>
#include<map>
#include<stdio.h>
#include<graphics.h>
#include<easyx.h>
#include<conio.h>
using namespace std;
class Student //学生类的定义
{
public:
string Number, Name, Class;
vector<string>time = {};
//奇数项存储开始上机时间,偶数项存储结束上机时间,例:格式为“202311051603”,即2023年11月5号十六点3分
Student(string number, string name, string _class)
{
Number = number;//学生的学号
Name = name;//学生的名字
Class = _class;//学生的班级
}
};
int DeltaTime(string time1, string time2) //计算时间差,单位为分钟,其中time2(结束上机时间)比time1(开始上机时间)要大
{
int ans;
ans = (stoi(time2.substr(8, 2)) * 60 - stoi(time1.substr(8, 2)) * 60) + (stoi(time2.substr(10, 2)) - stoi(time1.substr(10, 2)));
return ans;
}
//stoi为string字符串转换为时间的函数
//substr是字符截取函数,substr(a,b)可以理解为从第a个字符后截取b个字符
bool IsFirst(string num0, vector<Student>stu_info) //通过学号判断是否第一次上机
{
if (stu_info.size() == 0)
{
return true;//若总学生信息库中没有任何记录,则他第一个上机,必然也是第一次上机
}
else
{
for (int i = 0; i < stu_info.size(); i++)
{
if (stu_info[i].Number == num0)
{
return false;//遍历学号查找他是否有上机史
}
}
return true;
}
}
int Cost(string num0, vector<Student>stu_info, int order1) //通过学号计算上机费用
{
int cost = 0;//费用
int bill = 0.1;//每分钟0.1元
for (int i = 0; i < stu_info[order1].time.size(); i + 2)//遍历所有结束上机时间
{
cost += DeltaTime(stu_info[order1].time[i + 1], stu_info[order1].time[i]) * bill;
}
return cost;
}
//按钮类的定义
class Button
{
public:
int x, y; //按钮绘制时左上角像素的横纵坐标
int width, height; //按钮的长宽
bool isMouseOver; //鼠标是否处于按钮上
wstring text; //按钮上的文本内容
int nextpage;//点击该按钮后,应转入的下一个页面的序号,-1表示该按钮无需跳转
float scale;//缩放比例
Button(int x0, int y0, int width0, int height0, wstring& text0, int nextpage0 = -1)
{ //构造函数初始化各种信息
x = x0, y = y0, width = width0, height = height0, text = text0, isMouseOver = false, scale=1.0f, nextpage = nextpage0;
}
void checkMouseOver(int mouseX, int mouseY) //检查鼠标指针是否处于按钮上
{
isMouseOver = (mouseX >= x && mouseY <= x + width && mouseY >= y && mouseY <= y + height);
if (isMouseOver)
{
scale = 0.9f;//鼠标在按钮上时缩放
}
else
{
scale = 1.0f;//否则复原
}
}
void draw() //绘制按钮形状及添加文字
{
BeginBatchDraw();
int scaledWidth = width * scale; //缩放后的宽
int scaledHeight = height * scale;//缩放后的长
int scaledX = x + (width - scaledWidth) / 2; //缩放后的横坐标
int scaledY = y + (height - scaledHeight) / 2; //缩放后的纵坐标
if (isMouseOver) //如果鼠标在按钮上
{
setlinecolor(RGB(255, 143, 220));//粉色
setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, 3, NULL, 0);//边框
setfillcolor(RGB(255, 212, 241));
}
else //如果鼠标不在按钮上
{
setlinecolor(RGB(66, 222, 165));//青色
setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, 3, NULL, 0);//边框
setfillcolor(RGB(217, 255, 241));
}
fillrectangle(scaledX, scaledY, scaledX + scaledWidth, scaledY + scaledHeight);
LOGFONT buttonText;//设置字体
gettextstyle(&buttonText);
buttonText.lfHeight = 30;//字高
buttonText.lfWeight = 0;//字宽,0为系统自适应宽度
buttonText.lfQuality = ANTIALIASED_QUALITY;//抗锯齿效果
_tcscpy(buttonText.lfFaceName, _T("幼圆"));//字体
settextstyle(&buttonText);
setbkmode(TRANSPARENT);//透明背景
settextcolor(BLACK);//字色
int textX = scaledX + (scaledWidth - textwidth(text.c_str())) / 2; //字体居中
int textY = scaledY + (scaledHeight - textheight(_T("幼圆"))) / 2;
outtextxy(textX, textY, text.c_str());//c_str是string字符串转为char*的函数
EndBatchDraw();
}
};
//弹出InputBox输入框的按钮的定义
class InputButton
{
public:
int x, y; //按钮绘制时左上角像素的坐标
int width, height; //按钮的长宽
bool isMouseOver; //鼠标是否处于按钮上
wstring text; //按钮上的文本内容
const int nextpage = -1;//点击该按钮后,应转入的下一个页面的序号,-1表示该按钮无需跳转
wchar_t info[100];//定义字符串缓冲区,存储输入的文本,wchar_t是宽字符类型,所能表示的字符数远超char
LPCTSTR tip;//对话框中的提示文本
int function_order;//该对话框在内置信息处理函数中的设定的索引值
float scale;//缩放比例
InputButton(int x0, int y0, int width0, int height0, wstring& text0) //构造函数,基本初始化
{
x = x0, y = y0, width = width0, height = height0, text = text0, scale = 1.0f, isMouseOver = false;
}
void checkMouseOver(int mouseX, int mouseY) //检查鼠标是否处于按钮上
{
isMouseOver = (mouseX >= x && mouseY <= x + width && mouseY >= y && mouseY <= y + height);
if (isMouseOver)
{
scale = 0.9f;//鼠标在按钮上时缩放
}
else
{
scale = 1.0f;//否则复原
}
}
void draw() //绘制按钮形状及添加文字
{
BeginBatchDraw();
int scaledWidth = width * scale; //缩放后的宽
int scaledHeight = height * scale;//缩放后的长
int scaledX = x + (width - scaledWidth) / 2; //缩放后的横坐标
int scaledY = y + (height - scaledHeight) / 2; //缩放后的纵坐标
if (isMouseOver)
{
setlinecolor(RGB(255, 143, 220));//粉色
setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, 3, NULL, 0);//边框
setfillcolor(RGB(255, 212, 241));
}
else
{
setlinecolor(RGB(66, 222, 165));//青色
setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, 3, NULL, 0);//边框
setfillcolor(RGB(217, 255, 241));
}
fillrectangle(scaledX, scaledY, scaledX + scaledWidth, scaledY + scaledHeight);
LOGFONT buttonText;//设置字体
gettextstyle(&buttonText);
buttonText.lfHeight = 30;//字高
buttonText.lfWeight = 0;//字宽,0为系统自适应宽度
buttonText.lfQuality = ANTIALIASED_QUALITY;//抗锯齿效果
_tcscpy(buttonText.lfFaceName, _T("幼圆"));//字体
settextstyle(&buttonText);
setbkmode(TRANSPARENT);//透明背景
settextcolor(BLACK);//字色
int textX = scaledX + (scaledWidth - textwidth(text.c_str())) / 2; //字体居中
int textY = scaledY + (scaledHeight - textheight(_T("幼圆"))) / 2;
outtextxy(textX, textY, text.c_str());//c_str是string字符串转为char*的函数
EndBatchDraw();
}
void input_info()//输入信息函数
{
InputBox(info, 100, tip);//输入文本对话框窗口
}
};
class textBox //定义仅用于显示文字的文本框
{
public:
int x, y; //绘制时左上角像素的坐标
wstring text; //文本内容
textBox(int x0, int y0, wstring text0)
{ //构造函数,初始化
x = x0, y = y0;
text = text0;
}
void draw()
{
settextcolor(WHITE);//设置文本颜色
setbkmode(TRANSPARENT);//文本背景颜色
settextstyle(45, 0, _T("幼圆"));//字体大小,字体样式
int textX = x;
int textY = y;
outtextxy(textX, textY, text.c_str());//显示文字
}
};
class Page //窗口页面的定义
{
public:
int width; //窗口宽度
int height; //窗口高度
LPCTSTR backpath;//页面背景图的路径
int Index;//该页面的序号
wstring Pagename;//页面名字
vector<Button>buttons;//该页面所具有的按钮
vector<textBox>textBoxs;//该页面所具有的文本
vector<InputButton>inputbuttons;//该页面所具有的对话框按钮
Page();//默认构造函数
Page(int width0, int height0, int Index0)
{
width = width0;
height = height0;
Index = Index0;
}
void drawbackphoto() //绘制背景函数
{
initgraph(width, height, NULL); //绘制窗口
loadimage(NULL, backpath, width, height, true); //上传背景图
}
void draw(int mousex, int mousey, MOUSEMSG mouse_info1) //在该页面显示时绘制按钮与文本框
{
BeginBatchDraw();
for (int i1 = 0; i1 < buttons.size(); i1++)
{
buttons[i1].draw();
buttons[i1].checkMouseOver(mousex, mousey);
}
for (int i2 = 0; i2 < textBoxs.size(); i2++)
{
textBoxs[i2].draw();
}
for (int i5 = 0; i5 < inputbuttons.size(); i5++)
{
inputbuttons[i5].draw();
inputbuttons[i5].checkMouseOver(mousex, mousey);
}
EndBatchDraw();
}
void closepages() //关闭该窗口
{
closegraph();
}
};
int main()
{
// 处理信息相关数据的初始化
vector<Student>stu_info;//stu_info用来存储学生信息
map<string, int>stu_order;//stu_order用来存储学生的信息在stu_info中的索引值,键为学生的学号,实值为该学生的信息在stu_info中的索引
// 在映射map中,前一个为键值,后一个为实值,键值作为索引对应实值,从而关联学号和记录,便于查找
int order = 0;//用来辅助stu_order的工具
string num0, name0, class0, name1, class1;// 临时存放数据的变量
string StartTime, FinishTime; // 开始时间和结束时间
string text3;
int count = 0;//记录各字符串的长度
//基本数据的初始化
vector<Page>Pages; //存储所有的页面
Pages.push_back(Page(1536, 864, 0));
Pages.push_back(Page(1536, 864, 1));
Pages.push_back(Page(1536, 864, 2));
Pages.push_back(Page(1536, 864, 3));
Pages.push_back(Page(1536, 864, 4));
Pages.push_back(Page(1536, 864, 5));
int run = 1;//检测程序是否在运行
bool need_to_turnpage = false;//是否需要跳转页面
bool need_to_turninputbox = false;//是否需要弹出对话框
int button_order;//用来记录被按下且需要跳转页面的按钮在对应页面中的序号
MOUSEMSG mouse_info;//初始化鼠标消息类mouse_info
int RunningIndex = 0;//动态记录当前的页面的序号
wstring text0; //临时存放文本
//Pages[0]代表初始界面
Pages[0].backpath = _T("D:\\图\\机房计时收费系统封面 - 副本.png");
Pages[1].backpath = _T("D:\\图\\机房计时收费系统封面 - 副本.png");
Pages[2].backpath = _T("D:\\图\\机房计时收费系统封面 - 副本.png");
Pages[3].backpath = _T("D:\\图\\机房计时收费系统封面 - 副本.png");
Pages[4].backpath = _T("D:\\图\\机房计时收费系统封面 - 副本.png");
Pages[5].backpath = _T("D:\\图\\机房计时收费系统封面 - 副本.png");
//创建首页面的按钮
text0 = _T("上传学生信息");
Pages[0].buttons.push_back(Button(700, 300, 240, 70, text0, 1));
text0 = _T("新建上机信息");
Pages[0].buttons.push_back(Button(700, 400, 240, 70, text0, 2));
text0 = _T("查询上机费用");
Pages[0].buttons.push_back(Button(700, 500, 240, 70, text0, 3));
text0 = _T("修改学生信息");
Pages[0].buttons.push_back(Button(700, 600, 240, 70, text0, 4));
text0 = _T("查询上机信息");
Pages[0].buttons.push_back(Button(700, 700, 240, 70, text0, 5));
/*
//处理其它页面的标题及初始化
text0 = _T("上传学生信息");
Pages[1].textBoxs.push_back(textBox(700, 200, text0));
text0 = _T("新建上机信息");
Pages[2].textBoxs.push_back(textBox(700, 200, text0));
text0 = _T("查询上机费用");
Pages[3].textBoxs.push_back(textBox(700, 200, text0));
text0 = _T("修改学生信息");
Pages[4].textBoxs.push_back(textBox(700, 200, text0));
text0 = _T("查询上机信息");
Pages[5].textBoxs.push_back(textBox(700, 200, text0));
*/
//为其它页面添加一个返回按钮
text0 = _T("返回首页");
Pages[1].buttons.push_back(Button(730, 600, 150, 50, text0, 0));
Pages[2].buttons.push_back(Button(730, 600, 150, 50, text0, 0));
Pages[3].buttons.push_back(Button(730, 600, 150, 50, text0, 0));
Pages[4].buttons.push_back(Button(730, 600, 150, 50, text0, 0));
Pages[5].buttons.push_back(Button(730, 600, 150, 50, text0, 0));
//进行界面1的相关初始化
text0 = _T("点击输入信息");
Pages[1].inputbuttons.push_back(InputButton(500, 400, 600, 60, text0));
Pages[1].inputbuttons[0].tip = L"请依次输入学号,姓名,班级,数据之间用空格隔开:";
Pages[1].inputbuttons[0].function_order = 1;
//进行界面2的相关初始化
text0 = _T("点击输入信息");
Pages[2].inputbuttons.push_back(InputButton(500, 400, 600, 60, text0));
Pages[2].inputbuttons[0].tip = L"请依次输入学生的学号,上机开始时间,上机结束时间";
Pages[2].inputbuttons[0].function_order = 2;
//进行界面3的相关初始化
text0 = _T("点击输入信息");
Pages[3].inputbuttons.push_back(InputButton(500, 400, 600, 60, text0));
Pages[3].inputbuttons[0].tip = L"请输入要查询的学生的学号";
Pages[3].inputbuttons[0].function_order = 3;
//进行界面4的相关初始化
text0 = _T("点击输入信息");
Pages[4].inputbuttons.push_back(InputButton(500, 400, 600, 60, text0));
Pages[4].inputbuttons[0].tip = L"请输入要修改学生的学号";
Pages[4].inputbuttons[0].function_order = 4;
//进行界面5的相关初始化
text0 = _T("点击输入信息");
Pages[5].inputbuttons.push_back(InputButton(500, 400, 600, 60, text0));
Pages[5].inputbuttons[0].tip = L"请输入要查询的学生的学号";
Pages[5].inputbuttons[0].function_order = 5;
Pages[0].drawbackphoto();//加载初始背景
while (run == 1)
{
while (run == 1)
{
mouse_info = GetMouseMsg();//获取鼠标信息
Pages[RunningIndex].draw(mouse_info.x, mouse_info.y, mouse_info);//每次执行时刷新页面绘制的东西
//检测跳转页面的相关代码
for (int i3 = 0; i3 < Pages[RunningIndex].buttons.size(); i3++) //检测是否有按钮被按下且需要跳转
{
if (Pages[RunningIndex].buttons[i3].isMouseOver == true && mouse_info.uMsg == WM_LBUTTONDOWN && Pages[RunningIndex].buttons[i3].nextpage != -1)
{ // 如果鼠标在当前页面的当前按钮上,且鼠标左键按下,且下一个页面的索引值不是-1(WM_LBUTTONDOWN是easyx库中内置的宏定义,对应一个消息类型)
need_to_turnpage = true; //需要跳转页面
button_order = i3;//记录下被按下按钮的序号
break;//跳出这次循环
}
}
if (need_to_turnpage) //如果需要跳转页面
{
Pages[RunningIndex].closepages();//关闭上一个页面
RunningIndex = Pages[RunningIndex].buttons[button_order].nextpage;//设置当前页面为下一个页面
run = 0;//跳出该循环
}
//处理需要跳出输入对话框的相关代码
for (int i6 = 0; i6 < Pages[RunningIndex].inputbuttons.size(); i6++)
{
if (Pages[RunningIndex].inputbuttons[i6].isMouseOver && mouse_info.uMsg == WM_LBUTTONDOWN)
{ // 如果鼠标在当前页面的当前按钮上,且鼠标左键按下(WM_LBUTTONDOWN是easyx库中内置的宏定义,对应一个消息类型)
need_to_turninputbox = true;//需要跳出输入对话框
button_order = i6;//记录下被按下按钮的序号
run = 0;//跳出该循环
}
}
}
//跳转页面初始化相关代码
if (need_to_turnpage == true)
{
//判断要跳转的页面,并进行背景的初始化
Pages[RunningIndex].drawbackphoto();
need_to_turnpage = false;
run = 1;
};
//处理跳出对话框,进行输入的相关代码
if (need_to_turninputbox)
{
Pages[RunningIndex].inputbuttons[button_order].input_info();
switch (Pages[RunningIndex].inputbuttons[button_order].function_order)
{
case 1://新建学生信息
count = 0;//记录各字符串的长度
for (wchar_t* i7 = Pages[RunningIndex].inputbuttons[button_order].info; *i7 != ' '; i7++)
{ //遇到空格停止遍历
num0.push_back((char)(*i7));//存储学号
count += 1;//注意字符串末尾有 "\0"
}
for (wchar_t* i7 = Pages[RunningIndex].inputbuttons[button_order].info + count + 1; *i7 != ' '; i7++)
{ //加上"\0"和空格
name0.push_back((char)(*i7));//存储姓名
count += 1;
}
for (wchar_t* i7 = Pages[RunningIndex].inputbuttons[button_order].info + count + 1; *i7 != ' '; i7++)
{
class0.push_back((char)(*i7));//存储班级
count += 1;
}
if (IsFirst(num0, stu_info))
{
stu_info.push_back(Student(num0, name0, class0));//将第一次上机的同学基本信息加进去
stu_order[num0] = order;//实值order,可以看成stu_info的长度
order += 1;
}
else
{
InputBox(NULL, 100, L"该同学已录入");
}
num0.clear(), name0.clear(), class0.clear(), count = 0;// 清空临时变量
break;
case 2://新建上机信息
count = 0;//记录各字符串的长度
for (wchar_t* i7 = Pages[RunningIndex].inputbuttons[button_order].info; *i7 != ' '; i7++)
{
num0.push_back((char)(*i7));//存储学号
count += 1;//注意字符串末尾有 "\0"
}
for (wchar_t* i7 = Pages[RunningIndex].inputbuttons[button_order].info + count + 1; *i7 != ' '; i7++)
{ //加上"\0"和空格
StartTime.push_back((char)(*i7));//临时存储开始上机时间
count += 1;
}
for (wchar_t* i7 = Pages[RunningIndex].inputbuttons[button_order].info + count + 1; *i7 != ' '; i7++)
{
FinishTime.push_back((char)(*i7));//临时存储结束上机时间
count += 1;
}
if (IsFirst(num0, stu_info))
{
InputBox(NULL, 100, L"未查找到该同学,请录入学生信息");
}
else
{
stu_info[stu_order[num0]].time.push_back(StartTime);//存储开始上机时间
stu_info[stu_order[num0]].time.push_back(FinishTime);//存储结束上机时间
}
num0.clear(), StartTime.clear(), FinishTime.clear(), count = 0;;
break;
case 3://查询上机费用
count = 0;//记录各字符串的长度
for (wchar_t* i7 = Pages[RunningIndex].inputbuttons[button_order].info; *i7 != ' '; i7++)
{
num0.push_back((char)(*i7));//存储学号
count += 1;//注意"\0"
}
if (IsFirst(num0, stu_info)) //判断有没有此学生
{
InputBox(NULL, 100, L"未查找到该同学,请录入学生信息");
}
else if (stu_info[stu_order[num0]].time.size() == 0) //判断是否有上机史
{
InputBox(NULL, 100, L"该同学未上机过");
}
else //计算费用
{
LPCTSTR text1 = L"该同学上机费用为";
text1 += Cost(num0, stu_info, stu_order[num0]);
InputBox(NULL, 100, text1);
}
num0.clear(), count = 0;// 清空临时变量
break;
case 4: //修改学生信息
count = 0;
for (wchar_t* i7 = Pages[RunningIndex].inputbuttons[button_order].info; *i7 != ' '; i7++)
{
num0.push_back((char)(*i7));
count += 1;//注意字符串末尾有 "\0"
}
if (IsFirst(num0, stu_info)) //判断有没有此学生
{
InputBox(NULL, 100, L"该同学未录入");
}
else
{
wchar_t text2[100];
InputBox(text2, 100, L"请依次输入该学生新的班级与姓名");
for (wchar_t* i7 = text2; *i7 != ' '; i7++)
{
class0.push_back((char)(*i7));//存储新的班级
count += 1;//注意字符串末尾有 "\0"
}
for (wchar_t* i7 = text2 + count + 1; *i7 != ' '; i7++)
{
name0.push_back((char)(*i7));//存储新的姓名
count += 1;//注意字符串末尾有 "\0"
}
stu_info[stu_order[num0]].Class = class0;
stu_info[stu_order[num0]].Name = name0;
}
num0.clear(), name0.clear(), count = 0;// 清空临时变量
break;
case 5://查询上机信息
count = 0;
for (wchar_t* i7 = Pages[RunningIndex].inputbuttons[button_order].info; *i7 != ' '; i7++)
{
num0.push_back((char)(*i7));
count += 1;
}
count = 0;
if (IsFirst(num0, stu_info)) //判断有没有此学生
{
InputBox(NULL, 100, L"该同学未录入");
}
else
{
for (int i2 = 0; i2 < stu_info[stu_order[num0]].time.size(); i2 += 2)
{
text3 += "该同学于" + (stu_info[stu_order[num0]].time[i2].substr(0, 4)) + "年" + stu_info[stu_order[num0]].time[i2].substr(4, 2)
+ "月" + stu_info[stu_order[num0]].time[i2].substr(6, 2) + "日" + stu_info[stu_order[num0]].time[i2].substr(8, 2)
+ "时" + stu_info[stu_order[num0]].time[i2].substr(10, 2) + "分" + "开始上机";
text3 += ',';
text3 += "该同学于" + stu_info[stu_order[num0]].time[i2 + 1].substr(0, 4) + "年" + stu_info[stu_order[num0]].time[i2 + 1].substr(4, 2)
+ "月" + stu_info[stu_order[num0]].time[i2 + 1].substr(6, 2) + "日" + stu_info[stu_order[num0]].time[i2 + 1].substr(8, 2)
+ "时" + stu_info[stu_order[num0]].time[i2 + 1].substr(10, 2) + "分" + "结束上机";
}
InputBox(NULL, 200, (LPCTSTR)text3.c_str());//显示具体上机时间
}
num0.clear(), text3.clear();// 清空临时变量
break;
}
need_to_turninputbox = false;
run = 1;
}
}
return 0;
}
这是我的效果
这是目标效果