#include "room.h"
char over = 0;/*RunSys中用于判断是否结束运行的变量,只有运行ExitSys时才更改为1*/
unsigned long ul;
int main()
{
R_type **phead;
COORD size = {SCR_COL , SCR_ROW}; /*窗口缓冲区大小*/
WORD att = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
gh_std_out = GetStdHandle(STD_OUTPUT_HANDLE);/*获取标准输出设备句柄*/
gh_std_in = GetStdHandle(STD_INPUT_HANDLE); /*获取标准输入设备句柄*/
SetConsoleTitle("房屋出租管理系统"); /*设置窗口标题*/
SetConsoleScreenBufferSize(gh_std_out , size);/*设置窗口缓冲区大小*/
SetConsoleTextAttribute(gh_std_out , att); /*设置白色前景和黑色背景*/
LoadFile(phead);
ClearWindow(); /*清屏*/
/*创建弹出窗口信息堆栈,将初始化后的屏幕窗口当作第一层弹出窗口*/
gp_scr_att = (char*)malloc(SCR_COL*SCR_ROW*sizeof(char));/*窗口字符属性*/
gp_top_layer = (LAYER*)malloc(sizeof(LAYER));
gp_top_layer->LayerNum = 0; /*弹出窗口层号为0*/
gp_top_layer->rcArea.Left = 0;
gp_top_layer->rcArea.Top = 0;
gp_top_layer->rcArea.Right = SCR_COL-1;
gp_top_layer->rcArea.Bottom = SCR_ROW-1;
gp_top_layer->pContent = NULL;
gp_top_layer->pScrAtt = gp_scr_att;
gp_top_layer->next = NULL;
ShowMenu(); /*显示系统主菜单*/
RunSys(phead);
return 0;
}
/**
* 函数名称: LoadFile
* 函数功能: 将三类基础数据从数据文件载入到内存缓冲区和十字链表中.
* 输入参数: phead 主链头指针的地址, 用来保存所创建的十字链表地址
* 输出参数: 无
* 返 回 值: 无
*
* 调用说明: 该功能用于运行主要功能之前的数据加载,如果打开文件失败
* 则不会运行系统,并输出提示信息。
*/
void LoadFile(R_type **phead)
{
R_type *head=NULL, *pR_type,tmp1;
ROOM *pROOM, tmp2;
GUEST *pGUEST, tmp3;
FILE *pFile;
char find;
if((pFile = fopen("RoomType.dat","rb")) == NULL)
{
printf("\n客房类别文件打开失败");
exit(-1);
}
while(fread(&tmp1,sizeof(R_type),1,pFile) == 1)
{/*读入客房类别信息并加入链表*/
pR_type = (R_type *)malloc(sizeof(R_type));
*pR_type = tmp1; //对指针本身内容进行修改,所以需要二级指针作为入口参数
pR_type->rnext = NULL; //初始房间类型结点下的房间信息链表为空
pR_type->next = head;
head = pR_type;
}
if(head == NULL)
{/*头指针为空指针说明未加入类别信息,调用录入类别功能*/
printf("\n还未添加任何客房类别信息!请添加客房类别信息:");
maintain_rtype_add(&head);
}
*phead = head;
fclose(pFile);
if((pFile = fopen("RoomInfo.dat","rb")) == NULL)
{
printf("\n客房基本信息文件打开失败");
exit(-1);
}
while(fread(&tmp2,sizeof(ROOM),1,pFile) == 1)
{/*读入房间信息并加入链表*/
pROOM = (ROOM *)malloc(sizeof(ROOM));
*pROOM = tmp2;
pROOM->gnext = NULL; //初始化房间信息结点下的客人链表为空
pR_type = head;
while((pR_type != NULL)&&(pR_type->type != pROOM->r_type))
{/*顺序遍历链表,查找该客房的客房类型结点*/
pR_type = pR_type->next;
}
if(pR_type)
{/*如果找到该类别*/
pROOM->next = pR_type->rnext;
pR_type->rnext = pROOM;
}
else
{/*如果未找到则释放存储该房间信息的内存*/
free(pROOM);
}
}
fclose(pFile);
if((pFile = fopen("GuestInfo.dat","rb")) == NULL)
{
printf("\n客人信息文件打开失败");
exit(-1);
}
while(fread(&tmp3,sizeof(GUEST),1,pFile) == 1)
{/*读入客人信息并加入链表*/
pGUEST = (GUEST *)malloc(sizeof(GUEST));
*pGUEST = tmp3;
pR_type = head;
find = 0;
while(pR_type && !find)
{/*没有查找完所有客房类别而且没有找到时,进行查找的循环*/
pROOM = pR_type->rnext;
while(pROOM && !find)
{/*没有查找完所有客房而且没有找到时,进行查找的循环*/
if(pGUEST->r_num == pROOM->r_num)
{/*查找到客人所在客房时,标记find为1,并停止查找*/
find = 1;
break;
}
pROOM = pROOM->next;
}
pR_type = pR_type->next;
}
if(find)
{/*将客人信息结点链接到房间的客人链表中*/
pGUEST->next = pROOM->gnext;
pROOM->gnext = pGUEST;
}
else
{
free(pGUEST);
}
}
}
/**
* 函数名称: ShowMenu
* 函数功能: 在屏幕上显示主菜单, 并设置热区, 在主菜单第一项上置选中标记.
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
*
* 调用说明:
*/
void ShowMenu(void)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
CONSOLE_CURSOR_INFO cci;
COORD size;
COORD pos = {0,0}, pos2={0,2};
int i,j;
int PosA = 2, PosB;
char ch;
GetConsoleScreenBufferInfo(gh_std_out , &csbi);
size.X = csbi.dwSize.X;
size.Y = 1;
SetConsoleCursorPosition(gh_std_out , pos);
for(i = 0; i<4; i++) /*第一行第一列输出主菜单项*/
{
printf(" %s ", main_menu[i]);
}
/*申请动态存储区作为存放菜单条屏幕区字符信息的缓冲区*/
buff_menubar_info = (CHAR_INFO*)malloc(size.X*size.Y*sizeof(CHAR_INFO));
SMALL_RECT rcMenu = {0, 0, size.X - 1,0};
/*将第一行内容读入到存放菜单条屏幕区字符信息的缓冲区中*/
ReadConsoleOutput(gh_std_out, buff_menubar_info , size,pos , &rcMenu);
/*将这一行字符单元置为白底黑字*/
for(i=0; i<size.X ; i++)
{
(buff_menubar_info+i)->Attributes = BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED;
}
/*修改后的字符信息回写到第一行*/
WriteConsoleOutput(gh_std_out, buff_menubar_info, size, pos, &rcMenu);
TagMainMenu(gi_sel_menu);/*标记选中主菜单*/
SetConsoleCursorPosition(gh_std_out, pos2);
return;
}
/**
* 函数名称: TagMainMenu
* 函数功能: 在指定主菜单项上置选中标志.
* 输入参数: num 选中的主菜单项号
* 输出参数: 无
* 返 回 值: 无
*
* 调用说明:
*/
void TagMainMenu(int num)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
COORD size;
COORD pos={0,0};
int PosA=2, PosB;
char ch;
int i;
if(num == 0)/*num为0时去除标记*/
{
PosA=0;
PosB=0;
}
else /*否则,定位选中主菜单项的起止位置:PosA为起始位置,PosB为截止位置*/
{
for(i=1; i<num; i++)
{
PosA += strlen(main_menu[i-1]) + 4;
}
PosB = PosA + strlen(main_menu[num-1]);
}
GetConsoleScreenBufferInfo(gh_std_out, &csbi);
size.X = csbi.dwSize.X;
size.Y = 1;
/*去除前面菜单项的标记*/
for(i=0; i<PosA; i++)
{
(buff_menubar_info+i)->Attributes = BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED;
}
/*标记选中菜单项,黑底白字*/
for(i=PosA; i<PosB; i++)
{
(buff_menubar_info+i)->Attributes = FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED;
}
/*去除后面菜单项的标记*/
for(i=PosB; i<size.X; i++)
{
(buff_menubar_info+i)->Attributes = BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED;
}
/*将做好标记的信息回写到第一行*/
SMALL_RECT rcMenu = {0,0,size.X-1,0};
WriteConsoleOutput(gh_std_out,buff_menubar_info, size, pos, &rcMenu);
return;
}
/**
* 函数名称: ClearWindow
* 函数功能: 清楚控制台窗口屏幕信息
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
*
* 调用说明:
*/
void ClearWindow(void)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
COORD home={0,0};
unsigned long size;
GetConsoleScreenBufferInfo(gh_std_out, &csbi);
size = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputAttribute(gh_std_out, csbi.wAttributes, size, home, &ul);
FillConsoleOutputCharacter(gh_std_out, ' ', size, home, &ul);
return;
}
/**
* 函数名称: ClearScreen
* 函数功能: 清除主菜单条下的屏幕信息.
* 输入参数: 无
* 输出参数: 无
* 返 回 值: