




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第3章MFC應(yīng)用程序框架ForwithyNew本章各小節(jié)目錄3.1MFC程序根本框架類和文件組成3.2MFC應(yīng)用程序中各個(gè)框架類的作用3.3MFC應(yīng)用程序的執(zhí)行步驟分析3.4MFC應(yīng)用程序設(shè)計(jì)結(jié)構(gòu)體系剖析在第2章小節(jié)用MFCAppWizard生成了一個(gè)完整的MFC應(yīng)用程序Draw。相信讀者在生成并對(duì)它編譯執(zhí)行時(shí),對(duì)執(zhí)行的結(jié)果是滿意的,對(duì)用MFC編程一定會(huì)產(chǎn)生濃厚的興趣。你可能會(huì)迫不及待的翻開的源代碼文件,尋找實(shí)際的執(zhí)行代碼。結(jié)果又肯定會(huì)讓你感到大失所望。第一次翻開這些文件時(shí),你可能覺(jué)得自己在看一些甲骨文的書籍,你連程序是從哪里執(zhí)行,怎么執(zhí)行的都無(wú)法找到,無(wú)法弄明白。不要失望,本章將對(duì)MFC應(yīng)用程序的結(jié)構(gòu)和工作流程進(jìn)行分析。在以后的各章,將以一個(gè)根本GIS的開發(fā)為例,引導(dǎo)讀者掌握MFC應(yīng)用程序設(shè)計(jì)的核心技術(shù)。3.1MFC程序根本框架類和文件組成3.1.1根本程序框架類通過(guò)對(duì)應(yīng)用程序Draw進(jìn)行分析,可知普通的MFC應(yīng)用程序包含著以下四個(gè)主要的類:文檔類、視圖類、主框架窗口類、應(yīng)用類。程序的主要任務(wù)在這四個(gè)類中分配,AppWizard為每個(gè)類產(chǎn)生了各自的源文件。C++類在文件組織上一般分為兩局部:頭〔包含〕文件〔.h〕和實(shí)現(xiàn)文件〔.cpp〕。頭文件是.h文件,一般用來(lái)存放類、結(jié)構(gòu)等的定義代碼,通過(guò)include宏插入到實(shí)現(xiàn)文件中。實(shí)現(xiàn)文件是通常所見(jiàn)的.cpp文件,用來(lái)存放類的成員函數(shù)的實(shí)際代碼?!?〕文檔類應(yīng)用程序Draw的文檔類名稱是CDrawDoc,這是AppWizard根據(jù)工程名稱默認(rèn)取的名稱,它是由MFC的Cdocument派生的。CDrawDoc類的頭文件是drawdoc.h,實(shí)現(xiàn)文件是drawdoc.cpp。頭文件中存放的是類的定義代碼,實(shí)現(xiàn)文件中存放的是類的各個(gè)成員函數(shù)的實(shí)現(xiàn)代碼。文檔類負(fù)責(zé)存放程序數(shù)據(jù)并讀取磁盤文件數(shù)據(jù),或?qū)⒋疟P文件數(shù)據(jù)寫入磁盤文件中。在建立一個(gè)應(yīng)用程序工程時(shí),在文檔類中對(duì)應(yīng)用程序所需要的數(shù)據(jù)資料進(jìn)行管理?!?〕視圖類應(yīng)用程序Draw中視圖類的名稱是CDrawView,它是由MFC的Cview類派生的。CDrawView類的頭文件是drawview.h,實(shí)現(xiàn)文件是drawview.cpp。視圖類負(fù)責(zé)顯示文檔類中的數(shù)據(jù),可以顯示在屏幕上,也可以輸出到打印機(jī)或其他設(shè)備上。視圖類也負(fù)責(zé)處理用戶的輸入。在一個(gè)矢量圖形系統(tǒng)中,在屏幕上顯示、在打印機(jī)上繪制圖形的操作功能都是由視圖類完成的?!?〕框架類在使用AppWizard生成應(yīng)用程序Draw時(shí),選擇的是一個(gè)多文檔選項(xiàng)〔在圖2-3中,選擇的是Multipledocuments選項(xiàng)〕,所以應(yīng)用程序Draw中包含著兩個(gè)框架類:主框架類CMainFrame和子框架類CChildFrame。主框架類CMainFrame是由MFC的CMDIFrameWnd類派生的,其頭文件是mainfrm.h,實(shí)現(xiàn)文件是mainfrm.cpp。主框架類CMainFrame提供了管理一個(gè)多文檔界面〔MDI〕的主窗口的所有功能及管理窗口中的子窗口,用來(lái)顯示一個(gè)標(biāo)題、一個(gè)菜單條、窗口最大化和最小化鍵、邊框、一個(gè)系統(tǒng)菜單、工具條以及狀態(tài)條等。子框架類CChildFrame是由MFC的CMDIChildWnd類派生的,其頭文件是childfrm.h,實(shí)現(xiàn)文件是childfrm.cpp。子框架類的功能是用來(lái)管理子窗口。一個(gè)子窗口非常像主窗口,但子窗口僅能在主窗口內(nèi)顯示,而不在Windows桌面上,子窗口沒(méi)有自己的菜單條,但它分享主窗口的菜單,程序自動(dòng)將框架窗口菜單作為當(dāng)前子窗口的菜單?!?〕應(yīng)用類應(yīng)用程序Draw的應(yīng)用類是CDrawApp,它是由MFC的CWinApp類派生的。其頭文件是draw.h,實(shí)現(xiàn)文件是draw.cpp。應(yīng)用類負(fù)責(zé)管理程序的總體,它完成不屬于任何其他三類的一般工作,例如初始化程序以及進(jìn)行最后的程序去除工作。每個(gè)MFC應(yīng)用程序必須正確的生成由CWinApp派生類的一個(gè)實(shí)例〔對(duì)象〕。3.1.2應(yīng)用程序主要源文件組成在組成應(yīng)用程序Draw的源文件中,除了五個(gè)主要類的源文件外〔10個(gè)源文件〕,還有其他一些文件,對(duì)他們簡(jiǎn)述如下:draw.rc資源定義文件,包含程序資源的定義〔菜單、對(duì)話框、字串、鍵盤加速鍵和圖標(biāo)等〕。一般情況下,這個(gè)文件是由AppStudio進(jìn)行可視化編輯維護(hù),一般不用手工修改這個(gè)文件。draw.dsw工作區(qū)信息文件,存儲(chǔ)著一個(gè)工作區(qū)的組成情況〔如包含哪些程序工程、程序工程的依賴關(guān)系等〕,用來(lái)存儲(chǔ)和翻開一個(gè)工作區(qū)。draw.clwClassWizard信息存儲(chǔ)文件,存儲(chǔ)ClassWizard編輯存在的類和增加新類的信息,文件也包含了ClassWizard建立和編輯各種消息處理函數(shù)和映射變量等的信息。draw.dsp程序工程工程文件,存儲(chǔ)著一個(gè)應(yīng)用程序工程所包含的具體信息,在翻開工程時(shí)用。makehelp.bat批處理文件,用來(lái)建立應(yīng)用程序的幫助文件hlp\draw.hlp。hlp\draw.hpj被幫助文件編輯器,用來(lái)建立系統(tǒng)的幫助文件時(shí)使用的工程文件。hlp\*.bmp位圖文件,被用來(lái)作為MFC標(biāo)準(zhǔn)命令幫助主題的位圖文件。hlp\*.rtf幫助主題文件,包含著MFC標(biāo)準(zhǔn)命令的幫助主題。res\draw.rc2資源定義文件,包含著不同AppStudio編輯的程序資源定義。當(dāng)手工〔而不是AppStudio〕定義程序資源時(shí),可以將資源定義在這個(gè)文件中。這個(gè)文件被插入〔#include〕在文件draw.rc中。res\draw.ico應(yīng)用程序的圖標(biāo)文件。最初,這個(gè)文件包含標(biāo)準(zhǔn)的“AFX”圖標(biāo)??梢杂肁ppStudio對(duì)圖標(biāo)進(jìn)行修改。res\toolbar.bmp工具條的位圖文件。stdafx.cpp和stdafx.h頂編譯文件,用于生成預(yù)編譯信息。resource.h資源ID號(hào)定義文件,這個(gè)文件與draw.rc相對(duì)應(yīng),包含程序資源中ID號(hào)的常量定義。一般也是由AppStudio自動(dòng)進(jìn)行維護(hù)的。draw.def它提供MicrosoftLINK程序進(jìn)行連接時(shí),用于準(zhǔn)備應(yīng)用程序文件的有關(guān)信息。一般不必編輯這個(gè)文件,因?yàn)樗m合于大多數(shù)MFCWindows程序的值。readme.txt
包含對(duì)所有該程序的源文件的解釋信息。3.2MFC應(yīng)用程序中各個(gè)框架類的作用以上討論了應(yīng)用程序Draw中包含的四個(gè)主要類及其文件組成。本節(jié)進(jìn)一步分析這個(gè)框架的組成及各個(gè)類的主要功能。學(xué)習(xí)VC++編程的人,特別是初學(xué)者,一定會(huì)感覺(jué)到程序的框架很難理解,即值有一定的理解,使用起來(lái)也不能得心應(yīng)手。作者根據(jù)實(shí)際的經(jīng)驗(yàn),舉一個(gè)可能并非完全恰當(dāng)?shù)谋扔鱽?lái)說(shuō)明一下程序的框架,使讀者對(duì)框架產(chǎn)生一個(gè)感性的認(rèn)識(shí)。假定有一些文稿,一塊黑板,一些工具盒,由這些組成了一個(gè)工作環(huán)境或平臺(tái)。程序框架中的四個(gè)主要的類所完成的工作可以如下理解:文檔類創(chuàng)立的對(duì)象負(fù)責(zé)文稿的管理工作,每個(gè)對(duì)象負(fù)責(zé)一份文稿的管理。在單文檔界面〔SDI〕中只有一份文稿,也就只需創(chuàng)立一個(gè)文檔對(duì)象負(fù)責(zé)文稿的管理工作;在多文檔程序框架〔MDI〕中可以有多份不同的文稿,那么就需要文檔類創(chuàng)立多個(gè)文檔對(duì)象來(lái)管理多份文檔,一個(gè)對(duì)象管理一份文檔資料。文稿中內(nèi)容的增加、刪除、修改、歸檔保存等管理和維護(hù)操作,都是由文檔類對(duì)象來(lái)完成的。框架類對(duì)象負(fù)責(zé)黑板的管理工作,黑板用來(lái)顯示文檔的內(nèi)容。一個(gè)主框架類的對(duì)象負(fù)責(zé)在黑板上劃出一個(gè)區(qū)域來(lái)〔主框架〕,在這個(gè)區(qū)域內(nèi),主框架類對(duì)象負(fù)責(zé)安排擺放如粉筆盒的位置等〔菜單、工具條、狀態(tài)條等的布置〕,同時(shí),主框架類對(duì)象又能夠在自己管轄范圍內(nèi)劃出一塊區(qū)域〔窗口〕交給一個(gè)子框架類對(duì)象來(lái)管理。這個(gè)子框架類對(duì)象把管理的窗口中劃出一局部交給一個(gè)視圖對(duì)象來(lái)使用〔客戶區(qū)〕,視圖對(duì)象可以在這個(gè)區(qū)域內(nèi)書寫內(nèi)容。在單文檔框架中,主框架類管理的區(qū)域內(nèi)只能分配一個(gè)區(qū)域〔窗口〕,此時(shí),只能有一個(gè)客戶區(qū)供一個(gè)視圖對(duì)象來(lái)使用。而在多文檔程序框架中,主框架類對(duì)象可以將黑板中分成多個(gè)區(qū)域〔窗口〕,每個(gè)區(qū)域交給一個(gè)子框架類對(duì)象來(lái)管理。子框架類對(duì)象將這個(gè)區(qū)域的一局部〔客戶區(qū)〕交給一個(gè)視圖對(duì)象來(lái)使用。主框架類根據(jù)需求來(lái)維護(hù)和管理這些區(qū)域,像區(qū)域的創(chuàng)立、刪除、改變大小等工作都是由主框架類來(lái)完成的。Windows下的窗口與黑板中的區(qū)域不同的是,窗口是可以任意重疊的。視圖類對(duì)象的作用是將文稿中的內(nèi)容進(jìn)行顯示,在黑板中創(chuàng)立的一個(gè)子窗口內(nèi)的客戶區(qū)被一個(gè)視圖類對(duì)象所使用。同時(shí),這個(gè)視圖類對(duì)象在創(chuàng)立時(shí)已經(jīng)被規(guī)定了是用來(lái)顯示哪份文稿的。它的任務(wù)是將這份文稿中的內(nèi)容顯示在黑板中其擁有的客戶區(qū)內(nèi)。在單文檔程序框架下,只有一份文檔,即只有一個(gè)文檔類對(duì)象,也只有一個(gè)視圖類對(duì)象,這個(gè)視圖類對(duì)象負(fù)責(zé)把文檔的內(nèi)容顯示到黑板上,如何顯示〔用文字還是用圖表現(xiàn),用大字還是小字,用紅粉筆還是白粉筆〕是由視圖類對(duì)象決定的。而在多文檔程序框架〔MDI〕下,情況復(fù)雜多了,這時(shí)可以有多份文稿,黑板中可以創(chuàng)立有多個(gè)子窗口區(qū)域:對(duì)于一份文稿,可以創(chuàng)立多個(gè)視圖類對(duì)象來(lái)顯示。例如,有兩份文檔,對(duì)其中的第一份創(chuàng)立了五個(gè)視圖類對(duì)象,對(duì)于另一份文檔創(chuàng)立了三個(gè)視圖類對(duì)象,這時(shí),就有八個(gè)視圖類對(duì)象,創(chuàng)立了八個(gè)子框架對(duì)象,管理黑板中創(chuàng)立的八個(gè)子窗口,五個(gè)視圖類對(duì)象顯示第一份文檔的內(nèi)容,三個(gè)視圖類對(duì)象顯示另一份文檔的內(nèi)容。一份文稿由多于一個(gè)視圖對(duì)象在不同窗口的區(qū)域〔客戶區(qū)〕上進(jìn)行顯示就是所謂的多視圖,有多于一個(gè)的文稿在不同的區(qū)域上被顯示就是多文檔。應(yīng)用類創(chuàng)立一個(gè)對(duì)象〔且只創(chuàng)立一個(gè)對(duì)象〕,負(fù)責(zé)建立并啟動(dòng)這個(gè)工作環(huán)境,建立起文檔、視圖、框架對(duì)象之間的相互聯(lián)系。如,當(dāng)建立或翻開一個(gè)文檔時(shí),文檔類會(huì)創(chuàng)立一個(gè)文檔類對(duì)象,框架類會(huì)創(chuàng)立一個(gè)子框架類對(duì)象,同時(shí)視圖類會(huì)創(chuàng)立一個(gè)視圖類對(duì)象,并建立了文檔、子框架及視圖類對(duì)象間的相互聯(lián)系。這些工作是由應(yīng)用類對(duì)象來(lái)完成的。對(duì)于一個(gè)多文檔MFC應(yīng)用程序,在程序運(yùn)行過(guò)程中,只有一個(gè)應(yīng)用類對(duì)象,一個(gè)主框架對(duì)象,可以有多個(gè)子框架類對(duì)象,多個(gè)文檔類對(duì)象和多個(gè)視圖類對(duì)象。子框架對(duì)象的數(shù)目與視圖類對(duì)象相同,文檔類對(duì)象可以比視圖、子框架類對(duì)象少,因?yàn)橐粋€(gè)文檔類對(duì)象可以有多個(gè)視圖類對(duì)象。在應(yīng)用程序Draw中,已經(jīng)建立起了窗口、視圖、文檔之間的關(guān)系,不用程序設(shè)計(jì)者再去建立這個(gè)框架。運(yùn)行“文件”菜單下的“新建”菜單項(xiàng),就會(huì)在主框架窗口內(nèi)產(chǎn)生一個(gè)子窗口,子窗口內(nèi)的區(qū)域〔客戶區(qū)〕屬于新建的視圖類對(duì)象,這個(gè)子窗口對(duì)應(yīng)著新建的空文檔。運(yùn)行“文件”菜單下的“翻開…”菜單項(xiàng),選擇翻開一個(gè)文檔時(shí),也會(huì)在主框架窗口內(nèi)產(chǎn)生一個(gè)子窗口,這個(gè)子窗口對(duì)應(yīng)的文檔是剛剛翻開的文檔。在應(yīng)用程序Draw中有翻開文檔的情況下,運(yùn)行“窗口”菜單下的“新建”菜單項(xiàng),也會(huì)在主框架窗口中產(chǎn)生子窗口,這個(gè)窗口中顯示的是當(dāng)前文檔的另外一個(gè)視圖。以上討論了程序框架中文檔、視圖、窗口間的關(guān)系和各主要類的作用。在實(shí)際的程序設(shè)計(jì)中,用的最多的是文檔、視圖類。在有些情況中,文檔類和視圖類的一些作用區(qū)分是不明顯的,特別是在單文檔編制程序的情況下。因?yàn)樵趩挝臋n情況下,只有一個(gè)文檔,也只有一個(gè)視圖,換句話說(shuō),文檔類和視圖類都是被實(shí)例化了一次,即都只創(chuàng)立了一個(gè)對(duì)象,所以有些數(shù)據(jù)和函數(shù)放在文檔類和視圖類中是一樣的。而在多文檔程序設(shè)計(jì)中就不一樣了,舉一個(gè)簡(jiǎn)單的例子,來(lái)說(shuō)明將變量定義在文檔類和視圖類的區(qū)別:如果有一個(gè)變量來(lái)控制文檔的顯示比例,這個(gè)變量定義在文檔類中時(shí),對(duì)于這個(gè)文檔類對(duì)象的多個(gè)視圖在顯示比例上時(shí)一樣的,一個(gè)視圖比例變化時(shí),其他屬于這個(gè)文檔類對(duì)象的視圖比例也發(fā)生變化。如果這個(gè)變量在視圖類中定義,多個(gè)視圖在顯示比例上就可以不一樣。所以,只有真正理解了視圖/文檔體系結(jié)構(gòu),才能隨心所欲的來(lái)組織程序。3.3MFC應(yīng)用程序的執(zhí)行步驟分析如果讀者熟悉傳統(tǒng)的程序設(shè)計(jì),面對(duì)由AppWizard生成的MFC應(yīng)用程序Draw,你肯定會(huì)問(wèn),Draw從哪里開始執(zhí)行的?從哪里吸收控制?在本書中,對(duì)這個(gè)問(wèn)題進(jìn)行簡(jiǎn)單的介紹。下面是一般MFC應(yīng)用程序運(yùn)行的主要步驟:①調(diào)用CWinApp類構(gòu)造函數(shù)。②程序入口函數(shù)WinMain接收控制。③WinMain調(diào)用程序的InitInstance函數(shù)進(jìn)行初始化。④WinMain進(jìn)入消息循環(huán),處理消息。⑤WinMain退出,程序終止。MFC應(yīng)用程序必須創(chuàng)立有且只有一個(gè)應(yīng)用類對(duì)象,在實(shí)現(xiàn)文件draw.cpp中可以找到一個(gè)全局創(chuàng)立的應(yīng)用程序類的對(duì)象:CDrawApptheApp;以下介紹應(yīng)用程序運(yùn)行的這幾個(gè)主要步驟?!?〕調(diào)用CWinApp類構(gòu)造函數(shù)由于應(yīng)用類對(duì)象theApp被創(chuàng)立成全局的,所以在程序入口函數(shù)WinMain接收控制前,先調(diào)用應(yīng)用類的構(gòu)造函數(shù)。在實(shí)現(xiàn)文件draw.cpp中可以找到應(yīng)用類CDrawApp的構(gòu)造函數(shù):CDrawApp::CDrawApp(){ //TODO:addconstructioncodehere, //PlaceallsignificantinitializationinInitInstance}在調(diào)用這個(gè)構(gòu)造函數(shù)時(shí),同時(shí)調(diào)用基類CWinApp的構(gòu)造函數(shù)完成構(gòu)造任務(wù)。將應(yīng)用類對(duì)象theApp創(chuàng)立成全局的,是為了在MFC中能夠?qū)WinApp的成員函數(shù)進(jìn)行調(diào)用?!?〕WinMain接受控制創(chuàng)立全局應(yīng)用類對(duì)象theApp后,程序入口函數(shù)WinMain接受控制。這個(gè)函數(shù)已經(jīng)在MFC中做了定義,在建立執(zhí)行文件時(shí)能夠鏈接到應(yīng)用程序Draw。WinMain完成的任務(wù)很多,下面介紹一些重要的任務(wù)。〔3〕調(diào)用函數(shù)InitInstance進(jìn)行初始化在WinMain得到控制后不久,就調(diào)用執(zhí)行應(yīng)用類CDrawApp類的成員函數(shù)InitInstance來(lái)進(jìn)行程序的初始化。在實(shí)現(xiàn)文件draw.cpp中可以找到InitInstance函數(shù)的實(shí)現(xiàn)代碼:BOOLCDrawApp::InitInstance(){AfxEnableControlContainer();
#ifdef_AFXDLL//當(dāng)把MFC作為一個(gè)動(dòng)態(tài)鏈接庫(kù)使用時(shí)Enable3dControls();//使Windows顯示具有三維外觀的控件#else//當(dāng)把MFC作為一個(gè)靜態(tài)庫(kù)使用時(shí)Enable3dControlsStatic();#endif//以下是程序注冊(cè)的關(guān)鍵字,可以改為用戶需要的信息SetRegistryKey(_T(“LocalAppWizard-GeneratedApplications”));LoadStdProfileSettings();//裝入標(biāo)準(zhǔn)初始化文件選擇CMultiDocTemplate*pDocTemplate;//定義一個(gè)多文檔模板對(duì)象的指針//創(chuàng)立一個(gè)文檔資料模板對(duì)象,并把指針保存在以上定義的指針中pDocTemplate=newCMultiDocTemplate(IDR_DRAWTYPE,RUNTIME_CLASS(CDrawDoc),//注冊(cè)文檔類RUNTIME_CLASS(CChildFrame),//注冊(cè)多文檔子框架窗口類RUNTIME_CLASS(CDrawView)//注冊(cè)視圖類);AddDocTemplate(pDocTemplate);//增加一個(gè)文檔模板//創(chuàng)立一個(gè)主框架窗口CMainFrame*pMainFrame=newCMainFrame;if(!pMainFrameLoadFrame(IDR_MAINFRAME))//裝入主框架returnFALSE;m_pMainWnd=pMainFrame;//Parsecommandlineforstandardshellcommands,DDE,fileopenCCommandLineInfocmdInfo;ParseCommandLine(cmdInfo);//取出運(yùn)行程序時(shí)的命令行//Dispatchcommandsspecifiedonthecommandlineif(!ProcessShellCommand(cmdInfo))//處理命令行returnFALSE;//Themainwindowhasbeeninitialized,soshowandupdateit.pMainFrame->ShowWindow(m_nCmdShow);//顯示主框架窗口pMainFrame->UpdateWindow();returnTRUE;}這個(gè)函數(shù)所完成的最主要任務(wù)如下:①創(chuàng)立并初始化了一個(gè)多文檔模板對(duì)象pDocTemplate,創(chuàng)立這個(gè)對(duì)象時(shí)用了四個(gè)參數(shù)。第一個(gè)參數(shù)是顯示和管理文檔的程序資源IDR_DRAWTYPE,就是在應(yīng)用程序Draw有翻開的文檔時(shí),顯示在主框架窗口的菜單、圖標(biāo)等資源〔可以翻開Draw.rc,在里面找到ID號(hào)是IDR_DRAWTYPE的資源〕。另外三個(gè)參數(shù)是文檔類、子框架類和視圖類的信息,通過(guò)MFC宏RUNTIME_CLASS取得。MFC應(yīng)用程序通過(guò)這些信息,在翻開或新建一個(gè)新文檔時(shí),分別生成一個(gè)文檔類、子框架類和視圖類的對(duì)象,并用第一個(gè)參數(shù)指定的資源進(jìn)行管理。②完成多文檔模板的創(chuàng)立后,程序產(chǎn)生了一個(gè)主框架窗口,創(chuàng)立主框架窗口時(shí)采用的是IDR_MAINFRAME資源。應(yīng)用程序Draw運(yùn)行時(shí),當(dāng)所有的文檔被關(guān)閉時(shí)顯示在屏幕上的資源就是IDR_MAINFRAME資源。在有翻開的文檔的情況下,這個(gè)資源被注冊(cè)到文檔模板類對(duì)象中的IDR_DRAWFRAME資源所代替。③創(chuàng)立主框架窗口后,程序?qū)⑻幚砻钚行畔?。命令行信息是跟隨在命令后的參數(shù)。如可以用如下的語(yǔ)句啟動(dòng)應(yīng)用程序Draw:Drawdraw1.dat//啟動(dòng)應(yīng)用程序Draw,并在啟動(dòng)后自動(dòng)翻開draw1.dat文件ParseCommandLine函數(shù)用來(lái)取得命令行,函數(shù)ProcessShellCommand處理命令行的信息。命令行參數(shù)存在,此函數(shù)會(huì)取出參數(shù)調(diào)用CWinApp的OnOpenDocument翻開參數(shù)指定的文檔;命令行參數(shù)不存在,那么調(diào)用CWinApp的OnOpenDocument函數(shù)創(chuàng)立新的文檔。不管是翻開文檔還是新建文檔,CWinApp都是通過(guò)調(diào)用多文檔模板來(lái)創(chuàng)立一個(gè)文檔類對(duì)象、一個(gè)子框架類對(duì)象和一個(gè)視圖類對(duì)象,并調(diào)用其相關(guān)的資源產(chǎn)生運(yùn)行界面。④最后,程序顯示并更新主框架窗口。〔4〕WinMain進(jìn)行消息循環(huán),處理消息完成初始化任務(wù)后,WinMain進(jìn)入消息循環(huán)。通過(guò)Run()函數(shù)把消息從消息隊(duì)列中取出,并發(fā)送到別的窗口。大多數(shù)命令消息被發(fā)送到應(yīng)用程序主窗口,其中的函數(shù)WindowProc()得到消息,再根據(jù)消息的類別送到適當(dāng)?shù)膶?duì)象,激活并運(yùn)行對(duì)象中的消息處理函數(shù)?!?〕WinMain退出,程序終止在應(yīng)用程序Draw中,運(yùn)行“文件”菜單下的“退出”菜單項(xiàng),或運(yùn)行系統(tǒng)菜單的“關(guān)閉”菜單項(xiàng),或單擊主框架間窗口中的Close框時(shí),應(yīng)用程序刪除程序窗口,并調(diào)用Win32API函數(shù)::PostQuitMessage,使消息循環(huán)退出。然后WinMain函數(shù)返回,程序終止。3.4MFC應(yīng)用程序設(shè)計(jì)結(jié)構(gòu)體系剖析運(yùn)行應(yīng)用程序Draw時(shí),從運(yùn)行情況來(lái)看,應(yīng)用程序Draw包含很多標(biāo)準(zhǔn)菜單〔如“文件”、“編輯”、“窗口”、“顯示”等菜單下的各菜單項(xiàng)〕,運(yùn)行標(biāo)準(zhǔn)菜單可以執(zhí)行一系列的操作。初學(xué)者可能會(huì)急著翻開程序的源代碼文件,尋找對(duì)應(yīng)于每個(gè)菜單的程序執(zhí)行代碼,跟蹤一下程序是怎么運(yùn)行的。但把代碼看了個(gè)遍也可能找不到菜單項(xiàng)是如何被執(zhí)行的,更談不上控制這些菜單項(xiàng)的執(zhí)行情況了。這到底是怎么回事呢?3.4.1標(biāo)準(zhǔn)菜單的執(zhí)行分析在小節(jié)曾經(jīng)討論過(guò),MFC定義了一些標(biāo)準(zhǔn)的命令消息和窗口消息,如ID_FILE_NEW、ID_FILE_OPEN等,應(yīng)用程序Draw各個(gè)標(biāo)準(zhǔn)菜單項(xiàng)對(duì)應(yīng)的都是這些已經(jīng)在MFC中定義的消息,同時(shí),MFC為這些消息都創(chuàng)立了消息處理函數(shù)并建立了消息映射機(jī)制。中選中并執(zhí)行這些菜單項(xiàng)的時(shí)候,MFC中的消息處理函數(shù)被執(zhí)行。讀者如有興趣,可以從VC++主目錄下的mfc\src子目錄下找到各種已經(jīng)創(chuàng)立好的函數(shù)。對(duì)于每一個(gè)菜單命令消息,在MFC中實(shí)現(xiàn)的消息處理函數(shù)中調(diào)用了一系列的函數(shù),經(jīng)過(guò)一系列的步驟來(lái)完成這一個(gè)操作。如對(duì)于ID_FILE_OPEN消息〔即點(diǎn)擊“文件”菜單下的“翻開…”菜單項(xiàng)時(shí)〕,在CWinApp類中創(chuàng)立了消息處理函數(shù)OnFileOpen。OnFileOpen函數(shù)執(zhí)行時(shí),根據(jù)在應(yīng)用類CDrawApp中的InitInstance函數(shù)中注冊(cè)的多文檔程序模板,分別去創(chuàng)立一個(gè)文檔類、子框架類和視圖類對(duì)象。沒(méi)有必要去分析操作的全過(guò)程,以下這個(gè)OpenDocumentFile函數(shù)是在OnFileOpen函數(shù)操作過(guò)程中調(diào)用的一個(gè)屬于多文檔模板類的成員函數(shù),它完成創(chuàng)立一個(gè)文檔類對(duì)象和屬于這個(gè)文檔類對(duì)象的框架類對(duì)象的功能,以下是這個(gè)函數(shù)的實(shí)現(xiàn)代碼:CDocument*CMultiDocTemplate::OpenDocumentFile(LPCSTRlpszPathName,BOOLbMakeVisible){//創(chuàng)立新文檔對(duì)象,pDocument指向這個(gè)對(duì)象CDocument*pDocument=CreateNewDocument();if(pDocument==NULL)//如創(chuàng)立文檔類對(duì)象失敗,函數(shù)非正常退出{TRACE0(“CDocTemplate::CreateNewDocumentreturnedNULL.\n”);AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);returnNULL;}ASSERT_VALID(pDocument);BOOLbAutoDelete=pDocument->m_bAutoDelete;//don’tdestroyifsomethinggoeswrongpDocument->m_bAutoDelete=FALSE;//創(chuàng)立一個(gè)子框架類對(duì)象CFrameWnd*pFrame=CreateNewFrame(pDocument,NULL);pDocument->m_bAutoDelete=bAutoDelete;if(pFrame==NULL)//如果創(chuàng)立子框架類對(duì)象失敗,函數(shù)非正常退出{AfxMessageBox(AFX_lOP_FAILED_TO_CREATE_DOC);deletepDocument;//explicitdeleteonerrorreturnNULL;}ASSERT_VALID(pFrame);if(lpszPathName==NULL)//如果文檔沒(méi)有名稱,即執(zhí)行“新建”菜單時(shí)運(yùn)行時(shí){//createanewdocument–withdefaultdocumentnameSetDefaultTitle(pDocument);//給定一個(gè)默認(rèn)名稱//avoidcreatingtemporarycompoundfilewhenstartingupinvisibleif(!bMakeVisible)pDocument->m_hEmbeded=TRUE;if(!pDocument->OnNewDocument()){//userhasbealertedtowhatfailedinOnNewDocumentTRACE0(“CDocument::OnNewDocumentreturnedFALSE.\n”);pFrame->DestroyWindow();returnNULL;}m_nUntitledCount++;//給計(jì)數(shù)器加1,通過(guò)此計(jì)數(shù)器產(chǎn)生無(wú)名的文檔名稱}else//如果文檔有名稱,即運(yùn)行“翻開…”菜單項(xiàng)時(shí)運(yùn)行的本函數(shù){//openanexistingdocumentCWaitCursorwait;if(!pDocument->OnOpenDocument(lpszPathName))//調(diào)用產(chǎn)生文檔類的函數(shù){//userhasbealertedtowhatfailedinOnOpenDocumentTRACE0(“Cdocument::OnOpenDocumentreturnedFALSE.\n”);pFrame->DestroyWindow();returnNULL;}#ifdef_MAC//ifthedocumentisdirty,wemusthaveopenedastationerypad//-don’tchangethepathnamebecausewewanttotreatthe//documentasuntitledif(!pDocument->IsModified())#endifpDocument->SetPathName(lpszPathName);}InitialUpdateFrame(pFrame,pDocument,bMakeVisible);returnpDocument;}3.4.2修改標(biāo)準(zhǔn)菜單執(zhí)行功能在小節(jié)中,討論了MFC應(yīng)用程序標(biāo)準(zhǔn)菜單的執(zhí)行情況。在MFC中已經(jīng)實(shí)現(xiàn)的針對(duì)標(biāo)準(zhǔn)菜單的操作功能,不可能滿足實(shí)際應(yīng)用程序設(shè)計(jì)的要求。但是,程序設(shè)計(jì)者不可能去修改MFC中實(shí)現(xiàn)標(biāo)準(zhǔn)操作功能的代碼,來(lái)實(shí)現(xiàn)實(shí)際的操作功能。所以,如何在應(yīng)用程序設(shè)計(jì)中改變和控制這些標(biāo)準(zhǔn)菜單的執(zhí)行功能,是一個(gè)關(guān)鍵的問(wèn)題所在。從上一小節(jié)列出的函數(shù)OpenDocumentFile中可以看到,在完成翻開一個(gè)文檔的操作功能時(shí),MFC實(shí)現(xiàn)的標(biāo)準(zhǔn)操作通過(guò)當(dāng)前文檔類對(duì)象指針調(diào)用了成員函數(shù)OpenDocument(見(jiàn)黑體局部代碼pDocument->OnPenDocument(lpszPathName))。你留心一下的話,在應(yīng)用程序Draw的文檔類CDrawDoc中找不到這個(gè)函數(shù)。這時(shí)此句代碼執(zhí)行的是基類CDocument中的OpenDocument函數(shù)。這個(gè)函數(shù)是虛函數(shù),如果當(dāng)前類沒(méi)有這個(gè)函數(shù),就會(huì)執(zhí)行基類中的虛函數(shù)。而如果在當(dāng)前類中重載了這個(gè)函數(shù),代碼就轉(zhuǎn)而執(zhí)行當(dāng)前類的這個(gè)虛函數(shù)。這樣,只要在當(dāng)前類中重載和改變各個(gè)虛函數(shù),就到達(dá)修改標(biāo)準(zhǔn)菜單執(zhí)行功能的目的。MFC程序框架正是基于此實(shí)現(xiàn)的。由AppWizard產(chǎn)生的框架程序中,其標(biāo)準(zhǔn)菜單執(zhí)行的操作過(guò)程是在MFC中創(chuàng)立實(shí)現(xiàn)時(shí),在多個(gè)環(huán)節(jié)中調(diào)用了一些虛函數(shù)來(lái)完成操作。在代碼不做改動(dòng)的情況下,這些調(diào)用都是通過(guò)定義在MFC的基類中的虛函數(shù)完成的。如果在當(dāng)前程序類中對(duì)這些虛函數(shù)進(jìn)行重載,就使這些環(huán)節(jié)中程序執(zhí)行的是當(dāng)前類的函數(shù),從而到達(dá)了改變和控制標(biāo)準(zhǔn)菜單操作任務(wù)的目的,實(shí)現(xiàn)自己特定的功能。從而到達(dá)了改變和控制標(biāo)準(zhǔn)菜單操作任務(wù)的目的,實(shí)現(xiàn)自己特定的功能。此項(xiàng)特定功能的實(shí)現(xiàn)是通過(guò)虛函數(shù)和多態(tài)性來(lái)實(shí)現(xiàn)的。實(shí)際上,在MFC中除了實(shí)現(xiàn)了大量標(biāo)準(zhǔn)的命令消息處理函數(shù)外〔標(biāo)準(zhǔn)菜單的消息處理函數(shù)〕,還實(shí)現(xiàn)了大量的窗口消息處理函數(shù),幾乎所有的窗口消息〔如在窗口中移動(dòng)鼠標(biāo)、關(guān)閉窗口等等〕都已經(jīng)在MFC類中實(shí)現(xiàn)了消息處理函數(shù),通過(guò)這些消息處理函數(shù)來(lái)完成一定的操作。在這些消息處理函數(shù)執(zhí)行過(guò)程中,調(diào)用了一些是當(dāng)前應(yīng)用程序類基類〔如CDocument、CView、CFrameWnd、CWinApp等〕中的虛函數(shù),這樣,在當(dāng)前的應(yīng)用程序中,通過(guò)在文檔類、視圖類、框架類、應(yīng)用類中重載并修改虛函數(shù),就到達(dá)了局部修改這些消息處理函數(shù),就到達(dá)了局部修改這些消息處理函數(shù)、實(shí)現(xiàn)實(shí)際程序設(shè)計(jì)功能的目的。這是MFC程序設(shè)計(jì)的本質(zhì)和基石。3.4.3MFC應(yīng)用程序多態(tài)性的實(shí)現(xiàn)〔1〕實(shí)現(xiàn)多態(tài)性的前提條件通過(guò)虛函數(shù)實(shí)現(xiàn)多態(tài)性的關(guān)鍵,是將調(diào)用函數(shù)時(shí)的對(duì)象指針指向?qū)嶋H對(duì)象。例如,在小節(jié)列出的OnOpenDocument虛函數(shù),實(shí)現(xiàn)多態(tài)性的關(guān)鍵問(wèn)題是指針pDocument指向當(dāng)前應(yīng)用程序的文檔類對(duì)象。如果pDocument指針指向的是一個(gè)CDocument類對(duì)象〔可以用以下的代碼來(lái)描述這個(gè)過(guò)程〕:CDocumentm_Document1;CDocument*pDocument=&m_Document;即使在當(dāng)前應(yīng)用程序Draw的文檔類CDrawDoc中重載虛函數(shù)OnOpenDocument,通過(guò)pDocument指針調(diào)用虛函數(shù)OnOpenDocument時(shí),程序流程也不會(huì)去執(zhí)行CDrawDoc類中的重載虛函數(shù)OnOpenDocument。只有把對(duì)象指針pDocument指向當(dāng)前應(yīng)用程序文檔類對(duì)象時(shí)〔用以下代碼來(lái)描述這個(gè)過(guò)程〕:CDrawDocm_Document1;CDocument*pDocument=&m_Document1;通過(guò)pDocument指針去調(diào)用虛函數(shù)OnOpenDocument時(shí):pDocument->OnOpenDocument(lpszPathName);如果在CDrawDoc類中重載了OnOpenDocument函數(shù),以上代碼調(diào)用就會(huì)執(zhí)行CDrawDoc類中的虛函數(shù)OnOpenDocument,從而到達(dá)了程序執(zhí)行的多態(tài)性?!?〕MFC應(yīng)用程序?qū)崿F(xiàn)多態(tài)性的過(guò)程現(xiàn)在來(lái)討論MFC應(yīng)用程序是如何實(shí)現(xiàn)多態(tài)性的。在MFC類中實(shí)現(xiàn)了大量完成標(biāo)準(zhǔn)功能的標(biāo)準(zhǔn)操作,在這些操作過(guò)程中調(diào)用了大量當(dāng)前應(yīng)用程序的基類〔如CDocument、CView、CFrameWnd等〕中的虛函數(shù)。MFC應(yīng)用程序的啟動(dòng)和設(shè)置局部是在MFC類中實(shí)現(xiàn)的〔這就是不能從當(dāng)前應(yīng)用程序中找到程序啟動(dòng)局部的原因〕。在執(zhí)行過(guò)程中,通過(guò)創(chuàng)立的全局CDrawApp類對(duì)象theApp,調(diào)用應(yīng)用類CDrawApp的InitInstance函數(shù)將當(dāng)前應(yīng)用程序的文檔類、視圖類、框架類都注冊(cè)到了多文檔模板對(duì)象中,通過(guò)這個(gè)多文檔模板對(duì)象在新建和翻開文檔操作時(shí),創(chuàng)立的是當(dāng)前應(yīng)用程序類的對(duì)象。而在MFC類中實(shí)現(xiàn)的標(biāo)準(zhǔn)操作過(guò)程中,利用指向當(dāng)前應(yīng)用程序類對(duì)象的基類指針,調(diào)用了基類中定義的虛函數(shù)去實(shí)現(xiàn)操作功能〔如,在Draw應(yīng)用程序翻開文檔操作時(shí),實(shí)際上是在MFC中創(chuàng)立了一個(gè)CDrawDoc,然后將CDocument類指針指向這個(gè)對(duì)象〕。這樣,就滿足了實(shí)現(xiàn)多態(tài)性操作的條件,當(dāng)在當(dāng)前應(yīng)用程序的框架類〔如CDrawDoc、CDrawView、CMainFrame等〕重載其基類的虛函數(shù)時(shí),MFC應(yīng)用程序中實(shí)現(xiàn)的標(biāo)準(zhǔn)功能就會(huì)去執(zhí)行這些重載的虛函數(shù),而到達(dá)改變MFC程序設(shè)計(jì)標(biāo)準(zhǔn)功能的目的。在MFC應(yīng)用程序新建或翻開文檔操作時(shí),可通俗的理解為在MFC中執(zhí)行了如下操作:CDrawDocm_Drawdoc1;CDrawViewm_Drawview1;CChildFramem_Childframe1;以上代碼只作為理解用,對(duì)象的名稱也是為了加深讀者的理解而定的。MFC應(yīng)用程序建立了各個(gè)對(duì)象之間的關(guān)系,并將各個(gè)基類指針指向了這些類對(duì)象:pDocument=&m_DrawDoc1;pView=&m_Drawview1;pFrame=&m_Childframe1;pDocument、pView、pFrame是在MFC中定義的基類指針:CDocument*pDocument;CView*pView;CFrameWnd*pFrame;這些指針被用來(lái)在各個(gè)MFC的消息處理函數(shù)中,調(diào)用基類的虛函數(shù)完成各個(gè)標(biāo)準(zhǔn)操作功能。在應(yīng)用程序翻開視圖的操作時(shí)〔運(yùn)行應(yīng)用程序Draw“窗口”菜單下的“新建”菜單項(xiàng)時(shí)〕,MFC程序框架執(zhí)行了如下操作:CDrawViewm_Drawview1;CChildFramem_Childframe1;在MFC中創(chuàng)立了一個(gè)視圖類和子框架類對(duì)象,而沒(méi)有新建文檔類對(duì)象,在建立各個(gè)對(duì)象間的關(guān)系時(shí),采用的是已經(jīng)存在的處于活動(dòng)狀態(tài)的文檔類對(duì)象。將各個(gè)基類指針指向了這些新建的類對(duì)象:pView=&m_Drawview1;pFrame=&m_Childframe1;3.4.4MFC應(yīng)用程序中各個(gè)框架類對(duì)象的相互調(diào)用關(guān)系從上一小節(jié)的討論中可以知道,在多文檔MFC應(yīng)用程序執(zhí)行過(guò)程中,創(chuàng)立了多于一個(gè)的文檔類、視圖類、子框架類對(duì)象和一個(gè)主框架類、應(yīng)用類對(duì)象。這些對(duì)象之間是通過(guò)一定的方式聯(lián)系在一起的,在應(yīng)用程序
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 山東滕州市八年級(jí)政治上冊(cè) 第1單元 讓愛(ài)駐我家 第2課 我們共有一個(gè)家教學(xué)實(shí)錄與檢測(cè) 魯教版
- 達(dá)州市通川區(qū)楊家溝煤業(yè)有限公司楊家溝煤礦礦山地質(zhì)環(huán)境保護(hù)與土地復(fù)墾方案情況
- 四川化工職業(yè)技術(shù)學(xué)院
- 肝膿腫護(hù)理相關(guān)知識(shí)
- 【人教PEP版英語(yǔ)四年級(jí)下冊(cè)】期中測(cè)試卷6
- 人教版小學(xué)四年級(jí)語(yǔ)文下冊(cè)2024-2025學(xué)年度第二學(xué)期第一單元質(zhì)量檢測(cè)試卷含參考答案
- 人教版小學(xué)四年級(jí)語(yǔ)文下冊(cè)2024-2025學(xué)年度第二學(xué)期第八單元質(zhì)量檢測(cè)試卷
- 第5單元 第14課 新年賀卡-綜合制作-教學(xué)設(shè)計(jì)2023-2024學(xué)年清華大學(xué)版(2012)初中信息技術(shù)八年級(jí)上冊(cè)001
- 網(wǎng)絡(luò)安全運(yùn)維專家簡(jiǎn)歷
- 安徽省部分地市2024-2025學(xué)年高三下學(xué)期2月聯(lián)合考試物理試題(解析版)
- 迪士尼樂(lè)園主題PPT模板
- C形根管的形態(tài)識(shí)別和治療實(shí)用教案
- 部編版《道德與法治》四年級(jí)下冊(cè)第5課《合理消費(fèi)》優(yōu)質(zhì)課件
- 京東入駐流程(課堂PPT)
- 鍋爐巡檢制度
- 切紙機(jī)說(shuō)明書-原稿
- 中國(guó)國(guó)際航空公司VI形象識(shí)別規(guī)劃提案
- 三菱PLC模擬量模塊fx2n4da中文手冊(cè)
- 金屬材料工程課程設(shè)計(jì)
- 學(xué)校突發(fā)公共衛(wèi)生事件應(yīng)急處置.ppt
- 學(xué)生課堂表現(xiàn)評(píng)價(jià)量表(20211208204532)
評(píng)論
0/150
提交評(píng)論