windows API 开发飞机订票系统(二)

来源:互联网 发布:招聘网络技术员图片 编辑:程序博客网 时间:2024/05/20 13:37

呐,上回书说到写代码过程中遇到不少问题,在这里就一点一点慢慢道来吧。

首先,定义的结构体、全局变量和函数如下:

// Flight.c : 定义应用程序的入口点。//#include "stdafx.h"//订单typedef struct OrderForm{TCHAR IdNum[32];//订单用户身份证号int Order_Number;//订单号int Tickets_Num;//订票数量TCHAR Flight_Number[16];//航班号TCHAR Departure[16];//出发地TCHAR Destination[16];//目的地TCHAR Date[16];//出发日期TCHAR TakeOff_Time[16];//起飞时间TCHAR Landing_Time[16];//降落时间struct OrderForm *Next;//所有订单链表nextstruct OrderForm *psgNext;//用户订单链表next}OrderForm;//乘客订单链表typedef struct PsgOrderLink{int OrderNum;//订单数目OrderForm *head;//头结点OrderForm *tail;//尾结点}PsgOrderLink;//所有订单列表typedef struct AllOrderLink{int AllOrderNum;//所有订单数目OrderForm *head;//头结点OrderForm *tail;//尾结点}AllOrderLink;//乘客typedef struct Passenger{TCHAR Name[16];        //姓名TCHAR IdNum[32];//身份证号码TCHAR PassWord[32];    //密码int TicketNum;//订单数目PsgOrderLink OrderLink;//用户所有订单struct Passenger *Next;}Passenger;//乘客链表typedef struct PsgLinkList{int PsgNum;//账户数量Passenger *head;//头结点Passenger *tail;//尾结点}PsgLinkList;//航班typedef struct Flight{double Fare;//票价int Seat_Number;//座位数int Vacant_Seat;//空余座位数TCHAR Discount[16];//折扣TCHAR Flight_Number[16];//航班号TCHAR Departure[16];//出发地TCHAR Destination[16];//目的地TCHAR Date[16];//出发日期TCHAR TakeOff_Time[16];//起飞时间TCHAR Landing_Time[16];//降落时间struct Flight *Next;}Flight;//航班链表typedef struct FlightLinkList{Flight *head;//头结点Flight *tail;//尾结点int Flight_Number;//航班数目}FilghtLinkList;// 全局变量: HICON hIcon;HINSTANCE hInst;//当前实例static TCHAR szBuffer[256];//缓冲区static PsgLinkList psglink;//所有账户_链表static Passenger *passenger;//登陆账户信息static AllOrderLink allorder;//所有订单_链表static FilghtLinkList flightlink;//所有航班_链表//函数声明BOOL AccountLogIn(HWND);//账户登陆BOOL AccountRegister(HWND);//注册账户BOOL ReadFlightData(HWND);//读入航班信息BOOL ReadAccountData(HWND);//读入账户资料BOOL ReadAccountOrder(HWND,Passenger*);//读入所有订单、账户订单BOOL SearchFlight(HWND);//查询航班BOOL BookTickets(HWND);//订票BOOL _Book_Tickets(HWND,Flight*,int);//订票BOOL Recommend(HWND,Flight*,int);//航班建议BOOL ReturnTickets(HWND);//退票BOOL EntryFlight(HWND);//录入航班BOOL ModifyFlight(HWND);//修改航班信息BOOL PrintFlight(HWND, Flight*);//输出航班信息BOOL WriteFlightData(HWND);//保存航班信息BOOL WriteAccountData(HWND);//保存账户资料BOOL WriteOrderData(HWND);//保存订单信息BOOL CALLBACK LogInDlgProc(HWND, UINT, WPARAM, LPARAM);//登陆窗口窗口过程BOOL CALLBACK MainDlgProc(HWND, UINT, WPARAM, LPARAM);//主界面窗口过程BOOL CALLBACK NameDlgProc(HWND, UINT, WPARAM, LPARAM);//获取新注册用户姓名窗口过程BOOL CALLBACK FlightNumDlgProc(HWND, UINT, WPARAM, LPARAM);//获取用户输入机票数量窗口过程BOOL CALLBACK EntryFlightProc(HWND, UINT, WPARAM, LPARAM);//录入航班窗口过程BOOL CALLBACK ModifyFlightProc(HWND, UINT, WPARAM, LPARAM);//修改航班信息窗口过程
主函数如下:

//主函数int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR szCmdLine,int iCmdShow){hInst = hInstance;InitCommonControls();hIcon=LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1));return DialogBox(hInst, MAKEINTRESOURCE(IDD_LOGINDLG), NULL, (DLGPROC)LogInDlgProc);}//WinMain

登陆界面窗口过程:

//登陆窗口_窗口过程BOOL CALLBACK LogInDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)  {switch (uMsg){//WM_INITDIALOG是当其对话框和子控件全部创建完毕,将要显示内容的时候发送的消息//因此可以在WM_INITDIALOG消息响应函数中添加对编辑框控件的初始化和修改case WM_INITDIALOG:  {if (hIcon)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);ReadAccountData(hwndDlg);//登陆对话框初始化时读入账户资料ReadFlightData(hwndDlg);//登陆对话框初始化时读入航班信息}//WM_INITDIALOGreturn TRUE;case WM_CLOSE:{EndDialog(hwndDlg, 0);}//WM_CLOSEreturn TRUE;case WM_COMMAND:{switch (LOWORD(wParam)){case IDC_LOGIN:AccountLogIn(hwndDlg);//登陆break;case IDC_REGISTER:AccountRegister(hwndDlg);//注册break; }//switch}//WM_COMMANDreturn TRUE;}//switchreturn FALSE;}//LogInDlgProc()

我在对话框初始化时调用了下述函数来加载程序标题栏的图标:

if (hIcon)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);

接下来就该读取文件了。

那么问题就来了,挖掘机...额,不对,应该怎么读入账户资料和航班信息?

我把账户资料和航班信息储存在了.txt文件里,每一行是结构体的一个成员,一个一个读入。

两个读入函数代码如下:

//读入账户信息BOOL ReadAccountData(HWND hwndDlg){FILE *fp;passenger = (Passenger *)malloc(sizeof(Passenger));//为登录账户分配内存if (!passenger){MessageBox(hwndDlg, TEXT("内存申请错误!"), TEXT("错误"), MB_OK | MB_ICONERROR);EndDialog(hwndDlg, 0);return FALSE;}//if psglink.head = NULL;psglink.tail = NULL;psglink.PsgNum = 0;if ((fp = fopen(".\\AccountData.txt", "r+")) == NULL){//打开文件MessageBox(hwndDlg, TEXT("账户文件读入错误!"), TEXT("错误"), MB_OK | MB_ICONERROR);EndDialog(hwndDlg, 0);}//ifwhile (!feof(fp)){Passenger *p = (Passenger *)malloc(sizeof(Passenger));if (!p){MessageBox(hwndDlg, TEXT("内存申请错误!"), TEXT("错误"), MB_OK | MB_ICONERROR);EndDialog(hwndDlg, 0);return FALSE;}//if//读入账户姓名、身份证号、密码if (fscanf(fp, "%s%s%s", p->Name, p->IdNum, p->PassWord) == EOF){free(p); break;}p->Next = NULL;if (psglink.head == NULL)//读入第一个账户信息时,头、尾结点均指向ppsglink.head = p;elsepsglink.tail->Next = p;//否则,尾结点Next指向ppsglink.tail = p;//尾结点指向ppsglink.PsgNum++;//已注册账户个数}//whilefclose(fp);//关闭文件return TRUE;}//ReadAccountData(HWND)//读入航班信息BOOL ReadFlightData(HWND hwndDlg){int flag = 0;FILE *fp;flightlink.Flight_Number = 0;flightlink.head = NULL;flightlink.tail = NULL;if ((fp = fopen(".\\FlightData.txt", "r")) == NULL){//打开文件MessageBox(hwndDlg, TEXT("账户文件读入错误!"), TEXT("错误"), MB_OK | MB_ICONERROR);EndDialog(hwndDlg, 0);}//ifwhile (!feof(fp)){Flight *p = (Flight *)malloc(sizeof(Flight));if (!p){MessageBox(hwndDlg, TEXT("内存申请错误!"), TEXT("错误"), MB_OK | MB_ICONERROR);EndDialog(hwndDlg, 0);return FALSE;}//if//读入航班信息if (fscanf(fp, "%s%lf%s%d%d%s%s%s%s%s",p->Flight_Number,&p->Fare,p->Discount,&p->Seat_Number,&p->Vacant_Seat,p->Departure,p->Destination,p->Date,p->TakeOff_Time,p->Landing_Time) == EOF){free(p);break;}p->Next = NULL;if (flightlink.head == NULL)//添加至链表flightlink.head = p; elseflightlink.tail->Next = p;flightlink.tail = p;flightlink.Flight_Number++;}//whilefclose(fp);//关闭文件return TRUE;}//ReadFlightData()

编译运行的时候会报错,报错信息是大体是说fopen()函数不安全,根据提示信息,解决办法是在文件头部做如下定义:

#define _CRT_SECURE_NO_WARNINGS

或者是在项目->属性->c/c++->预处理器->预处理器定义,后面加上_CRT_SECURE_NO_WARNINGS就行了。

结下来又遇到问题了:程序退出把数据写入txt文件时每行末尾都会有一个\n,读入数据的时候用的是feof()函数,而feof()返回的其实是"最后一次读操作的内容",与数据库中的eof()不同,eof()读取的是当前指针位置。因此在读到文件末尾的时候,程序会多执行一次循环,为了防止这种情况,我采取的是检查fscanf()返回值的方法,在此以读入账户资料时为例:

//读入账户姓名、身份证号、密码if (fscanf(fp, "%s%s%s", p->Name, p->IdNum, p->PassWord) == EOF){<span style="white-space:pre"></span>free(p); break;}
下面继续贴函数代码:
//登陆用户验证BOOL AccountLogIn(HWND hwndDlg){int flag = 0;//flag!=0则该用户已注册,flag==0则该用户尚未注册Passenger *p;GetDlgItemText(hwndDlg, IDC_IDEDIT, passenger->IdNum, 256);//获取用户输入IDGetDlgItemText(hwndDlg, IDC_PSWEDIT, passenger->PassWord, 256);//获取用户输入密码p = psglink.head;while (p){//在用户链表查找登陆用户IDif (!lstrcmp(passenger->IdNum, p->IdNum)){flag++;//该用户已注册if (!lstrcmp(passenger->PassWord, p->PassWord)){//密码匹配,登陆成功lstrcpy(passenger->Name, p->Name);MessageBox(hwndDlg, TEXT("登陆成功,单击确定进入程序主界面"), TEXT("登陆成功"), MB_OK | MB_ICONINFORMATION);break;}//ifelse{//密码错误,退出循环MessageBox(hwndDlg, TEXT("密码错误,请重新输入"), TEXT("密码错误"), MB_OK | MB_ICONERROR);return FALSE;}//else}//ifp = p->Next;}//whileif (!flag){//用户尚未注册if (lstrlen(passenger->PassWord)==0)MessageBox(hwndDlg, TEXT("请输入密码!"), TEXT("信息"), MB_OK | MB_ICONINFORMATION);elseMessageBox(hwndDlg, TEXT("该账户尚未注册,请先注册"), TEXT("信息"), MB_OK | MB_ICONINFORMATION);}//ifelse{//关闭登陆界面,弹出主界面EndDialog(hwndDlg, TRUE);if (ReadAccountOrder(hwndDlg, passenger))//读取用户订单DialogBox(hInst, MAKEINTRESOURCE(IDD_MAINDLG), NULL, (DLGPROC)MainDlgProc);}//elsereturn TRUE;}//AccountLogIn(HWND)
//用户注册BOOL AccountRegister(HWND hwndDlg){GetDlgItemText(hwndDlg, IDC_IDEDIT, passenger->IdNum, 256);//获取用户输入IDGetDlgItemText(hwndDlg, IDC_PSWEDIT, passenger->PassWord, 256);//获取用户输入密码if (lstrlen(passenger->PassWord) == 0){MessageBox(hwndDlg, TEXT("请输入注册用户密码!"), TEXT("信息"), MB_OK | MB_ICONINFORMATION);return FALSE;}DialogBox(hInst, MAKEINTRESOURCE(IDD_NAMEDLG), NULL, (DLGPROC)NameDlgProc);//获取新注册用户姓名if (lstrlen(passenger->Name) == 0)return FALSE;passenger->Next = NULL;if (psglink.head == NULL)//该注册账户为第一个账户时,头、尾结点均指向passengerpsglink.head = passenger;elsepsglink.tail->Next = passenger;//将新注册账户资料添加至账户链表psglink.tail = passenger;//链表尾指针指向链表尾psglink.PsgNum++;//注册用户数目加1passenger->TicketNum = 0;passenger->OrderLink.head = NULL;//乘客订单链表初始化passenger->OrderLink.tail = NULL;passenger->OrderLink.OrderNum = 0;MessageBox(hwndDlg, TEXT("注册成功!请单击确定进入主界面"), TEXT("注册成功"), MB_OK | MB_ICONINFORMATION);EndDialog(hwndDlg, TRUE);//关闭登陆界面DialogBox(hInst, MAKEINTRESOURCE(IDD_MAINDLG), NULL, (DLGPROC)MainDlgProc); //弹出主界面return TRUE;}//AccountRegister(HWND)

//获取新注册用户姓名_窗口过程BOOL CALLBACK NameDlgProc(HWND hNameDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){switch (uMsg){case WM_INITDIALOG:{if (hIcon)SendMessage(hNameDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);}return TRUE;case WM_CLOSE:{wsprintf(passenger->IdNum, TEXT("\0"));EndDialog(hNameDlg, 0);}//WM_CLOSEreturn TRUE;case WM_COMMAND:{switch (LOWORD(wParam)){case IDC_GETNAMEOK:{GetDlgItemText(hNameDlg, IDC_GETNAME, passenger->Name, 16);EndDialog(hNameDlg, TRUE);break;}//GETNAMEcase IDC_GETNAMECANCEL:{wsprintf(passenger->IdNum, TEXT("\0"));EndDialog(hNameDlg, TRUE);break;}//GETNAMECANCEL}//stitch}//WM_COMMANDreturn TRUE;}//stitchreturn FALSE;}//NameDlgProc()
//读取订单信息BOOL ReadAccountOrder(HWND hwndDlg, Passenger *passenger){FILE *fp;allorder.AllOrderNum = 0;//订单链表初始化allorder.head = NULL;allorder.tail = NULL;passenger->TicketNum = 0;//乘客订单链表初始化passenger->OrderLink.head = NULL;passenger->OrderLink.tail = NULL;passenger->OrderLink.OrderNum = 0;if ((fp = fopen(".\\OrderForm.txt", "r")) == NULL){//打开存储订单信息文件MessageBox(hwndDlg, TEXT("订单文件读入错误!"), TEXT("错误"), MB_OK | MB_ICONERROR);return FALSE;}while (!feof(fp)){OrderForm *p = (OrderForm *)malloc(sizeof(OrderForm));if (!p){MessageBox(hwndDlg, TEXT("内存申请错误!"), TEXT("错误"), MB_OK | MB_ICONERROR);EndDialog(hwndDlg, 0);return FALSE;}//ifif (fscanf(fp, "%s%d%d%s%s%s%s%s%s",p->IdNum,//读取订单信息&p->Order_Number,&p->Tickets_Num,p->Flight_Number,p->Departure,p->Destination,p->Date,p->TakeOff_Time,p->Landing_Time) == EOF){free(p);break;}p->Next = NULL;p->psgNext = NULL;if (allorder.head == NULL){//将结点添至订单链表末尾allorder.head = p; }elseallorder.tail->Next = p;allorder.tail = p;allorder.AllOrderNum++;//订单数目增加if (!lstrcmp(p->IdNum, passenger->IdNum)){//若该订单为当前登录账户订单,则添至用户订单链表末尾if (passenger->OrderLink.head == NULL){//将结点添至用户订单链表末尾passenger->OrderLink.head = p;}elsepassenger->OrderLink.tail->psgNext = p;passenger->OrderLink.tail = p;passenger->TicketNum += p->Tickets_Num;passenger->OrderLink.OrderNum++;//订单数目增加}//if}//whilefclose(fp);return TRUE;}//ReadAccountOrder()

至此,登录对话框部分已经完成。下篇博客来完成主界面的部分功能.....
0 0
原创粉丝点击