通過這個簡單圖書管理系統我溫習了不少mfc即c++的基礎知識,收穫還是很多的。現在把其中涉及到的一些基礎知識都記錄下來。
1.book類,
class CBook
{
public:
CBook(){};
CBook(char* cName,char* cIsbn,char* cPrice,char* cAuthor);
//~CBook();
char* GetName();
void SetName(char* cName);
char* GetIsbn();
void SetIsbn(char* cIsbn);
char* GetPrice();
void SetPrice(char* cPrice);
char* GetAuthor();
void SetAuthor(char* cAuthor);
void WriteData();
void DeleteData(int iCount);
void GetBookFromFile(int iCount);
protected:
char m_cName[NUM1];
char m_cIsbn[NUM1];
char m_cPrice[NUM2];
char m_cAuthor[NUM2];
};
先是定義了book類,裏面包含了,書名,isbn號,作者和價錢幾個成員變量,另外還定義了構造函數和析構函數,以及成員函數。具體的實現方法在book.cpp裏實現。
2.接着是登錄界面的設計,以前用java也寫過登錄界面,但是和mfc還是不太一樣的,在這裏遇到的問題是,輸入登錄名後直接回車就進入界面了,有些尷尬,另外在輸入完密碼後如何按回車進入登錄操作,在這裏費了一些時間,後面找到解決方法,就是重載PreTranslateMessage函數,這個函數是在進入消息循環之前的攔截消息的函數,如其名,在轉換消息之前攔截,
BOOL BookManagerLogin::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case VK_RETURN:
//按下回車,執行登陸.....
OnBnClickedButtonLogin();
break;
default:
break;
}
}
//return CDialog::PreTranslateMessage(pMsg);//rreturn 1,則不響應這個消息
return false;
}
在這裏攔截回車按鍵VK-wParam,就可以解決上面的兩個問題
3.另外還有一個是在兩個界面之間的切換,一開始的時候,在登錄成功之後,登錄界面並不會消失,
MSDN是這樣說明其返回值的
If successful, the value of the nRetCode parameter specified in the call toEndDialog; otherwise, -1.
如果操作成功,其返回值爲由EndDialog指定的nRetCode的值,而此參數nRetCode的含義爲關閉對話框所採用的方式也就是說,在關閉此模態對話框時,其返回值爲關閉對話框時所採用的方式 因此它只在對話框關閉時才返回相關參數值
默認對話框關閉方式有2種:OnOK(); OnCancel()
當使用OnOK()函數關閉對話框時,返回值爲IDOK
當使用OnCancel()函數關閉對話框時,返回值爲IDCANCEL返回值與ID無關
所以我在驗證登錄賬號和密碼的處理函數中加入了CDialogEx::OnOK();或者是this->OnOk()都可以,關閉之前的對話框,
4.接着就是主界面的設計
整體來說界面做的很醜,很簡單,不過主要是爲了驗證功能,也就無所謂了,這裏面還是遇到了不少的難題的。這裏說明一下,這裏沒有用到數據庫,做的都是本地存儲。
(1)圖書信息存儲,這裏用的是fstream,ofstream,ifstream而沒有用到mfc專門封裝的CFile和CStdioFile,
這裏主要是討論fstream的內容:
-
#include <fstream>
-
ofstream //文件寫操作 內存寫入存儲設備
-
ifstream //文件讀操作,存儲設備讀取到內存中
-
fstream //讀寫操作,對打開的文件可進行讀寫操作
1.打開文件
在fstream類中,成員函數open()實現打開文件的操作,從而將數據流和文件進行關聯,通過ofstream,ifstream,fstream對象進行對文件的讀寫操作
函數:open()
-
void open ( const char * filename,
-
ios_base::openmode mode = ios_base::in | ios_base::out );
-
void open(const wchar_t *_Filename,
-
ios_base::openmode mode= ios_base::in | ios_base::out,
-
int prot = ios_base::_Openprot);
參數: filename 操作文件名
mode 打開文件的方式
prot 打開文件的屬性 //基本很少用到,在查看資料時,發現有兩種方式
打開文件的方式在ios類(所以流式I/O的基類)中定義,有如下幾種方式:
ios::in | 爲輸入(讀)而打開文件 |
ios::out | 爲輸出(寫)而打開文件 |
ios::ate | 初始位置:文件尾 |
ios::app | 所有輸出附加在文件末尾 |
ios::trunc | 如果文件已存在則先刪除該文件 |
ios::binary | 二進制方式 |
這些方式是能夠進行組合使用的,以“或”運算(“|”)的方式:例如
-
ofstream out;
-
out.open("Hello.txt", ios::in|ios::out|ios::binary) //根據自己需要進行適當的選取
打開文件的屬性同樣在ios類中也有定義:
0 | 普通文件,打開操作 |
1 | 只讀文件 |
2 | 隱含文件 |
4 | 系統文件 |
對於文件的屬性也可以使用“或”運算和“+”進行組合使用,這裏就不做說明了。
ofstream流,以ios::app打開(或者“ios::app|ios::out”),如果沒有文件,那麼生成空文件;如果有文件,那麼在文件尾追加。
以ios::app|ios::in打開,不管有沒有文件,都是失敗。
以ios::ate打開(或者”ios::ate|ios::out”),如果沒有文件,那麼生成空文件;如果有文件,那麼清空該文件
以ios::ate|ios::out打開,如果沒有文件,那麼打開失敗;如果有文件,那麼定位到文件尾,並可以寫文件,但是不能讀文件
ifstream流,以ios::app打開(“ios::app|ios::out”),不管有沒有文件,打開都是失敗。
以ios::ate打開(“ios::ate|ios::out”),如果沒有文件,打開失敗
如果有文件,打開成功,並定位到文件尾,但是不能寫文件
fstream流,默認是ios::in,所以如果沒有文件,ios::app和ios::ate都是失敗,
以ios::app|ios::out,如果沒有文件則創建文件,如果有文件,則在文件尾追加
以ios::ate|ios::out打開,如果沒有文件則創建文件,如果有,則清空文件。
以ios::ate|ios::out|ios::in打開,如果沒有文件,則打開失敗,有文件則定位到文件尾
可見:ios::app不能用來打開輸入流,即不能和ios::in相配合
而ios::ate可以和ios::in配合,此時定位到文件尾;如果沒有ios::in相配合而只是同ios::out配合,那麼將清空原文件
可以在《C++ 輸入輸出流及本地化》1.4.2中找到更詳細的描述:(大意)以ios::app方式打開文件,即使修改文件指針,也只能輸出到文件尾。實際上以ios::app打開的文件的寫入,和文件指針五關。
奇怪的是:《C++ 輸入輸出流及本地化》和《C++編程思想》都說以ios::ate打開的文件,文件指針都會定位到文件尾且不清空文件,但是我發現ios::ate如果不和ios::in配合的話,將清空原文件。
總之一句,如果要創建文件,用ios::app|ios::out,沒有文件的時候回創建文件,有文件的時候在後面追加,但是不可以用seek函數,無論怎樣都是在文件後面添加。
要修改文件的話,用ios::out,可用使用seek定位到你想要的位置然後修改。
ofstream:打開文件不存在,默認會創建這個文件。(除非指定ios::nocreate)
ifstream:打開文件存在與否,默認不會創建在個文件.
fstream:打開文件不存在,默認會創建這個文件。(除非只是指定ios::in 或者指定ios::nocreate)
二進制模式和Text模式的區別。
二進制模式:對於一行的結尾我們必須輸入'\r\n',才能表示回車換行的效果。
Text模式:'\r'回車的工作是自動完成的,我們只需要寫入'\n'即可。在使用Text模式時從外部讀入文件時,'\r\n'會被翻譯成'\n',寫入文件時,我們對於回車換行只需提供'\n',即可,'\r\n'會被寫入到文件中