?? chap2_4.htm
字號:
<p><span style="font-size: 9pt">class CObject</span></p>
<p><span style="font-size: 9pt">{</span></p>
<p><span style="font-size: 9pt">public:</span></p>
<p><span style="font-size: 9pt">// Object model (types, destruction, allocation)</span></p>
<p><span style="font-size: 9pt">virtual CRuntimeClass* GetRuntimeClass() const;</span></p>
<p><span style="font-size: 9pt">virtual ~CObject(); // virtual destructors are necessary</span></p>
<p><span style="font-size: 9pt">// Diagnostic allocations</span></p>
<p><span style="font-size: 9pt">void* PASCAL operator new(size_t nSize);</span></p>
<p><span style="font-size: 9pt">void* PASCAL operator new(size_t, void* p);</span></p>
<p><span style="font-size: 9pt">void PASCAL operator delete(void* p);</span></p>
<p><span style="font-size: 9pt">#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)</span></p>
<p><span style="font-size: 9pt">// for file name/line number tracking using DEBUG_NEW</span></p>
lpszFileName, int nLine);</span></p>
<p><span style="font-size: 9pt">#endif</span></p>
<p><span style="font-size: 9pt">// Disable the copy constructor and assignment by default
so you will get</span></p>
<p><span style="font-size: 9pt">// compiler errors instead of unexpected behaviour if you
pass objects</span></p>
<p><span style="font-size: 9pt">// by value or assign objects.</span></p>
<p><span style="font-size: 9pt">protected:</span></p>
<p><span style="font-size: 9pt">CObject();</span></p>
<p><span style="font-size: 9pt">private:</span></p>
<p><span style="font-size: 9pt">CObject(const CObject& objectSrc); // no
implementation</span></p>
<p><span style="font-size: 9pt">void operator=(const CObject& objectSrc); // no
implementation</span></p>
<p><span style="font-size: 9pt">// Attributes</span></p>
<p><span style="font-size: 9pt">public:</span></p>
<p><span style="font-size: 9pt">BOOL IsSerializable() const;</span></p>
<p><span style="font-size: 9pt">BOOL IsKindOf(const CRuntimeClass* pClass) const;</span></p>
<p><span style="font-size: 9pt">// Overridables</span></p>
<p><span style="font-size: 9pt">virtual void Serialize(CArchive& ar);</span></p>
<p><span style="font-size: 9pt">// Diagnostic Support</span></p>
<p><span style="font-size: 9pt">virtual void AssertValid() const;</span></p>
<p><span style="font-size: 9pt">virtual void Dump(CDumpContext& dc) const;</span></p>
<p><span style="font-size: 9pt">// Implementation</span></p>
<p><span style="font-size: 9pt">public:</span></p>
<p><span style="font-size: 9pt">static const AFX_DATA CRuntimeClass classCObject;</span></p>
<p><span style="font-size: 9pt">#ifdef _AFXDLL</span></p>
<p><span style="font-size: 9pt">static CRuntimeClass* PASCAL _GetBaseClass();</span></p>
<p><span style="font-size: 9pt">#endif</span></p>
<p><span style="font-size: 9pt">};</span></p>
<p><span style="font-size: 9pt">CObject類為派生類提供了下述服務(wù):</span></p>
<blockquote>
<p><span style="font-size: 9pt">對象診斷</span></p>
<p><span style="font-size: 9pt">MFC提供了許多診斷特性,它可以:</span></p>
<p><span style="font-size: 9pt">輸出對象內(nèi)部信息:CDumpContext類與CObject的成員函數(shù)Dump配合,用于在調(diào)試程序時輸出對象內(nèi)部數(shù)據(jù)。</span></p>
<p><span style="font-size: 9pt">對象有效性檢查:重載基類的AssertValid成員函數(shù),可以為派生類的對象提供有效性檢查。</span></p>
<p><span style="font-size: 9pt">運(yùn)行時訪問類的信息:</span></p>
<p ALIGN="JUSTIFY"><span style="font-size: 9pt">MFC提供了一個非常有用的特性,它可以進(jìn)行運(yùn)行時的類型檢查。如果從CObject派生出一個類,并使用了以下三個宏(IMPLEMENT_DYNAMIC,IMPLEMENT_
DYNCREATE或IMPLEMENT_SERIAL)之一,就可以:</span></p>
<p><span style="font-size: 9pt">運(yùn)行時訪問類名</span></p>
<p><span style="font-size: 9pt">安全可靠的把通用的CObject指針轉(zhuǎn)化為派生類的指針</span></p>
<p><span style="font-size: 9pt">比如,我們定義一個主窗口類</span></p>
<p><span style="font-size: 9pt">CMyFrame:public CFrameWnd</span></p>
<p><span style="font-size: 9pt">{</span></p>
<p><span style="font-size: 9pt">......</span></p>
<p><span style="font-size: 9pt">}</span></p>
<p><span style="font-size: 9pt">然后我們使用這個類:</span></p>
<p><span style="font-size: 9pt">CMyFrame *pFrame=(CMyFrame*)AfxGetMainWnd();</span></p>
<p><span style="font-size: 9pt">pFrame->DoSomeOperation();</span></p>
<p ALIGN="JUSTIFY"><span style="font-size: 9pt">AfxGetMainWnd是一個全局函數(shù),返回指向應(yīng)用程序的主窗口的指針,類型為CWnd*,因此我們必須對它進(jìn)行強(qiáng)制類型轉(zhuǎn)換,但我們?nèi)绾沃朗欠褶D(zhuǎn)換成功了呢?我們可以使用CObject的IsKindOf()成員函數(shù)檢查pFrame的類型,用法如下:</span></p>
<p><span style="font-size: 9pt">ASSERT(pFrame->IsKindOf(RUN_TIMECLASS(CMyFrame)));</span></p>
<p><span style="font-size: 9pt">將上一語句插入到pFrame-> DoSomeOperation()之前,就可以在運(yùn)行時作類型檢查,當(dāng)類型檢查失敗時,引發(fā)一個斷言(ASSERT),中斷程序執(zhí)行。</span></p>
<p><span style="font-size: 9pt">對象持續(xù)性</span></p>
<p ALIGN="JUSTIFY"><span style="font-size: 9pt">通過與非CObject派生的檔案類CArchive相結(jié)合,提供將多個不同對象以二進(jìn)制形式保存到磁盤文件(Serilization)中以及根據(jù)磁盤文件中的對象狀態(tài)數(shù)據(jù)在內(nèi)存中重建對象(Deserilization
)的功能。</span></p>
</blockquote>
<p><span style="font-size: 9pt">然而,MFC不僅僅是一個類庫,它還提供了一層建立在Windows
API的C++封裝上的附加應(yīng)用程序框架。該框架提供了Windows程序需要的多數(shù)公共用戶界面。</span></p>
<p><span style="font-size: 9pt">所謂應(yīng)用程序框架指的是為了生成一般的應(yīng)用所必須的各種軟組件的集成。應(yīng)用框架是類庫的一種超集。一般的類庫只是一種可以用來嵌入任何程序中的、提供某些特定功能(如圖象處理、串行通信)的孤立的類的集合,但應(yīng)用框架卻定義了應(yīng)用程序的結(jié)構(gòu),它的類既相互獨(dú)立,又相互依賴,形成一個統(tǒng)一的整體,可以用來構(gòu)造大多數(shù)應(yīng)用程序。中國用戶熟悉的Borland
C++的DOS下的Turbo Vision和Windows下OWL(Object Windows Language)都是應(yīng)用框架的例子。</span></p>
<p><span style="font-size: 9pt">下面我們舉個具體的例子來說明MFC所提供的應(yīng)用程序框架,程序如清單2.2。</span><b></p>
<p><span style="font-size: 9pt">清單2.2應(yīng)用程序框架示例</span></b></p>
<p><span style="font-size: 9pt">#include<afxwin.h></span></p>
<p><span style="font-size: 9pt">//derived an application class</span></p>
<p><span style="font-size: 9pt">class CMinMFCApp:public CWinApp</span></p>
<p><span style="font-size: 9pt">{</span></p>
<p><span style="font-size: 9pt">public:</span></p>
<p><span style="font-size: 9pt">BOOL InitInstance();</span></p>
<p><span style="font-size: 9pt">};</span></p>
<p><span style="font-size: 9pt">//Derive the main window class</span></p>
<p><span style="font-size: 9pt">class CMainWindow:public CFrameWnd</span></p>
<p><span style="font-size: 9pt">{</span></p>
<p><span style="font-size: 9pt">public:</span></p>
<p><span style="font-size: 9pt">CMainWindow();</span></p>
<p><span style="font-size: 9pt">DECLARE_MESSAGE_MAP()</span></p>
<p><span style="font-size: 9pt">};</span></p>
<p><span style="font-size: 9pt">BEGIN_MESSAGE_MAP(CMainWindow,CFrameWnd)</span></p>
<p><span style="font-size: 9pt">END_MESSAGE_MAP()</span></p>
<p><span style="font-size: 9pt">/*CMinMFCApp Member Functions*/</span></p>
<p><span style="font-size: 9pt">BOOL CMinMFCApp::InitInstance()</span></p>
<p><span style="font-size: 9pt">{</span></p>
<p><span style="font-size: 9pt">m_pMainWnd=new CMainWindow();</span></p>
<p><span style="font-size: 9pt">m_pMainWnd->ShowWindow(m_nCmdShow);</span></p>
<p> </p>
<p><span style="font-size: 9pt">m_pMainWnd->UpdateWindow(); </span></p>
<p><span style="font-size: 9pt">return TRUE;</span></p>
<p><span style="font-size: 9pt">}</span></p>
<p><span style="font-size: 9pt">/*CMainWindow member functions*/</span></p>
<p><span style="font-size: 9pt">CMainWindow::CMainWindow()//constructor</span></p>
<p><span style="font-size: 9pt">{</span></p>
<p><span style="font-size: 9pt">Create(NULL,</span></p>
<p><span style="font-size: 9pt">"Min MFC Application",</span></p>
<p><span style="font-size: 9pt">WS_OVERLAPPEDWINDOW,</span></p>
<p><span style="font-size: 9pt">rectDefault,</span></p>
<p><span style="font-size: 9pt">NULL,</span></p>
<p><span style="font-size: 9pt">NULL);</span></p>
<p><span style="font-size: 9pt">}</span></p>
<p><span style="font-size: 9pt">/*an instance of type CMinMFCApp*/</span></p>
<p><span style="font-size: 9pt">CMinMFCApp ThisApp;</span></p>
<p ALIGN="JUSTIFY"><span style="font-size: 9pt">清單2.2程序段定義了一個最小的MFC應(yīng)用程序所需的框架程序。其中聲明了CMinMFCApp類,它是從應(yīng)用程序類CWinApp中派生下來的;和窗口CMainWindow類,它是從框架窗口CFrameWnd類派生出來。我們還用CMinMFCApp定義了一個全局對象ThisApp。讀者也許會問,為什么沒有WinMain函數(shù)?因為MFC已經(jīng)把它封裝起來了。在程序運(yùn)行時,MFC應(yīng)用程序首先調(diào)用由框架提供的標(biāo)準(zhǔn)的WinMain函數(shù)。在WinMain函數(shù)中,首先初始化由CMinMFCApp定義的唯一的實例,然后調(diào)用CMinMFCApp繼承CWinApp的Run成員函數(shù),進(jìn)入消息循環(huán)。退出時調(diào)用CWinApp的ExitInstance函數(shù)。</span></p>
<p ALIGN="JUSTIFY"><span style="font-size: 9pt">由上面的說明可以看到,應(yīng)用程序框架不僅提供了構(gòu)建應(yīng)用程序所需要的類(CWinApp,CFrameWnd等),還定義了程序的基本執(zhí)行結(jié)構(gòu)。所有的應(yīng)用程序都在這個基本結(jié)構(gòu)基礎(chǔ)上完成不同的功能。</span></p>
<p><span style="font-size: 9pt">MFC除了定義程序執(zhí)行結(jié)構(gòu)之外,還定義了三種基本的主窗口模型:單文檔窗口,多文檔窗口和對話框作為主窗口。</span></p>
<p ALIGN="JUSTIFY"><span style="font-size: 9pt">Visual C++提供了兩個重要的工具,用于支持應(yīng)用程序框架,它們就是前面提到AppWizard和ClassWizard。AppWizard用于在應(yīng)用程序框架基礎(chǔ)上迅速生成用戶的應(yīng)用程序基本結(jié)構(gòu)。ClassWizard用于維護(hù)這種應(yīng)用程序結(jié)構(gòu)。</span><b></p>
<p></b><span style="font-size: 9pt"><font color="#3973DE">2.4.3 MFC的優(yōu)點</font></span></p>
<p><span style="font-size: 9pt">Microsoft MFC具有以下不同于其它類庫的優(yōu)勢:</span></p>
<blockquote>
<p><span style="font-size: 9pt">完全支持Windows所有的函數(shù)、控件、消息、GDI基本圖形函數(shù),菜單及對話框。類的設(shè)計以及同API函數(shù)的結(jié)合相當(dāng)合理。</span></p>
<p><span style="font-size: 9pt">使用與傳統(tǒng)的Windows API同樣的命名規(guī)則,即匈牙利命名法。</span></p>
<p><span style="font-size: 9pt">進(jìn)行消息處理時,不使用易產(chǎn)生錯誤的switch/case語句,所有消息映射到類的成員函數(shù),這種直接消息到方法的映射對所有的消息都適用。它通過宏來實現(xiàn)消息到成員函數(shù)的映射,而且這些函數(shù)不必是虛擬的成員函數(shù),這樣不需要為消息映射函數(shù)生成一個很大的虛擬函數(shù)表(V表),節(jié)省內(nèi)存。</span></p>
<p><span style="font-size: 9pt">通過發(fā)送有關(guān)對象信息到文件的能力提供更好的判定支持,也可確認(rèn)成員變量。</span></p>
<p><span style="font-size: 9pt">支持異常錯誤的處理,減少了程序出錯的機(jī)會</span></p>
<p><span style="font-size: 9pt">運(yùn)行時確定數(shù)據(jù)對象的類型。這允許實例化時動態(tài)操作各域</span></p>
<p><span style="font-size: 9pt">有較少的代碼和較快的速度。MFC庫只增加了少于40k的目標(biāo)代碼,效率只比傳統(tǒng)的C
Windows程序低5%。</span></p>
<p><span style="font-size: 9pt">可以利用與MFC緊密結(jié)合的AppWizard和ClassWizard等工具快速開發(fā)出功能強(qiáng)大的應(yīng)用程序。</span></p>
</blockquote>
<p> </p>
<p><span style="font-size: 9pt">另外,在使用MFC時還允許混合使用傳統(tǒng)的函數(shù)調(diào)用。</span></p>
<p><span style="font-size: 9pt">我們著重講解一下MFC對消息的管理,這是編寫MFC消息處理程序的基礎(chǔ)。</span><b></p>
<p></b><span style="font-size: 9pt"><font color="#3973DE">2.4.4 MFC對消息的管理</font></span></p>
<p><span style="font-size: 9pt">Windows消息的管理包括消息發(fā)送和處理。為了支持消息發(fā)送機(jī)制,MFC提供了三個函數(shù):SendMessage、PostMessage和SendDlgItemMessage。而消息處理則相對來說顯得復(fù)雜一些。MFC采用了一種新的機(jī)制取代C語言編程時對Windows消息的Switch/Case分支,簡化了Windows編程,使程序可讀性、可維護(hù)性大大提高。</span><b></p>
<p><span style="font-size: 9pt">MFC對消息的處理</span></b></p>
<p><span style="font-size: 9pt">MFC不使用用C語言編寫Windows程序時用的易產(chǎn)生錯誤的switch/case語句,而采用一種消息映射機(jī)制來決定如何處理特定的消息。這種消息映射機(jī)制包括一組宏,用于標(biāo)識消息處理函數(shù)、映射類成員函數(shù)和對應(yīng)的消息等。其中,用afx_msg放在函數(shù)返回類型前面,用以標(biāo)記它是一個消息處理成員函數(shù)。類若至少包含了一個消息處理函數(shù),那么還需要加上一個DECLARE_MESSAGE_MAP()宏,該宏對程序執(zhí)行部分所定義的消息映射進(jìn)行初始化。清單2.3演示了消息處理函數(shù)的例子:</span><b></p>
<p><span style="font-size: 9pt">清單2.3 消息處理函數(shù)例子</span></b></p>
<p><span style="font-size: 9pt">class CMainFrame:CFrameWnd{</span></p>
<p><span style="font-size: 9pt">public:</span></p>
<p><span style="font-size: 9pt">CMainFrame();</span></p>
<p><span style="font-size: 9pt">protected:</span></p>
<p><span style="font-size: 9pt">//{{AFX_MSG(CMainFrame)</span></p>
<p><span style="font-size: 9pt">afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);</span></p>
<p><span style="font-size: 9pt">afx_msg void OnEditCopy();</span></p>
<p><span style="font-size: 9pt">afx_msg void OnClose();</span></p>
<p><span style="font-size: 9pt">//}}AFX_MSG</span></p>
<p><span style="font-size: 9pt">DECLARE_MESSAGE_MAP()</span></p>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -