?
了解如何使用 windows API 函數編程后,對 windows 應用程序的大體結構框架有初步的認識。但是直接使用 windows API 進行編程程序員需要自己編寫大量代碼。像我這種從一開始接觸程序開發就是學習的 OO 的人來說,實在是無法忍受。從現在開始,我把重點轉到 VC++ 的另一方面,利用 MFC 進行和向導來編寫 windows 程序。
MFC ( Microsoft Foundation Class ) 是用來編寫 windows 應用程序的 C++ 類集,它封裝了大量的 windows API 函數和 windows 控件,并且以層次結構組織起來。使程序員在開發時能方便的進行代碼重用,加快開發速度并提高代碼的可靠性。
應該注意的是 MFC 是 使用C++語言實現的一個類庫,但并非是進行GUI程序設計的唯一標準。
有 OO 基礎或者是學習過 JAVA 語言理解 MFC 的體系結構會比較輕松。目前, MFC 中包含了大約 100 多個類,通過定義類對象并調用對象的成員函數來實現相應的功能。
下面簡要介紹一下 MFC 的類組織結構:
1.???????? 根類 CObject
MFC 中絕大多數類和自定義子類的根類,它提供了許多編程所需要的公共操作如:對象建立和刪除、串行化支持、對象診斷、運行時信息以及集合類的兼容等
2.???????? 命令相關類 CCmdTarget
它是 CObject 的直接子類,它是 MFC 中具有消息映射屬性的基類。一般很少需要程序員直接從 CcmdTarget 直接派生新類。
3.???????? 線程基類 CWinThread
所有線程的基類,可以直接使用,它封裝了操作系統的線程化功能。
4.???????? 窗口應用程序類 CWinApp
每個應用程序有且只有一個應用程序對象,在運行程序中該對象與其它對象相互協調,該對象從 CwinApp 類中派生而來。它封裝了初始化,運行,終止應用程序的代碼。
5.???????? 文檔 / 視類 CDocument/CView
文檔對象由文檔模板對象創建,管理應用程序的數據。 CDocument 支持標準的文檔操作,這些操作包括文檔創建、下載、保存等。一個應用程序可以操作多種文檔類型,每一種文檔類型都有特定的文檔模板( document template )。
用戶通過文檔和相關聯的視圖對象( CView object )與文檔進行交互。一個視圖顯示文檔中的信息,并把用戶在框架窗口內的操作轉換成對文檔操作的相應命令。當用戶打開一個文檔時,應用程序實際上創建了一個視圖并把這個視圖和相應的文檔聯系在一起。一個視圖充當了溝通用戶和文檔對象的中間橋梁的作用。
6.???????? 可視對象類 CWnd
該類提供了 MFC 中所有窗口類的基本功能,它的消息映射機制隱藏了窗口函數 WndProc 。一個 windows 消息通過消息映射發送到相應的 CWnd 類的 OnMessage 成員函數,通過重載 OnMessage 函數來對特定的消息進行處理。
CWnd 類有許多經常使用的子類,如 CMenu 類, CDialog 類, CButton 類等等。
7.???????? 通用類
通用類提供了許多共用服務,例如文件 I/O ( CFile 類和 CArchive 類)、異常處理( CException 類)等。
8.???????? OLE 類
OLE1.0 規范是 MS 在 1991 年發布的。它是處理復合文檔的一種方法: Object Linking and Embedding 技術。所謂復合文檔,就是在一個文檔中同時保存了如文本、圖像和聲音等多種不同類型的數據,而這些數據又可以通過不同的應用程序用不同的格式產生。
1993 年發布的 OLE2.0 是基本對象的一整套體系結構,能夠擴展、定制和增強服務功能,它的理論基礎是 COM 技術。
此外, ActiveX 也是一種對 OLE 技術的擴展,它使 OLE 進入 Internet 和 Intranet 。
9.???????? ODBC 類
為了支持帶有 ODBC 驅動程序的各種數據庫管理系統, MFC 也提供了 Cdatabase 和 CRecordset 類,用于管理數據庫的連接及其操作。
10.???? MFC 中全局函數和變量
在 MFC 中提供的全局函數和變量一般都以 Afx 開頭,它們可以在 MFC 應用程序的任務地方中使用,如: AfxAbort 、 AfxMessageBox 等等。
在使用 VC 生成 MFC 應用程序時, IDE 會自動生成許多代碼,以一個簡單的對話框程序為例,將會有如下幾個主要的文件:
stdafx.h/cpp ??????????????? 標準系統包含文件,或是常使用但不常更改的
MFCles1.h/.cpp??????????? 應用程序類
MFCles1Dlg.h/cpp??????? 對話框類
Resource.h?????????????????? 資源頭文件,被 MFCles1.rc 所使用
???????????
MFC
應用程序的一般結構
就設計模式來看, MFC 應用程序是一個標準的單例模式。每一個應用程序有且僅有一個實例對象: theApp
程序執行的基本流程,就我現在的理解而言:
首先應該從在應用程序體系結構類中聲明的一個全局實例對象
theApp
入手(C++里的全局類對象初始化在main函數之前),在進入CWinApp類的構造函數之后,程序才進入原來Windows API里的那個入口函數:AfxWinMain。
我們在寫MFC程序時并沒有顯示的指出WinMain入口函數的位置。這個函數的定義被安置在了APPMODUL.CPP文件里(這一文件位于VS安裝目錄下的VC98目錄里的MFC源文件里)。每個app實例被構造后,會產調用相應的InitInstance函數進行初始化。原來的注冊窗口類的工作被放在了WINCORE.CPP文件里的AfxEndDeferRegisterClass函數,這里MFC已經為我們定義好了幾種默認的窗口類。然后就會調用CPreCreateWnd函數進行窗口的顯示工作。最后,使用CWinThread::Run方法啟動消息循環,至此,整個窗口應用程序就運行起來了。windows應用程序可以被同時多次運行,第一次運行完成初始化工作后,以后每次運行程序拷貝都全調用InitInstance函數進行初始化工作。
class CMFCles1App : public CWinApp
{
public:
?????? CMFCles1App();
// 重寫一些父類方法
?????? public:
?????? virtual BOOL InitInstance();
// 實現消息映射的宏
?????? DECLARE_MESSAGE_MAP()
};
extern CMFCles1App theApp;// 代碼應用程序本身
以一個簡單的對話框程序為例,在InitInstance函數里完成了以下工作
CMFCles1Dlg dlg;
??? m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
第一行聲明了一個對話框類對象,第二行將其賦值給當前應用程序類的成員變量,這是一個指向主窗口的指針,最后一行顯示窗口。
了解了一點關于應用程序類的知識后,再來分析剩下的與GUI有關的另一個類,這里使用一個對話框類作一點說明。
同樣, MFCles1Dlg 則派生自 CDialog 類
class CMFCles1Dlg : public CDialog
{
public:
?????? CMFCles1Dlg(CWnd* pParent = NULL);??? // 標準構造函數
protected:
?????? HICON m_hIcon;// 應用程序圖標的句柄
DECLARE_MESSAGE_MAP()
?????? // 生成的消息映射函數
?????? virtual BOOL OnInitDialog();
?????? afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
?????? afx_msg void OnPaint();
?????? afx_msg HCURSOR OnQueryDragIcon();
};
DECLARE_MESSAGE_MAP() 是一個用來定義消息映射的宏,而下面以 afx_msg 開頭的函數都是消息的響應函數,這比起 API 里面把消息都寫在一些 switch 語句中要更清楚,也方便了修改。要實現對話框對消息的響應還需要在類中加上這兩行
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
所有的消息映射函數都要寫在這兩行之間,例如ON_WM_RBUTTONDOWN( )就定義了一個右鍵按下的消息映射。MFC已經有了預定義好了許多消息映射函數的格式,需要查看可以參考MSDN。