Windows API開発飛行機予約システム(二)


ねえ、前回の本はコードを書く過程で多くの問題があったと言っていましたが、ここでは少しずつゆっくり話しましょう.
まず、定義された構造体、グローバル変数、関数は次のとおりです.
// 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()

これで、ログインダイアログのセクションが完了しました.次のブログはメインインタフェースの一部の機能を完成します.....