1 MFC概述 顧名思意,MFC應(yīng)用程序框架是以MFC作為框架基礎(chǔ)的,以此程序框架模式搭建起來的應(yīng)用程序在程序結(jié)構(gòu)組織上是完全不同于以前的Win32 SDK編程方式的。自20世紀(jì)90年代初問世以來,MFC一直試圖把Windows API函數(shù)封裝到類庫中個(gè)各個(gè)邏輯類中。MFC的這種封裝并非簡(jiǎn)單地對(duì)API函數(shù)進(jìn)行分組與打包,而是更多地通過類來試圖實(shí)現(xiàn)全部的系統(tǒng)策略。隨著越來越多系統(tǒng)功能的加入,MFC的規(guī)模也在不斷拓展,目前已包括有200多個(gè)類,涵蓋了通用Windows 類、文檔/視框架、OLE、數(shù)據(jù)庫、Internet以及分布式功能等多方面的基本內(nèi)容。這樣一個(gè)堅(jiān)實(shí)的程序開發(fā)基礎(chǔ)無疑從很大程度上方便了程序設(shè)計(jì)人員對(duì)Windows 程序的開發(fā)。 MFC提供了相當(dāng)多不同功能的類以適合盡可能廣泛的需求。這里絕大多數(shù)的MFC類都是直接或間接從CObject類派生出來的,CObject類為其派生類提供了三個(gè)重要的特性支持:持久性(Serialization)支持、運(yùn)行時(shí)(Run-time)類信息支持和診斷(Diagnostic)調(diào)試支持等。其中持久性是以流的方式將某個(gè)類對(duì)象中的持久性數(shù)據(jù)輸出或輸入到外部存儲(chǔ)介質(zhì)如磁盤文件等的過程;運(yùn)行時(shí)類信息(Run-time Class Information,RTCI)則可以重新獲取一個(gè)對(duì)象的類名及其他一些有關(guān)對(duì)象在運(yùn)行時(shí)的信息。RTCI也是C++中除運(yùn)行時(shí)類型信息(Run-time Type Information,RTTI)機(jī)制外的另一個(gè)重要工具;診斷和調(diào)試支持作為CObject類的一個(gè)組成部分,可以在實(shí)現(xiàn)CObject派生類時(shí)執(zhí)行有效性檢查并可向調(diào)試窗口輸出狀態(tài)信息。 并非MFC提供的所有函數(shù)都是類成員函數(shù),MFC也提供了一系列以Afx為前綴的全局函數(shù)。類成員函數(shù)只能在其所屬類對(duì)象所在的上下文中使用,但是這些AFX函數(shù)卻可以在任何時(shí)候的任何地方直接使用。下表列出的是幾個(gè)比較重要AFX函數(shù): 函數(shù)名 函數(shù)說明 AfxAbout 無條件終止一個(gè)應(yīng)用程序;通常在發(fā)生無法回復(fù)的錯(cuò)誤時(shí)使用 AfxBeginThread 創(chuàng)建一個(gè)新的線程并開始執(zhí)行 AfxEndThread 終止當(dāng)前正在執(zhí)行的線程 AfxMessageBox 顯示一個(gè)Windows 消息窗口 AfxGetApp 返回一個(gè)指向應(yīng)用程序?qū)ο蟮闹羔? AfxGetAppName 返回應(yīng)用程序名 AfxGetMainWnd 返回一個(gè)指向應(yīng)用程序主窗口的指針 AfxGetInstanceHandle 返回一個(gè)標(biāo)識(shí)當(dāng)前應(yīng)用程序?qū)嵗木浔? AfxRegisterWndClass 為一個(gè)MFC應(yīng)用程序注冊(cè)一個(gè)用戶自定義的窗口類 2 MFC對(duì)API函數(shù)的封裝 如果讀者曾經(jīng)有過SDK的開發(fā)經(jīng)歷,一定會(huì)對(duì)其煩瑣的編程方式和大量的Win32 API函數(shù)調(diào)用深有感觸。所有不同功能的API函數(shù)均是以全局函數(shù)的形式放在一起的,由于API函數(shù)數(shù)目比較龐大,因此無論是學(xué)習(xí)還是使用都是有一定難度的。相比而言,建立在API函數(shù)基礎(chǔ)之上的MFC類庫則通過把相關(guān)API函數(shù)的分類封裝而可以大大簡(jiǎn)化編程的難度,用MFC類編寫的Windows 應(yīng)用程序完成相同的任務(wù)只需要進(jìn)行少量的工作。 眾多的API函數(shù)根據(jù)功能的不同而被MFC封裝到200多個(gè)類中,這些類基本涵蓋了進(jìn)行Windows 編程大部分可能用到的功能。由于封裝后的MFC類太多,這里不能一一介紹,下面就以其中比較重要的CObject類和CWnd類為例對(duì)API函數(shù)的封裝情況做一簡(jiǎn)要介紹。 CObject類是MFC中最主要也是最基本的類之一,該類不支持多重繼承,派生的類只能有一個(gè)CObject基類。CObject類是位于類層次結(jié)構(gòu)最頂層的,絕大多數(shù)MFC類都是從CObject類派生出來的。CObject類包含了所有MFC類必須具備的幾個(gè)基本功能:持久性支持、運(yùn)行時(shí)類信息支持和診斷調(diào)試支持。其中持久性支持功能由成員函數(shù)IsSerializable()和Serialize()提供。前者用于檢測(cè)對(duì)象是否支持序列化。如果一個(gè)類能夠被序列化,就必須在聲明時(shí)包含DECLARE_SERIAL宏、在實(shí)現(xiàn)時(shí)包含IMPLEMENT_SERIAL宏。Serialize()函數(shù)則可以將對(duì)象寫入檔案文件(Archive)或從檔案文件讀出對(duì)象。成員函數(shù)GetRuntimeClass()可以獲取到一個(gè)指向CruntimeClass類對(duì)象的指針,通過該指針可以得到對(duì)象的運(yùn)行時(shí)類信息。CObject類在診斷調(diào)試支持方面提供了成員函數(shù)AssertValid()和Dump(),前者可對(duì)對(duì)象內(nèi)存狀態(tài)的有效性進(jìn)行檢查,后者負(fù)責(zé)將對(duì)象的內(nèi)容轉(zhuǎn)儲(chǔ)到一個(gè)CdumpContext對(duì)象中,并可以提供診斷服務(wù)及一些有用的調(diào)試信息。 在MFC中,CWnd類提供了所有窗口類的基本功能,是一個(gè)非常重要的類,大約三分之一的MFC類都是以此為基類。該類主要對(duì)創(chuàng)建、操縱窗口類的API函數(shù)進(jìn)行了封裝,而且通過消息映射機(jī)制隱藏了SDK編程中使用相當(dāng)不便的窗口處理函數(shù),是消息的分發(fā)處理更加方便。 CWnd類最重要的一個(gè)封裝是對(duì)API函數(shù)CreateWindow()的封裝,該函數(shù)被封裝為CWnd類成員函數(shù)Create()。從VC提供的MFC源文件WinCore.cpp中可以清楚看出CWnd類對(duì)CreateWindow()函數(shù)的封裝過程,下面給出相關(guān)部分的實(shí)現(xiàn)清單: BOOL CWnd::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { // can't use for desktop or pop-up windows (use CreateEx instead) ASSERT(pParentWnd != NULL); ASSERT((dwStyle & WS_POPUP) == 0); return CreateEx(0, lpszClassName, lpszWindowName, dwStyle | WS_CHILD, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pParentWnd->GetSafeHwnd(), (HMENU)nID, (LPVOID)pContext); } 可以看出,主要工作是在CreateEx()成員函數(shù)中完成的,而該函數(shù)又是對(duì)API函數(shù)CreateWindowEx()的封裝。封裝后的代碼在調(diào)用CreateWindowEx()前構(gòu)造并填充了一個(gè)非常類似于WNDCLASS結(jié)構(gòu)的CREATESTRUCT結(jié)構(gòu),并調(diào)用了PreCreateWindow()。 BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam) { // allow modification of several common create parameters CREATESTRUCT cs; cs.dwExStyle = dwExStyle; cs.lpszClass = lpszClassName; cs.lpszName = lpszWindowName; cs.style = dwStyle; cs.x = x; cs.y = y; cs.cx = nWidth; cs.cy = nHeight; cs.hwndParent = hWndParent;
4 小結(jié) |
|