Windows API開発飛行機予約システム(二)
13611 ワード
ねえ、前回の本はコードを書く過程で多くの問題があったと言っていましたが、ここでは少しずつゆっくり話しましょう.
まず、定義された構造体、グローバル変数、関数は次のとおりです.
主な関数は次のとおりです.
インタフェースウィンドウにログインする手順は、次のとおりです.
ダイアログボックスの初期化時に、プログラムタイトルバーのアイコンをロードするために次の関数を呼び出しました.
まず、定義された構造体、グローバル変数、関数は次のとおりです.
// 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; // next
struct 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_INITDIALOG
return TRUE;
case WM_CLOSE:
{
EndDialog(hwndDlg, 0);
}//WM_CLOSE
return TRUE;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_LOGIN:
AccountLogIn(hwndDlg); //
break;
case IDC_REGISTER:
AccountRegister(hwndDlg); //
break;
}//switch
}//WM_COMMAND
return TRUE;
}//switch
return FALSE;
}//LogInDlgProc()
ダイアログボックスの初期化時に、プログラムタイトルバーのアイコンをロードするために次の関数を呼び出しました.
if (hIcon) SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
次はファイルを読み込む時間です.
じゃあ問題だ掘削機...ええ、違います.口座の資料とフライト情報はどうやって読めばいいですか?
私は口座の資料とフライト情報を保存しました.txtファイルでは、各行が構造体のメンバーであり、1つずつ読み込まれます.
2つの読み込み関数コードは次のとおりです.// 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); }//if while (!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) // , 、 p psglink.head = p; else psglink.tail->Next = p; // , Next p psglink.tail = p; // p psglink.PsgNum++; // }//while fclose(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); }//if while (!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; else flightlink.tail->Next = p; flightlink.tail = p; flightlink.Flight_Number++; }//while fclose(fp); // return TRUE; }//ReadFlightData()
コンパイル実行時にエラーが発生します.エラー情報は大体fopen()関数が安全ではないということです.プロンプト情報によると、解決策はファイルヘッダで以下の定義をします.#define _CRT_SECURE_NO_WARNINGS
または、プロジェクト->プロパティ->c/c+->プリプロセッサ->プリプロセッサ定義に_を付けるCRT_SECURE_NO_WARNINGSでいいです.
プログラムが終了してtxtファイルにデータを書き込むと各行の末尾に1つあり、データを読み込むときにfeof()関数を使用しますが、feof()は「最後の読み取り操作の内容」を返し、データベースのeof()とは異なり、eof()は現在のポインタ位置を読み取ります.したがって、ファイルの最後まで読むと、プログラムは1回以上ループを実行します.これを防ぐために、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); // ID GetDlgItemText(hwndDlg, IDC_PSWEDIT, passenger->PassWord, 256); // p = psglink.head; while (p){ // ID if (!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; }//if else{ // , MessageBox(hwndDlg, TEXT(" , "), TEXT(" "), MB_OK | MB_ICONERROR); return FALSE; }//else }//if p = p->Next; }//while if (!flag){ // if (lstrlen(passenger->PassWord)==0) MessageBox(hwndDlg, TEXT(" !"), TEXT(" "), MB_OK | MB_ICONINFORMATION); else MessageBox(hwndDlg, TEXT(" , "), TEXT(" "), MB_OK | MB_ICONINFORMATION); }//if else{ // , EndDialog(hwndDlg, TRUE); if (ReadAccountOrder(hwndDlg, passenger)) // DialogBox(hInst, MAKEINTRESOURCE(IDD_MAINDLG), NULL, (DLGPROC)MainDlgProc); }//else return TRUE; }//AccountLogIn(HWND)
// BOOL AccountRegister(HWND hwndDlg){ GetDlgItemText(hwndDlg, IDC_IDEDIT, passenger->IdNum, 256); // ID GetDlgItemText(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) // , 、 passenger psglink.head = passenger; else psglink.tail->Next = passenger; // psglink.tail = passenger; // psglink.PsgNum++; // 1 passenger->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_CLOSE return TRUE; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_GETNAMEOK: { GetDlgItemText(hNameDlg, IDC_GETNAME, passenger->Name, 16); EndDialog(hNameDlg, TRUE); break; }//GETNAME case IDC_GETNAMECANCEL: { wsprintf(passenger->IdNum, TEXT("\0")); EndDialog(hNameDlg, TRUE); break; }//GETNAMECANCEL }//stitch }//WM_COMMAND return TRUE; }//stitch return 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; }//if if (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; } else allorder.tail->Next = p; allorder.tail = p; allorder.AllOrderNum++; // if (!lstrcmp(p->IdNum, passenger->IdNum)){ // , if (passenger->OrderLink.head == NULL){ // passenger->OrderLink.head = p; } else passenger->OrderLink.tail->psgNext = p; passenger->OrderLink.tail = p; passenger->TicketNum += p->Tickets_Num; passenger->OrderLink.OrderNum++; // }//if }//while fclose(fp); return TRUE; }//ReadAccountOrder()
これで、ログインダイアログのセクションが完了しました.次のブログはメインインタフェースの一部の機能を完成します.....