第一部分:MFC導論
Visual C++ 不僅僅是一個編譯器。它是一個全面的應用程序開發環境,使用它你充分利用具有面向對象特性的 C++ 來開發出專業級的 Windows 應用程序。為了能充分利用這些特性,你必須理解 C++ 程序設計語言。掌握了C++,你就必須掌握 Microsoft 基本類庫 (MFC) 的層次結構。該層次 結構包容了 Windows API 中的用戶界面部分,並使你能夠很容易地以面向對象的方式建立 Windows 應用程序。這種層次結構適用於所有版本的 Windows 並彼此兼容。你用 MFC 所建立的代碼是完全可移植的。
該教程將向你介紹MFC的基本概念和術語以及事件驅動程序設計方法。在本節中,你將會輸入、編譯和運行一個簡單的MFC程序。下一節中將向你詳細解釋這些代碼。第三部分討論了MFC控制和如何定制它們。第四部分將介紹消息映射,你將會處理MFC的事件。
什麼是MFC?
如果你要建立一個 Windows 應用程序,應該如何下手?
好的開端是從設計用戶界面開始。首先,你要決定什麼樣的用戶能使用該程序並根據需要來設置相應的用戶界面對象。Windows 用戶界面有一些標准的控制,如按鈕、菜單、滾動條和列表等,這對那些 Windows 用戶已經是很熟悉了。 要記住的是,作為程序員必須選擇一組控制並決定如何把它們安排到屏幕上。傳統上,你需要在紙上做一下用戶界面的草圖,直到對各元素感到滿意為止。這對於一些比較小的項目,以及一些大項目的早期原型階段是可以的。
下一步,是要實現代碼。為任何 Windows 平台建立應用程序時,程序員都有兩種選擇:C 或 C++。 使用 C,程序員是在 Windows 應用程序界面 ( API ) 的水平上編寫代碼。該界面是由幾百個 C 函數所組成,這些函數在Windows API 參考手冊中都有介紹。對於Windows NT, API 被稱為 “Win32 API”,以區別於其用於Windows 3.1的16位 API。
Microsoft 也提供了 C++ 庫,它位於任何 Windows API 之上,能夠使程序員的工作更容易。它就是Microsoft基本類庫 (MFC),該庫的主要優點是效率高。它減少了大量在建立 Windows 程序時必須編寫的代碼。同時它還提供了所有一般 C++ 編程的優點,例如繼承和封裝。MFC 是可移植的,例如,在 Windows 3.1下編寫的代碼可以很容易地移植到 Windows NT 或 Windows 95 上。因此,MFC 很值得推薦的開發Windows 應用程序的方法,在本教程自始至終使用的都是 MFC。
當是使用 MFC 時,你編寫的代碼是用來建立必要的用戶界面控制並定制其外觀。同時你還要編寫用來響應用戶操作這些控制的代碼。例如,如果用戶單擊一個按鈕時,你應該有代碼來響應。這就是事件驅動代碼,它構成了所有應用程序。一旦應用程序正確的響應了所有允許的控制,它的任務也就完成了。
你可以看出,使用 MFC 進行 Windows 編程時是一件比較容易的的過程。本教程的目的是比較詳細地教你如何快速建立專業級的應用程序的技術。Visual C++ 應用程序開發程序環境特別適合於使用 MFC (也有其它開發環境使用MFC,譯者注),所以一起學習 MFC 和 Visual C++ 能夠增強你的開發程序的能力。
Windows詞匯
在 Windows 用戶界面和軟件開發中所要用到的詞匯都是基本和唯一的。對於新接觸該環境的用戶,下面復習幾個定義以便使我們的討論更加容易。
Windows應用程序使用幾個標准的控制:
靜態文本標簽
按鈕
列表框
組合框(一種更高級的列表框)
單選按鈕
檢查按鈕
編輯框(單行和多行)
滾動條
你可以通過代碼或“資源編輯器”來建立這些控制,在資源編輯器中可以建立對話框和這些控制。在本教程中,我們將使用代碼來建立它們。
Windows支持幾種類型的應用程序窗口。一個典型的應用程序應該活動在稱為“框架窗口”中。一個框架窗口是一個全功能的主窗口,用戶可以改變尺寸、最小化、最大化等。Windows也支持兩種類型的對話框:模式和無模式對話框。模式對話框一旦出現在屏幕上,只有當它退出時,屏幕上該應用程序的其余部分才能響應。無模式對話框出現在屏幕上時,程序的其余部分也可以作出響應,它就象浮動在上面一樣。
最簡單的 Windows 應用程序是使用單文檔界面(SDI),只有一個框架窗口。Windows 的鐘表、PIF 編輯器、記事本等都是 SDI 應用程序的例子。Windows 也提供了一種稱為多文檔界面的組織形式,它可用於更復雜的應用程序。MDI 系統允許用戶在同一應用程序中同時可以查看多個文檔。例如,一個文本編輯器可以允許用戶同時打開多個文本文件。使用 MDI 時,應用程序有一個主窗口,在主窗口中有一些子窗口,每個子窗口中各自包含有各自的文檔。在MDI框架中,主窗口有一個主菜單,它對主框架中最頂端窗口有效。各子窗口都可以縮成圖標或展開,MDI主窗口也可以變成桌面上的一個圖標。MDI界面可能會給你一種第二桌面的感覺,它對窗口的管理和刪除混亂的窗口有很大的幫助。
你所建立的沒一個應用程序都會使用它自己的一套控制、菜單結構以及對話框。應用程序界面的好壞取決於你如何選擇和組織這些界面對象。Visual C++ 中的資源編輯器可以使你能容易的建立和定制這些界面對象。
事件驅動軟件和詞匯
所有基於窗口的 GUI 都包含相同的基本元素,它們的操作方式都是相同的。在屏幕上,用戶所看到的是一組窗口,每個窗口都包含有控制、圖標、對象以及一些處理鼠標和鍵盤的元素。從用戶角度來看,各系統的界面對象都是相同的:按鈕、滾動條、圖標、對話框以及下拉菜單等等。盡管這些界面元素的“外觀和感覺”可能有些不同,但這些界面對象的工作方式都是相同的。例如,滾動條對於Windows、Mac和Motif可能有些不同,但他們的作用完全是一樣的。---www.bianceng.cn
從程序員的角度來看,這些系統在概念上是相似的,盡管它們可能有很大的不同。為了建立 GUI 程序,程序員第一步要把所有需要的用戶界面控制都放到窗口上。例如,如果程序員要建立一個從攝氏到華氏的轉換的簡單程序,則程序員所選擇的用戶界面對象來完成並在屏幕上把結果顯示出來。在這個簡單的程序中,程序員可能需要用戶在一個可編輯的編輯框中輸入溫度值,在一個不可編輯的編輯框中顯示轉換結果,然後讓用戶可以單擊一個標有“退出”的按鈕來退出應用程序。
因為是用戶來操作應用程序的控制,所以程序必須作出響應。所做的響應依賴於用戶使用鼠標或鍵盤在不同控制上的操作。屏幕上的每個用戶界面對象對事件的響應是不同的。例如,如果用戶單擊退出按鈕,則該按鈕必須更新屏幕、加亮它自己。然後程序必須響應退出。
Windows 所用的模式也是類似的。在一個典型的應用程序中,你將建立一個主窗口,並且在其中放置了一些用戶界面控制。這些控制通常被稱為子窗口 它們就象一些在主窗口中的更小更特殊的子窗口。作為程序員,你應該通過函數調用來發送信息操作這些控制、通過把信息發送給你到代碼來響應用戶的操作。
如果你從未做過事件驅動程序設計,則所有這些對你來說可能是很陌生的。但是,事件驅動程序設計方式是很容易理解的。具體的細節對不同的系統可能有些不同,但是其基本概念是類似的。在一個事件驅動界面中,應用程序會在屏幕上繪制幾個界面對象,如按鈕、文本區和菜單。應用程序通常通過一段稱為事件循環的的代碼來響應用戶的操作。用戶可以使用鼠標或鍵盤來任意操作屏幕上的對象。例如,用戶用鼠標單擊一個按鈕。用鼠標單擊就稱為一個事件。事件驅動系統把用戶的動作如鼠標單擊和鍵盤操作定義為事件,也把系統操作如更新屏幕定義為事件。
在比較低級的編程方法中,如用C直接編寫Windows API應用程序,代碼量是非常大的,因為你所要照顧的細節太多了。例如,你用某種類型的結構來接收單擊鼠標事件。你的事件循環中的代碼會查看結構中不同域,以確定哪個用戶界面對象受到了影響,然後會完成相應的操作。當屏幕上有很多對象時,應用程序會變得很大。只是簡單地處理哪個對象被單擊和對它需要做些什麼要花費大量的代碼。
幸運的是,你可以在比較高級的方法來進行編程,這就是使用MFC。在MFC中,幾乎所有的低級的細節處理都為你代辦了。如果你把某一用戶界面對象放在屏幕上,你只需要兩行代碼來建立它。如果用戶單擊一個按鈕,則按鈕自己會完成一切必要的操作,從更新屏幕上的外觀到調用你程序中的預處理函數。該函數包含有對該按鈕作出相應操作的代碼。MFC 為你處理所有的細節:你建立按鈕並告知它特定的處理函數,則當它被按下時,它就會調用相應的函數。第四部分介紹了怎樣使用消息映射來處理事件。
例子
理解一個典型的 MFC 程序的結構和樣式的最好方法是輸入一段小程序,然後編譯和運行它。下面的程序是一段簡單的“hello world”程序。這對很多C程序員都是很熟悉了,讓我們看一下如何用MFC方法來實現。如果你是第一次看到這類程序,也許比較難理解。這沒關系,我們後面會詳細介紹。現在你只要用Visual C++ 環境中建立、編譯和運行它就可以了。
//hello.cpp
#include
// 說明應用程序類
class CHelloApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
// 建立應用程序類的實例
CHelloApp HelloApp;
// 說明主窗口類
class CHelloWindow : public CFrameWnd
{
CStatic* cs;
public:
CHelloWindow();
};
// 每當應用程序首次執行時都要調用的初始化函數
BOOL CHelloApp::InitInstance()
{
m_pMainWnd = new CHelloWindow();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
// 窗口類的構造函數
CHelloWindow::CHelloWindow()
{
// 建立窗口本身
Create(NULL,
"Hello World!",
WS_OVERLAPPEDWINDOW,
CRect(0,0,200,200));
// 建立靜態標簽
cs = new CStatic();
cs->Create("hello world",
WS_CHILD|WS_VISIBLE|SS_CENTER,
CRect(50,80,150,150),
this);
}
上面的這段程序如果用C來實現,得需要幾頁的代碼。這個簡單的例子做了三件事。第一,它建立了一個應用程序對象。你所編寫的每個 MFC 程序都有一個單一的程序對象,它是處理 MFC 和 Windows 的初始細節的。第二,應用程序建立了一個窗口來作為應用程序的主窗口。最後,在應用程序的窗口中建立了一個靜態文本標簽,它包含有“hello world”幾個字。在第二部分中我們會仔細研究這段程序,以理解其結構。
啟動 VC++,如果你是剛剛安裝好,則你會在屏幕上看到一個帶有工具欄的空窗口。如果 VC++ 已經在該機器上使用過了,則所顯示的窗口可能有些不同,因為 VC++ 會記憶和自動重新打開上次使用後退出時的項目和文件。我們需要的是它沒有裝如任何項目和代碼。如果程序啟動後彈出對話框指示不能打開某些文件,你只要單擊“No”即可。在“Window”菜單中選取“Close All”選項關閉所有窗口。在“File”菜單中選取“Close”選項來關閉其它窗口。現在,你就處於開始狀態了。如果你安裝VC++後,第一次運行,則屏幕應如下所示:
如果你以後不希望看到“InfoViewer Topic”窗口,你可以用按鈕把它關掉。如果以後需要的話,你還可以單擊工具欄上的“主頁”按鈕來打開該窗口。
現在一切都正常了。正如你所看到的,頂部是菜單和幾個工具欄。左邊的窗口所顯示的是在線幫助內容,你可以雙擊某項標題來浏覽其內容。在線幫助的內容是十分豐富的。
現在該做什麼了?你所要做的是輸入上面的程序,然後便宜並運行它。開始之前,要檢查以下你的硬盤上至少要留有5MB的剩余空間。
建立項目和編譯代碼
為了在 Visual C++ 中編譯代碼,你必須要建立一個項目。為了這麼小的程序來建立一個項目可能有點小題大作,但是,在任何實際的程序中,項目的概念是非常有用的。一個項目主要保存著下面三種不同類型的信息:
它可以記住建立一個可執行程序所需要的所有源程序代碼文件。在這個簡單的例子中,文件 HELLO.CPP 是唯一的源文件,但是在一個大型的應用程序中,為了便於管理和維護,你可以會有許多個不同的源文件。項目會維護這些不同文件的列表,並當你要建立下一個新的可執行程序時,在必要時編譯它們。
它會記住針對你的應用程序所使用的編譯器和連接器選項。例如,它會記住把哪個庫連接到了執行程序中,你是否預編譯了頭文件等等。
它會記住你想要建立的項目類型: 一個控制台應用程序,或一個窗口應用程序等等。
如果你已經對項目文件有所了解,則會很容易明白作為機器產生的項目文件的作用。現在,我們來建立一個簡單的項目,並用它來編譯 HELLO.CPP。
為此,首先從“File”菜單中選擇“New”選項。在“Projects”標簽中,加單擊“Win32 Application”。在“Location”域中輸入一個合適的路徑名或單擊“Browse”按鈕來選擇一個。在“Project name”中輸入“hello”作為項目名稱。這時候你會看到“hello”也會出現在“Location”域中。單擊“OK”按鈕。Visual C++ 會建立一個新的稱為HELLO的目錄,並把所有的項目文件 HELLO.OPT、HELLO.NCB、HELLO.DSP 和 HELLO.DSW 都放到該目錄中。如果你退出,以後再重新打開該項目,則可選擇 HELLO.DSW。
現在,在屏幕的左邊,出現了三個標簽。InfoView 標簽仍然在,又新出現了 ClassView 和 FileView 標簽。ClassView 標簽會把你程序中所有的類都列出來,FileView 標簽給出了項目中文件的列表。
現在可以輸入程序的代碼了。在“File”菜單中選擇“New”選項來建立一個編輯窗口。在出現的對話框中,選擇“Files”標簽和“Text File”。則會出現 Visual C++ 的智能編輯器,你可以用它來輸入上面的程序代碼。輸入代碼時,你會發現編輯器會自動把不同類型的文本變成不同的顏色,如注釋、關鍵字字符串等的顏色都不同。如果你要改變其顏色或關閉顏色功能,可選擇“Tools”菜單中“Options”選項,然後選擇“Format”標簽和“Source Windows”選項就可以修改。
輸入完代碼後,選擇“File”菜單中的“Save”選項來保存。在 Visual C++ 新建立的目錄中,把它存成 HELLO.CPP 文件。
現在選擇在“Project”菜單中選擇“Add To Project”選項,再選“Files...”。你會看到一個對話框供你選擇要添加的文件。在本例子中,選擇 HELLO.CPP 文件。
在屏幕的左邊,單擊 FileView 標簽,並雙擊標有 HELLO 的圖標。你會看到名為 HELLO.CPP 的文件。單擊 ClassView 標簽,並雙擊文件夾圖標,你會看到程序中所有的類。任何時候你都可以使用 FileView 來刪除項目的文件,你只要單擊該文件,然後按鍵盤上的 delete 鍵。
後,此時你必須告訴項目要使用MFC庫。如果你忽略了這一步,則項目在連接時會出錯,而出錯信息對你毫無幫助。選擇“Project”菜單的“Settings”。在出現的對話框中選擇“General”標簽。在“Microsoft Foundation Classes”組合框中,選擇“Use MFC in a Shared DLL”。然後關閉對話框。
我們已經建立了項目文件,並調整了設置,你現在可以准備編譯 HELLO.CPP 程序了。在“Build”菜單中,你會發現有三個不同的編譯選項:
Compile HELLO.CPP (只有當含有 HELLO.CPP 的窗口處於激活狀態時才可)
Build HELLO.EXE
Rebuild All
第一個選項只是編譯源文件並形成它們的目標文件。該選項不能完成連接任務,所以它只對快速編譯一些源文件以檢查錯誤有用。第二個選項編譯自上次編譯後所修改的所有源文件,並連接形成可執行文件。第三個選項要重新編譯和連接所有的源文件。
我們可以選擇“Build HELLO.EXE”來編譯和連接代碼。Visual C++ 會建立一個名為“Debug”的新子目錄,並把 HELLO.EXE 放在該目錄中。該子目錄的文件都是可以再產生的,所以你可以任意刪除它們。
如果你發現了編譯錯誤,雙擊輸出窗口中的錯誤信息。這時編輯器會把你帶到出錯的位置處。檢查你的代碼是否有問題,如果有,就修改之。如果你看到大量的連接錯誤,則可能你在建立項目對話框中所指定的項目類型不對。你可以把該項目所在的子目錄刪除,然後再重新按上面的步驟來建立。
為了執行該程序,你可選則“Build”菜單中的“Execute HELLO.EXE”選項。你就可以看到你的第一個MFC程序了 -- 出現一個帶有“hello world”的窗口。該窗口本身帶有:標題欄、尺寸縮放區、最大和最小按鈕等等。在窗口上,有一個標有“hello world”。請注意,該程序是完整的。你可以移動窗口、縮放窗口、最小化等。你只使用了很少的代碼就完成了一個完整的 Window 應用程序。這就是使用 MFC 的優點。所有的細節問題都有MFC來處理。
結論
在本講中,你已經成功地編譯和執行了你的第一個 MFC 程序。你將來會用類似的步驟來建立的應用程序。你可以為每個項目建立單獨的目錄,或建立一個單獨的項目文件,然後再添加或刪除不同的源文件。
在下一講中,我們將仔細研究該程序,你會更完整的理解它的結構。