(管理员)和(登录状态)是使用相应功能的条件。
// 文献信息
typedef struct Literature {
int literatureNumber; // 文献编号
char title[MAX_LEN_TITLE]; // 文献名
char author[MAX_LEN_AUTHOR]; // 著者
int currentStock; // 现存量
int totalStock; // 总库存
int appointNum; // 已预约数量
int borrowNum; // 已借出数量
char borIdNumber[50][50]; // 证件号,假设最大长度为50
char appIdNumber[50][50]; // 证件号,假设最大长度为50
char returnDate[50][50]; // 归还日期,假设最大长度为50
} Literature, *Liter;
// B树结点
typedef struct BTNode{
int keyNum; // 结点当前关键字个数
KeyType key[m + 1]; // 关键字数组,key[0]未用
struct BTNode *parent; // 双亲结点
struct BTNode *ptr[m + 1]; // 孩子结点指针数组, 0 号有使用
Liter data[m + 1]; // 数据数组,data[0]未用
} BTNode, *BTree;
// 用户信息
typedef struct {
char username[200]; // 用户名
char account[200]; // 账号
char password[200]; // 密码
} User;
这些代码过于繁琐,不在此展示。
完整代码见:SourceCode/BTree
这里的图形化借助了EasyX图形库,使用了EasyX的图形化界面实现。
// 可视化界面
void interfaces(){
int i;
short win_width,win_height;//定义窗口的宽度和高度
win_width = 600;win_height = 400;
initgraph(win_width,win_height);//初始化窗口(黑屏)
HWND hnd = GetHWnd();
SetWindowText(hnd, "文献管理系统");
setbkcolor(RGB(255,255,255));//设置背景色,原来默认黑色
cleardevice();//清屏(取决于背景色)
IMAGE background;//定义一个图片名.
loadimage(&background,"..\\bg.png",600,400,1);//从图片文件获取图像
setbkmode(TRANSPARENT);
putimage(0, 0, &background);//绘制图像到屏幕,图片左上角坐标为(0,0)
RECT R1={reg[0][0],reg[0][1],reg[0][2],reg[0][3]};
RECT R2={reg[1][0],reg[1][1],reg[1][2],reg[1][3]};
RECT R3={reg[2][0],reg[2][1],reg[2][2],reg[2][3]};
RECT R4={reg[3][0],reg[3][1],reg[3][2],reg[3][3]};
RECT R5={reg[4][0],reg[4][1],reg[4][2],reg[4][3]};
RECT R6={reg[5][0],reg[5][1],reg[5][2],reg[5][3]};
RECT R7={reg[6][0],reg[6][1],reg[6][2],reg[6][3]};
RECT R8={reg[7][0],reg[7][1],reg[7][2],reg[7][3]};
RECT R9={reg[8][0],reg[8][1],reg[8][2],reg[8][3]};
RECT R10={reg[9][0],reg[9][1],reg[9][2],reg[9][3]};
RECT R11={reg[10][0],reg[10][1],reg[10][2],reg[10][3]};
RECT R12={reg[11][0],reg[11][1],reg[11][2],reg[11][3]};
RECT R13={reg[12][0],reg[12][1],reg[12][2],reg[12][3]};
RECT R14={reg[13][0],reg[13][1],reg[13][2],reg[13][3]};
LOGFONT f;//字体样式指针
gettextstyle(&f); //获取字体样式
_tcscpy(f.lfFaceName,_T("宋体")); //设置字体为宋体
f.lfQuality = ANTIALIASED_QUALITY; // 设置输出效果为抗锯齿
settextstyle(&f); // 设置字体样式
settextcolor(GREEN); //BLACK在graphic.h头文件里面被定义为黑色的颜色常量
if(caretakers){
drawtext("入库文献",&R1,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R1内输入文字,水平居中,垂直居中,单行显示
drawtext("删除文献",&R2,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R2内输入文字,水平居中,垂直居中,单行显示
drawtext("显示B树图",&R3,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R8内输入文字,水平居中,垂直居中,单行显示
drawtext("检索文献",&R4,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R3内输入文字,水平居中,垂直居中,单行显示
drawtext("借阅文献",&R5,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R4内输入文字,水平居中,垂直居中,单行显示
drawtext("归还文献",&R6,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R5内输入文字,水平居中,垂直居中,单行显示
drawtext("搜作者文献",&R7,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R6内输入文字,水平居中,垂直居中,单行显示
drawtext("预约借阅文献",&R8,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R7内输入文字,水平居中,垂直居中,单行显示
} else{
drawtext("检索文献",&R1,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R3内输入文字,水平居中,垂直居中,单行显示
drawtext("借阅文献",&R2,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R4内输入文字,水平居中,垂直居中,单行显示
drawtext("归还文献",&R3,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R5内输入文字,水平居中,垂直居中,单行显示
drawtext("搜作者文献",&R4,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R6内输入文字,水平居中,垂直居中,单行显示
drawtext("预约借阅文献",&R5,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R7内输入文字,水平居中,垂直居中,单行显示
}
if (login){
drawtext(userName,&R12,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R12内输入文字,水平居中,垂直居中,单行显示
drawtext("退出登录",&R13,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R13内输入文字,水平居中,垂直居中,单行显示
}else{
drawtext("注册",&R10,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R10内输入文字,水平居中,垂直居中,单行显示
drawtext("登录",&R11,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R11内输入文字,水平居中,垂直居中,单行显示
drawtext("管理员登录",&R14,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R14内输入文字,水平居中,垂直居中,单行显示
}
drawtext("退出",&R9,DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R9内输入文字,水平居中,垂直居中,单行显示
setlinecolor(RED);
if(caretakers){
rectangle(reg[0][0],reg[0][1],reg[0][2],reg[0][3]);
rectangle(reg[1][0],reg[1][1],reg[1][2],reg[1][3]);
rectangle(reg[2][0],reg[2][1],reg[2][2],reg[2][3]);
rectangle(reg[3][0],reg[3][1],reg[3][2],reg[3][3]);
rectangle(reg[4][0],reg[4][1],reg[4][2],reg[4][3]);
rectangle(reg[5][0],reg[5][1],reg[5][2],reg[5][3]);
rectangle(reg[6][0],reg[6][1],reg[6][2],reg[6][3]);
rectangle(reg[7][0],reg[7][1],reg[7][2],reg[7][3]);
}else{
rectangle(reg[0][0],reg[0][1],reg[0][2],reg[0][3]);
rectangle(reg[1][0],reg[1][1],reg[1][2],reg[1][3]);
rectangle(reg[2][0],reg[2][1],reg[2][2],reg[2][3]);
rectangle(reg[3][0],reg[3][1],reg[3][2],reg[3][3]);
rectangle(reg[4][0],reg[4][1],reg[4][2],reg[4][3]);
}
if (login){
rectangle(reg[11][0],reg[11][1],reg[11][2],reg[11][3]);
rectangle(reg[12][0],reg[12][1],reg[12][2],reg[12][3]);
}else{
rectangle(reg[9][0],reg[9][1],reg[9][2],reg[9][3]);
rectangle(reg[10][0],reg[10][1],reg[10][2],reg[10][3]);
rectangle(reg[13][0],reg[13][1],reg[13][2],reg[13][3]);
}
rectangle(reg[8][0],reg[8][1],reg[8][2],reg[8][3]);
char title[] = "文献管理系统";
outtextxy(80, 10, title);
}
上述代码实现了图形化界面的绘制,其中reg
是一个二维数组,用于存储各个按钮的位置信息,login
和caretakers
是两个布尔值,用于判断当前是否登录和是否为管理员。
int reg[14][4]={{20,80,120,110},
{140,80,240,110},
{20,130,120,160},
{140,130,240,160},
{20,180,120,210},
{140,180,240,210},
{20,230,120,260},
{140,230,240,260},
{500,350,560,380},
{450,10,550,40},
{450,50,550,80},
{450,10,550,40},
{450,50,550,80},
{450,90,550,120}};//12个按钮的二维数组
//按钮判断函数
int button_judge(int x,int y)
{
if (caretakers){
if(x>reg[0][0] && xreg[0][1] && yreg[1][0] && xreg[1][1] && yreg[2][0] && xreg[2][1] && yreg[3][0] && xreg[3][1] && yreg[4][0] && xreg[4][1] && yreg[5][0] && xreg[5][1] && yreg[6][0] && xreg[6][1] && yreg[7][0] && xreg[7][1] && yreg[0][0] && xreg[0][1] && yreg[1][0] && xreg[1][1] && yreg[2][0] && xreg[2][1] && yreg[3][0] && xreg[3][1] && yreg[4][0] && xreg[4][1] && yreg[11][0] && xreg[11][1] && yreg[12][0] && xreg[12][1] && yreg[9][0] && xreg[9][1] && yreg[10][0] && xreg[10][1] && yreg[13][0] && xreg[13][1] && yreg[8][0] && xreg[8][1] && y
上述代码中的二维数组是按钮位置的信息。
和button_judge
函数 实现了按钮的判断,返回值为按钮的编号。
(x1, y1, x2, y2) 分别为按钮的左上角和右下角的坐标。
在编写B树的代码时,为了方便调试,B树的可视化是必不可少的。
这里的可视化借助了Graphviz工具,使用了Graphviz的DOT语言来实现。
(其他树形结构也可以使用这个工具)
// 辅助函数:递归打印B树的结点
void printNode(BTree node, FILE *out) {
if (node != NULL) {
fprintf(out, "%d [label=\"", node->key[1]);
for (int i = 1; i <= node->keyNum; ++i) {
fprintf(out, "%d", node->key[i]);
if (i < node->keyNum) {
fprintf(out, ",");
}
}
fprintf(out, "\"];\n");
for (int i = 0; i <= node->keyNum; ++i) {
if (node->ptr[i] != NULL) {
fprintf(out, "%d -> %d;\n", node->key[1], node->ptr[i]->key[1]);
}
}
for (int i = 0; i <= node->keyNum; ++i) {
printNode(node->ptr[i], out);
}
}
}
// 打开文件并写入B树的DOT格式
void treePrint(BTree root) {
FILE *out = fopen("./Btree.dot", "w");
if (out == NULL) {
perror("Error opening file");
exit(EXIT_FAILURE);
}
fprintf(out, "digraph {\nnode[shape=record];\n");
printNode(root, out);
fprintf(out, "}\n");
fclose(out);
// 执行 dot 命令来生成图像
system(".\\Graphviz\\bin\\dot -Tpng ./Btree.dot -o ./Btree.png");
sprintf(mes, "在当前文件夹生成tree.png文件");
}
InputBox
(小窗口输入),MessageBoxA(弹窗提示
就可以完成简单的图形化了(当然按钮功能更能体现图形化)