




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、版權(quán)所有版權(quán)所有 復(fù)制必究復(fù)制必究 一個(gè)優(yōu)秀的編程工具往往匹配一個(gè)功能強(qiáng)大的類庫(kù),類庫(kù)封裝了大量Windows編程需要使用的函數(shù)和數(shù)據(jù)結(jié)構(gòu)。與Visual C+捆綁在一起的MFC(Microsoft Foundation Class)微軟基礎(chǔ)類就是這樣一個(gè)由Microsoft公司設(shè)計(jì)的類庫(kù)。采用MFC方式編程提高了Windows應(yīng)用程序的開發(fā)效率,但由于MFC應(yīng)用程序結(jié)構(gòu)的復(fù)雜性和透明性,要想完全掌握MFC應(yīng)用程序的內(nèi)部機(jī)制需要付出很大的努力。 認(rèn)識(shí)MFC只是一個(gè)過(guò)程、一個(gè)手段,最終目的是為了良好并熟練地運(yùn)用MFC。 本章主要學(xué)習(xí)內(nèi)容:本章主要學(xué)習(xí)內(nèi)容:lWindows的編程機(jī)制lMFC的基本
2、原理和使用方法:MFC類類MFC應(yīng)用程序框架應(yīng)用程序框架MFC消息管理消息管理MFC宏宏l常用的MFC類7.1 Windows編程基礎(chǔ)編程基礎(chǔ) lWindows是一個(gè)多進(jìn)程的圖形窗口操作系統(tǒng),Windows應(yīng)用程序與DOS應(yīng)用程序有很大的區(qū)別。DOS應(yīng)用程序采用順序執(zhí)行過(guò)程,而Windows是一個(gè)基于事件的消息(Message)驅(qū)動(dòng)系統(tǒng)。lWindows應(yīng)用程序是按照“事件事件消息消息處理處理”非順序的機(jī)制運(yùn)行。當(dāng)有某個(gè)事件(如單擊鼠標(biāo)、鍵盤輸入和執(zhí)行菜單命令等)發(fā)生時(shí),Windows會(huì)根據(jù)具體的事件產(chǎn)生對(duì)應(yīng)的消息,并發(fā)送到指定應(yīng)用程序的消息隊(duì)列;應(yīng)用程序從消息隊(duì)列中取出消息,并根據(jù)不同的消息
3、進(jìn)行不同的處理。 lWindows API(Application Programming Interface)是Windows操作系統(tǒng)與應(yīng)用程序之間的標(biāo)準(zhǔn)接口,它提供了上千個(gè)標(biāo)準(zhǔn)函數(shù)、宏和數(shù)據(jù)結(jié)構(gòu)的定義。l在使用Visual C+、Visual Basic和Delphi編程時(shí)都可以調(diào)用Windows API函數(shù),Windows應(yīng)用程序可通過(guò)調(diào)用標(biāo)準(zhǔn)Windows API函數(shù)使用系統(tǒng)提供的功能。lWindows API函數(shù)定義在一些DLL動(dòng)態(tài)鏈接庫(kù)中,其中最主要的DLL是User32.dll、Gdi32.dll和Kernel32.dll三個(gè)庫(kù)文件。 7.1.1 關(guān)于關(guān)于API和和SDK l傳統(tǒng)
4、SDK編程:程序員通過(guò)調(diào)用API函數(shù),自己動(dòng)手、按部就班地實(shí)現(xiàn)程序各部分的功能。SDK應(yīng)用程序的結(jié)構(gòu)比較清晰,但程序員必須編寫所有的功能代碼。l利用Visual C+編寫一個(gè)類SDK應(yīng)用程序:首先利用Win32 Application向?qū)Ы⒁粋€(gè)Windows應(yīng)用程序框架,然后根據(jù)需要可以向程序項(xiàng)目中添加一些頭文件、實(shí)現(xiàn)源文件和資源文件,并編寫具體的程序代碼。例例 編寫一個(gè)名為Hello的類SDK應(yīng)用程序,當(dāng)單擊鼠標(biāo)時(shí)通過(guò)調(diào)用API函數(shù),以彈出一個(gè)提示信息對(duì)話框。 1執(zhí)行“File|New”菜單命令,在New對(duì)話框的Project頁(yè)面中選擇Win32 Application項(xiàng)目類型,輸入程序名
5、Hello。在向?qū)У?步選擇“A typital “Hello world!” application”項(xiàng),單擊Finish按鈕。2在窗口函數(shù)WndProc()的消息處理分支switch-case結(jié)構(gòu)中添加WM_LBUTTONDOWN鼠標(biāo)單擊消息及其處理代碼: case WM_LBUTTONDOWN: MessageBox(NULL, You pressed the left button of mouse !,Message,NULL); break; SDK應(yīng)用程序結(jié)構(gòu):l一個(gè)由API函數(shù)構(gòu)造的Windows程序的功能由三個(gè)部分組成:入口函數(shù)、窗口函數(shù)和Windows系統(tǒng)。l每一個(gè)程序都有
6、一個(gè)主函數(shù),WinMain()函數(shù)就是Windows程序的入口主函數(shù)。該函數(shù)的主要任務(wù)是完成一些初始化工作并維護(hù)一個(gè)消息循環(huán)。當(dāng)消息循環(huán)結(jié)束后,就退出了WinMain()函數(shù),也就退出了應(yīng)用程序。此外,WinMain()函數(shù)還負(fù)責(zé)完成窗口的注冊(cè)、創(chuàng)建和顯示。lWindows程序以窗口的形式存在,在不同窗口之間傳遞消息是Windows和應(yīng)用程序進(jìn)行交流的主要形式。程序具體功能由不同的窗口函數(shù)實(shí)現(xiàn)。 7.1.2 句柄句柄 l在Windows中,用句柄(句柄(Handle)標(biāo)識(shí)應(yīng)用程序中不同的對(duì)象和同類對(duì)象中不同的實(shí)例,如一個(gè)具體的窗口、按鈕、輸出設(shè)備、畫筆和文件等。通過(guò)句柄可以獲得相應(yīng)的對(duì)象信息。
7、常用的句柄類型有: HWND 、 HINSTANCE 、 HDC 、HCURSOR、HICON、HMENU等。l句柄常作為Windows消息和API函數(shù)的參數(shù),在采用API方法編寫Windows應(yīng)用程序時(shí)要經(jīng)常使用句柄。而采用MFC方法編寫Windows應(yīng)用程序時(shí),由于對(duì)應(yīng)的MFC類已對(duì)句柄進(jìn)行了封裝,大多數(shù)情況下不再需要訪問(wèn)句柄。 獲取獲取MFC類對(duì)象的句柄的兩種方法:類對(duì)象的句柄的兩種方法: l通過(guò)訪問(wèn)類的public屬性成員變量,如類CWnd的成員變量m_hWnd就是一個(gè)窗口對(duì)象的句柄。l先定義一個(gè)句柄,然后調(diào)用MFC類的成員函數(shù)Attach()將句柄與一個(gè)MFC類對(duì)象聯(lián)系在一起,此時(shí)的
8、句柄就成為該MFC類對(duì)象的句柄。在退出對(duì)象作用域之前,調(diào)用成員函數(shù)Detach()將句柄和對(duì)象進(jìn)行分離。如下所示:CWnd myWnd; HWND hWnd; myWnd.Attach(hWnd); . . . . . . myWnd.Detach(); l所謂消息消息就是用于描述某個(gè)事件發(fā)生的信息,而事事件件是對(duì)于Windows的某種操作。l事件和消息密切相關(guān),事件是因,消息是果,事件產(chǎn)生消息,消息對(duì)應(yīng)事件。所謂消息的響應(yīng),其實(shí)質(zhì)就是事件的響應(yīng)。l消息驅(qū)動(dòng)消息驅(qū)動(dòng)是Windows應(yīng)用程序的核心,所有的外部響應(yīng)(如鍵盤、鼠標(biāo)和計(jì)時(shí)器等)都被Windows先攔截,轉(zhuǎn)換成消息后再發(fā)送到應(yīng)用程序中的
9、目標(biāo)對(duì)象,應(yīng)用程序根據(jù)消息的具體內(nèi)容進(jìn)行處理。l消息不僅可由Windows發(fā)出,它也可由應(yīng)用程序本身或其它程序產(chǎn)生。Windows為每一個(gè)應(yīng)用程序都維護(hù)一個(gè)或多個(gè)消息隊(duì)列消息隊(duì)列,發(fā)送到每個(gè)程序窗口的消息都排成一個(gè)隊(duì)列。 7.1.3 事件和事件和消息消息 消息隊(duì)列和在應(yīng)用程序中的輪詢處理消息隊(duì)列和在應(yīng)用程序中的輪詢處理 Windows消息消息分為三種類型:分為三種類型:l標(biāo) 準(zhǔn)標(biāo) 準(zhǔn) W i n d o w s 消 息消 息 : 以 W M _ 前 綴 ( 但 不 包 括WM_COMMAND)開始的消息,包括鼠標(biāo)消息、鍵盤消息和窗口消息,如WM_MOVE 、WM_PAINT等。l控件通知(控件
10、通知(Control Notification)消息消息:對(duì)控件操作引起的 消 息 , 是 控 件 和 子 窗 口 向 其 父 窗 口 發(fā) 出 的WM_COMMAND通知消息。例如,當(dāng)用戶修改了編輯控件 中 的 文 本 后 , 編 輯 控 件 向 其 父 窗 口 發(fā) 送WM_COMMAND通知消息。l命令(命令(Command)消息消息:由菜單項(xiàng)、工具欄按鈕、快捷鍵等用戶界面對(duì)象發(fā)出的WM_COMMAND消息。命令消息與其它消息不同,它可被更廣泛的的對(duì)象如文檔、文檔模板、應(yīng)用程序?qū)ο蟆⒋翱诤鸵晥D等處理。 typedef struct tagMSG HWND hWnd; / 目標(biāo)窗口句柄 UIN
11、T message;/ 消息標(biāo)識(shí) WPARAM wParam;/ 消息參數(shù)1(附加信息,16位) LPARAM lParam;/ 消息參數(shù)2(附加信息,32位) DWORD time;/ 消息發(fā)送時(shí)間 POINT pt; / 消息發(fā)送時(shí)鼠標(biāo)的屏幕坐標(biāo) MSG;消息用消息用MSG結(jié)構(gòu)表示:結(jié)構(gòu)表示: 例例 為程序Hello添加鍵盤消息處理功能,判斷當(dāng)前按下的鍵是不是A或a鍵,并給出相應(yīng)的提示。 打開程序項(xiàng)目Hello,在文件Hello.cpp的窗口函數(shù)WndProc()的switch消息處理分支中添加鍵盤消息的處理代碼: case WM_KEYDOWN: / 處理鍵盤消息 if(wParam=0
12、 x41) / A或a鍵的虛鍵碼為0 x41HMessageBox(NULL, The key you pressed is A or a !,KEYDOWN,NULL); else MessageBox(NULL, The key you pressed is not A or a !,KEYDOWN,NULL); break; 利用Windows API開發(fā)程序的用戶有這樣的體會(huì),即使開發(fā)一個(gè)簡(jiǎn)單的Windows應(yīng)用程序也需要對(duì)Windows的編程原理有很深刻的認(rèn)識(shí),需要手工編寫冗長(zhǎng)的代碼。由于程序的出錯(cuò)率是隨著代碼長(zhǎng)度的增加呈幾何級(jí)數(shù)增長(zhǎng)的,而且當(dāng)程序長(zhǎng)度逐漸膨脹時(shí),調(diào)試程序會(huì)變得越來(lái)越
13、困難。因此,傳統(tǒng)的Windows應(yīng)用程序設(shè)計(jì)需要程序員有極大的耐心和豐富的編程經(jīng)驗(yàn)。 Visual C+捆綁了微軟的基礎(chǔ)類MFC,編程時(shí)我們就可以利用類的可重用性和可擴(kuò)充性,大大降低Windows應(yīng)用程序設(shè)計(jì)的難度和工作量。 7.2 MFC微軟基礎(chǔ)類微軟基礎(chǔ)類 7.2.1 MFC概述概述l類庫(kù)是一個(gè)可以在應(yīng)用程序中使用的相互關(guān)聯(lián)的C+類的集合。 MFC作為一個(gè)Windows編程類庫(kù),它包含了200多個(gè)類,封裝了Windows的大部分編程對(duì)象以及與它們有關(guān)的操作。l雖然程序在功能上千差萬(wàn)別,但從本質(zhì)上看,都可以分為用戶界面設(shè)計(jì)、文件操作、數(shù)據(jù)庫(kù)訪問(wèn)及多媒體使用等幾部分,這些都可以通過(guò)一些類來(lái)實(shí)現(xiàn)
14、。MFC提供了一個(gè)標(biāo)準(zhǔn)化的程序結(jié)構(gòu),使開發(fā)人員不必從頭設(shè)計(jì)一個(gè)Windows應(yīng)用程序。lMFC實(shí)際上是一個(gè)龐大的文件庫(kù),它由幾百個(gè)執(zhí)行文件和源代碼文件(如H文件)組成。 l使用標(biāo)準(zhǔn)化的程序代碼結(jié)構(gòu),有利于程序員之間的交流。lVisual C+為MFC提供了大量的工具支持,提高了編程效率。如利用MFC AppWizard創(chuàng)建MFC應(yīng)用程序框架,利用ClassWizard方便地對(duì)Windows消息進(jìn)行管理。lMFC應(yīng)用程序的效率較高,只比傳統(tǒng)的Windows C程序低5%左右。并且,在MFC應(yīng)用程序中還允許混合使用傳統(tǒng)的Windows API函數(shù)。l其它優(yōu)勢(shì):完全支持Windows所有的函數(shù)、控件
15、、消息、菜單及對(duì)話框;具有良好的穩(wěn)定性和可移植性,更符合微軟的風(fēng)格等。 采用采用MFC編程的優(yōu)點(diǎn):編程的優(yōu)點(diǎn): 7.2.2 MFC體系結(jié)構(gòu)體系結(jié)構(gòu)lMFC主要組成部分:類、宏和全局函數(shù)。l類是MFC中最主要的內(nèi)容。MFC類是以層次結(jié)構(gòu)方式組織起來(lái)的。MFC中的類分成兩部分,除了一些輔助類,大多數(shù)的MFC類是直接或間接從根類CObject派生而來(lái)。l幾乎每一個(gè)派生層次都與一具體的Windows實(shí)例相對(duì)應(yīng),如文檔類、窗口類和視圖類等。lMFC宏主要功能:消息映射、運(yùn)行時(shí)對(duì)象類型服務(wù)、診斷服務(wù)、異常處理。 lMFC約定:全局函數(shù)以“Afx”為前綴,全局變量以“afx”為前綴。 l首先要對(duì)Window
16、s編程概念和API函數(shù)有一定的了解,如Windows API有哪些功能和哪些常用的數(shù)據(jù)結(jié)構(gòu)等。 l學(xué)會(huì)抽象地把握問(wèn)題,不求甚解,不要一開始學(xué)習(xí)Visual C+就試圖了解整個(gè)MFC類庫(kù)。從理解和使用兩個(gè)方面學(xué)習(xí)MFC,理解MFC應(yīng)用程序的框架結(jié)構(gòu)。l先大體上了解MFC的概念、組成和基本約定,從簡(jiǎn)單的類入手,結(jié)合程序設(shè)計(jì),由淺入深,循序漸進(jìn)、日積月累。 l編程時(shí)如果MFC某個(gè)類能完成所需要的功能,可以直接調(diào)用已有類的方法(成員函數(shù))。否則,可以利用面向?qū)ο蠹夹g(shù)中的“繼承”方法對(duì)MFC類的行為進(jìn)行擴(kuò)充和修改,從MFC中已有的類派生出自己需要的類。 l學(xué)習(xí)MFC,另一點(diǎn)就是不要過(guò)分依賴于向?qū)В╓iz
17、ard)工具。向?qū)茏鲈S多工作,但同時(shí)掩飾了太多的細(xì)節(jié)。 7.2.3 學(xué)習(xí)學(xué)習(xí)MFC的方法的方法l盡管每個(gè)應(yīng)用程序具體實(shí)現(xiàn)的功能不同,但同一類程序的基本結(jié)構(gòu)是相同的。因此,通常采用MFC AppWizard創(chuàng)建一個(gè)MFC應(yīng)用程序框架應(yīng)用程序框架。lMFC不僅僅是一個(gè)類庫(kù),它還提供了一層建立在MFC類對(duì)象封裝上的附加應(yīng)用程序框架。應(yīng)用程序框架是為了生成一般的應(yīng)用程序所必需的各種軟組件的集成,是類庫(kù)的一種超集。l類庫(kù)只是一種可以嵌入到任何程序中的、提供某些特定功能的類的集合。而應(yīng)用程序框架卻定制了應(yīng)用程序的結(jié)構(gòu)和源代碼,其中的類對(duì)象既相互獨(dú)立、又相互作用,形成一個(gè)統(tǒng)一的整體。 7.3 MFC應(yīng)用程
18、序框架應(yīng)用程序框架 lMFC應(yīng)用程序框架提供了構(gòu)建應(yīng)用程序所需要的類,在程序運(yùn)行時(shí)能夠生成運(yùn)行時(shí)類的對(duì)象,如代表應(yīng)用程序?qū)ο蟆⑽臋n對(duì)象、視圖對(duì)象和框架窗口對(duì)象。應(yīng)用程序?qū)ο髏heApp是一個(gè)唯一的全局變量,它的主要功能是通過(guò)調(diào)用WinMain()主函數(shù)啟動(dòng)程序的運(yùn)行。lMFC應(yīng)用程序框架也有一個(gè)作為程序入口點(diǎn)的WinMain()主函數(shù),但在源程序中看不見該函數(shù),它在MFC中已定義好并同應(yīng)用程序相鏈接。 7.3.1 應(yīng)用程序框架中的對(duì)象應(yīng)用程序框架中的對(duì)象MFC應(yīng)用程序?qū)ο笾g的關(guān)系應(yīng)用程序?qū)ο笾g的關(guān)系 l在MFC應(yīng)用程序的CWinApp派生類對(duì)象theApp是一個(gè)全局變量,代表了應(yīng)用程序運(yùn)行
19、的主線程。它在程序整個(gè)運(yùn)行期間都存在,它的銷毀意味著運(yùn)行程序的消亡。lMFC應(yīng)用程序啟動(dòng)時(shí),首先創(chuàng)建應(yīng)用程序?qū)ο髏heApp,這時(shí)將自動(dòng)調(diào)用應(yīng)用程序類的構(gòu)造函數(shù)初始化對(duì)象theApp,然后由應(yīng)用程序框架調(diào)用MFC提供的AfxWinMain()主函數(shù)。 lAfxWinMain()主函數(shù)首先通過(guò)調(diào)用全局函數(shù)AfxGetApp()獲取應(yīng)用程序?qū)ο髏heApp的指針pApp,然后通過(guò)pApp調(diào)用應(yīng)用程序?qū)ο蟮挠嘘P(guān)成員函數(shù),完成程序的初始化和啟動(dòng)工作,最后調(diào)用成員函數(shù)Run(),進(jìn)入消息循環(huán)。l程序運(yùn)行后將收到WM_PAINT消息,調(diào)用OnPaint()函數(shù)繪制客戶區(qū)窗口。如果Run()收到WM_QUI
20、T消息,則結(jié)束消息循環(huán),然后調(diào)用函數(shù)ExitInstance(),結(jié)束程序運(yùn)行。 7.3.2 MFC應(yīng)用程序的生存與消亡應(yīng)用程序的生存與消亡 MFC應(yīng)用程序運(yùn)行后各函數(shù)的調(diào)用關(guān)系應(yīng)用程序運(yùn)行后各函數(shù)的調(diào)用關(guān)系 InitInstance()函數(shù)是派生類唯一需要重載的函數(shù),它負(fù)責(zé)應(yīng)用程序的初始化,如初始化數(shù)據(jù)、創(chuàng)建文檔模板、處理命令行以及顯示應(yīng)用程序主窗口。7.3.3 常用的常用的MFC文件文件 文文 件件 名名 稱稱說(shuō)說(shuō) 明明afxwin.h聲明MFC核心類afxext.hMFC擴(kuò)展文件,聲明工具欄、狀態(tài)欄、拆分窗口等類afxdisp.h聲明OLE類afxdtctl.h聲明支持IE 4公用控件的
21、MFC類,如CImageList等afxcmn.h聲明Windows公共控件類Mfc42.libMFCxx.DLL的導(dǎo)入函數(shù)庫(kù)(Release版)Mfc42D.libMFCxx.DLL的導(dǎo)入函數(shù)庫(kù)(Debug版)MfcS42.libMFCSxx.DLL的導(dǎo)入函數(shù)庫(kù)(Static Release版)MfcS42D.libMFCSxxD.DLL的導(dǎo)入函數(shù)庫(kù)(Static Debug版)Mfc42U.libMFCxxU.DLL的導(dǎo)入函數(shù)庫(kù)(Unicode Release版)Mfc42UD.libMFCxxUD.DLL的導(dǎo)入函數(shù)庫(kù)(Unicode Debug版)MfcO42D.libMFCOxxD.D
22、LL的導(dǎo)入函數(shù)庫(kù)(OLE Debug版)MfcD42D.libMFCDxxD.DLL的導(dǎo)入函數(shù)庫(kù)(Database Debug版)Nafxcw.libMFC靜態(tài)鏈接庫(kù)(Release版)NafxcwD.libMFC靜態(tài)鏈接庫(kù)(Debug版)gdi32.libGDI32.DLL的導(dǎo)入函數(shù)庫(kù)user32.libUSER32.DLL的導(dǎo)入函數(shù)庫(kù)kernel32.libKERNEL32.DLL的導(dǎo)入函數(shù)庫(kù)msvcrt.libMSVCRT.DLL(C運(yùn)行函數(shù)庫(kù))的導(dǎo)入函數(shù)庫(kù)msvcrtd.libMSVCRTD.DLL(Debug版C運(yùn)行函數(shù)庫(kù))的導(dǎo)入函數(shù)庫(kù)libcmt.libC運(yùn)行函數(shù)靜態(tài)鏈接庫(kù)(多線程
23、)libc.libC運(yùn)行函數(shù)靜態(tài)鏈接庫(kù)(單線程)lMFC消息管理是MFC編程的一個(gè)重要內(nèi)容,也是編寫MFC應(yīng)用程序的基礎(chǔ)。lMFC應(yīng)用程序消息處理的方式與SDK應(yīng)用程序有所不同。MFC應(yīng)用程序框架截取了Windows向應(yīng)用程序發(fā)出的消息,再確定將消息發(fā)送給哪一個(gè)對(duì)象,可以根據(jù)需要利用函數(shù)重載對(duì)消息進(jìn)行處理,但不需要處理的消息將由應(yīng)用程序框架自動(dòng)處理。l消息管理包括消息的發(fā)送和處理。對(duì)于消息發(fā)送,MFC提供了類似于API函數(shù)功能的消息發(fā)送函數(shù),而MFC消息處理的內(nèi)部機(jī)制則相對(duì)復(fù)雜一些。從編程的角度出發(fā),我們只需了解其大致的原理。 7.4 MFC消息管理消息管理 lMFC采用消息映射(消息映射(M
24、essage Map)機(jī)制取代C/C+語(yǔ)言中的switch-case結(jié)構(gòu)來(lái)處理消息。lMFC消息映射機(jī)制包括一組消息映射宏消息映射宏。一條消息映射宏把一個(gè)Windows消息和其消息處理函數(shù)聯(lián)結(jié)起來(lái)。lMFC應(yīng)用程序框架提供了消息映射功能。l在類的實(shí)現(xiàn)源文件中用BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()宏來(lái)定義消息映射。l在類定義的結(jié)尾用DECLARE_MESSAGE_MAP()宏來(lái)聲明使用消息映射。 7.4.1 MFC消息映射機(jī)制消息映射機(jī)制 BEGIN_MESSAGE_MAP(theclass, baseclass)/AFX_MSG_MAP(theclass)
25、ON_ . . . . . . / MFC預(yù)定義的消息映射宏ON_MESSAGE(message , memberFxn) / 用戶自定義的消息映射宏. . . . . . /AFX_MSG_MAPEND_MESSAGE_MAP()MFC應(yīng)用程序應(yīng)用程序MESSAGE_MAP消息映射形式:消息映射形式: 注意:注意:特殊注解“/AFX_MSG_MAP”是ClassWizard類向?qū)в糜诰S護(hù)消息映射宏的標(biāo)記,用戶不要?jiǎng)h除注解輕易修改注解內(nèi)的代碼。 啟動(dòng)ClassWizard,添加要求的三個(gè)消息處理函數(shù),ClassWizard將在類的實(shí)現(xiàn)文件中添加三個(gè)消息映射宏和消息處理函數(shù)。消息映射宏如下: B
26、EGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) /AFX_MSG_MAP(CMainFrame) ON_WM_CREATE() / 由MFC AppWizard程序向?qū)ё詣?dòng)生成的消息映射 ON_WM_CLOSE() / 由ClassWizard類向?qū)砑?ON_WM_DESTROY() ON_COMMAND(ID_EDIT_COPY, OnEditCopy) /AFX_MSG_MAPEND_MESSAGE_MAP() 例例 利用ClassWizard為框架類添加消息WM_CLOSE、WM_DESTROY及菜單項(xiàng)“Edit|Copy”的消息處理函數(shù),分析Class
27、Wizard完成了哪些工作。 class CMainFrame : CFrameWndpublic: CMainFrame();protected: /AFX_MSG(CMainFrame) / 聲明消息處理函數(shù)原形 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); / 由程序向?qū)ё詣?dòng)生成 afx_msg void OnClose(); / 由ClassWizard類向?qū)砑?afx_msg void OnDestroy(); afx_msg void OnEditCopy(); /AFX_MSG DECLARE_MESSAGE_MAP(
28、) / 聲明使用消息映射宏;ClassWizard在類的定義中聲明了消息處理函數(shù)在類的定義中聲明了消息處理函數(shù) :l發(fā)送消息到一個(gè)窗口可以采用傳送(Send)或寄送(Post)方式,這兩種方式之間的主要區(qū)別是消息被接收對(duì)象收到后是否立即被處理。Windows提供了三個(gè)API函數(shù)用于消息的發(fā)送。l函數(shù)SendMessage()用于向一個(gè)或多個(gè)窗口傳送消息,該函數(shù)將調(diào)用目標(biāo)窗口的窗口函數(shù),直到目標(biāo)窗口處理完收到的消息,該函數(shù)才返回。 l函數(shù)PostMessage()用于向一個(gè)或多個(gè)窗口寄送消息,它把消息放在指定窗口創(chuàng)建的線程的消息隊(duì)列中,然后不等消息處理完就返回。7.4.2 消息的發(fā)送消息的發(fā)送l
29、函數(shù)SendDlgItemMessage()函數(shù)用于向?qū)υ捒蛑兄付ǖ目丶l(fā)送消息,直到目標(biāo)控件處理完收到的消息,該函數(shù)才返回。 lMFC將這三個(gè)函數(shù)封裝為CWnd窗口類的成員函數(shù),封裝了目標(biāo)窗口句柄,它們將向調(diào)用它的窗口對(duì)象發(fā)送或寄送消息,如pMyView-SendMessage()的調(diào)用形式表示向pMyView所指對(duì)象發(fā)送消息。l與用戶輸入相關(guān)的消息(如鼠標(biāo)消息和鍵盤消息)通常是以寄送(Post)的方式發(fā)送,以便這些用戶輸入可以由運(yùn)行較緩慢的系統(tǒng)進(jìn)行緩沖處理。而其它消息通常是以傳送(Send)的方式發(fā)送l由于程序邏輯設(shè)計(jì)結(jié)構(gòu)的限制或不同窗口之間數(shù)據(jù)的同步,程序員需要手工自定義一些消息。例如,
30、如果需要在特定時(shí)間間隔內(nèi)通知所有數(shù)據(jù)輸出窗口重新取得數(shù)據(jù),就必須采用定時(shí)器事件來(lái)產(chǎn)生特定的消息。lMFC允許用戶自定義消息,常量WM_USER(為0 x0400)與第一個(gè)自定義消息值相對(duì)應(yīng),用戶必須為自己的消息定義相對(duì)于WM_USER的偏移值,。利用#define語(yǔ)句定義自己的消息,例如:#define WM_USER1 WM_USER+0#define WM_USER2 WM_USER+17.4.3 自定義消息處理自定義消息處理必須在函數(shù)返回類型前面加上afx_msg標(biāo)識(shí),如: afx_msg LRESULT memberFxn ( WPARAM wParam , LPARAM lParam
31、);其中,參數(shù)wParam、lParam用于傳遞消息的兩個(gè)附加信息自定義消息處理函數(shù)的聲明:自定義消息處理函數(shù)的聲明: ON_MESSAGE(message, memberFxn)其中,message是消息名標(biāo)識(shí),memberFxn是對(duì)應(yīng)的消息處理函數(shù)。如: ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)自定義消息映射宏的定義自定義消息映射宏的定義:1首先利用MFC AppWizardexe向?qū)?chuàng)建一個(gè)名為Rotate的應(yīng)用程序。利用ClassWizard類向?qū)镃RotateView類生成消息WM_CREATE的消息處理函數(shù),通過(guò)設(shè)置定時(shí)器在指定的時(shí)間間隔向窗口發(fā)
32、送WM_TIMER消息。 SetTimer(1,200,NULL); / 啟動(dòng)定時(shí)器2在文件RotateView.cpp開始位置定義一個(gè)用戶自定義消息:#define WM_MYMESSAGE WM_USER+1 利用ClassWizard為CRotateView類生成消息WM_TIME的消息處理函數(shù):SendMessage(WM_MYMESSAGE); 例例 編寫一個(gè)自定義消息應(yīng)用程序,程序啟動(dòng)后設(shè)置一個(gè)定時(shí)器,在WM_TIMER的消息處理函數(shù)中發(fā)送一個(gè)用戶自定義消息,在對(duì)應(yīng)的自定義消息處理函數(shù)中以動(dòng)畫的形式旋轉(zhuǎn)顯示一行文本。 3在類CRotateView的定義中聲明自定義消息處理函數(shù):af
33、x_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); 在文件RotateView.cpp消息映射BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之間添加自定義消息映射宏:ON_MESSAGE(WM_MYMESSAGE,OnMyMyessage) 4在類CRotateView的定義中聲明一個(gè)private屬性、int型的成員變量m_dEscapement,它表示文本顯示角度,并在類CRotateView的構(gòu)造函數(shù)中初始化:m_dEscapement=0; 5在文件RotateView.cpp中手工添加自定義消息處理函數(shù)
34、實(shí)現(xiàn)代碼,完成以動(dòng)畫形式旋轉(zhuǎn)顯示一行文本的功能。6利用ClassWizard生成消息WM_DESTROY的消息處理函數(shù),在銷毀已創(chuàng)建的定時(shí)器:KillTimer(1); 宏宏就是用預(yù)處理指令#define定義一個(gè)標(biāo)識(shí)符,用它來(lái)表示一個(gè)字符串或一段源代碼。MFC宏宏作為MFC類庫(kù)的一個(gè)組成部分在MFC應(yīng)用程序中經(jīng)常出現(xiàn)。MFC宏在Afxwin.h、Afx.h及Afxmsg_.h等MFC頭文件中分別進(jìn)行了定義。 MFC提供的宏有很多,常用的包括消息映射宏、運(yùn)行時(shí)類型識(shí)別的宏、調(diào)試宏和異常宏等,下表列出了一般MFC編程時(shí)要用到的宏。 7.5 MFC宏宏 RUNTIME_CLASS獲得運(yùn)行時(shí)類的CRu
35、ntimeClass結(jié)構(gòu)的DECLARE_DYNAMIC提供基本的運(yùn)行時(shí)類型識(shí)別(聲明)IMPLEMENT_ DYNAMIC提供基本的運(yùn)行時(shí)類型識(shí)別(實(shí)現(xiàn))DECLARE_DYNCREATE動(dòng)態(tài)創(chuàng)建(聲明)IMPLEMENT_DYNCREATE動(dòng)態(tài)創(chuàng)建(實(shí)現(xiàn))DECLARE_SERIAL對(duì)象序列化(聲明)IMPLEMENT_SERIAL對(duì)象序列化(實(shí)現(xiàn))DECLARE_MESSAGE_MAP聲明消息映射表BEGIN_MESSAGE_MAP開始建立消息映射表END_MESSAGE_MAP結(jié)束建立消息映射表ON_COMMAND命令消息映射宏ON_MESSAGE自定義消息映射宏ON_WM_MFC預(yù)定
36、義消息映射宏ON_BN_ , ON_CBN_ 等控件通知(Notification)消息映射宏 運(yùn)行時(shí)類型識(shí)別RTTI(Run Time Type Information)是指在程序運(yùn)行時(shí)允許確定對(duì)象的類型。MFC擴(kuò)充了一般C+中運(yùn)行時(shí)類型識(shí)別的功能,當(dāng)一個(gè)類支持MFC的運(yùn)行時(shí)類型識(shí)別時(shí),它允許程序獲取對(duì)象的信息(如類名、所占存儲(chǔ)空間大小及版本號(hào)等)和基類信息。1. 宏宏RUNTIME_CLASS(class_name): 返回參數(shù)class_name所指定類的靜態(tài)成員變量class#class_name的指針,該指針指向一個(gè)CRuntimeClass結(jié)構(gòu)。7.5.1 有關(guān)運(yùn)行時(shí)類型識(shí)別的宏有
37、關(guān)運(yùn)行時(shí)類型識(shí)別的宏2. 動(dòng)態(tài)支持宏動(dòng)態(tài)支持宏DECLARE_DYNAMIC()和和IMPLEMENT_DYNAMIC(): 使用動(dòng)態(tài)支持宏能夠使CObject派生類的對(duì)象具有基本的類型識(shí)別機(jī)能,可以通過(guò)調(diào)用成員函數(shù)CObject:IsKindOf()測(cè)試對(duì)象與給定類的關(guān)系。3. 動(dòng)態(tài)創(chuàng)建宏動(dòng)態(tài)創(chuàng)建宏DECLARE_DYNCREATE()和和IMPLEMENT_DYNCREATE(): 動(dòng)態(tài)創(chuàng)建是動(dòng)態(tài)支持的一個(gè)超集,除了基本的類型識(shí)別機(jī)能,使用動(dòng)態(tài)創(chuàng)建宏能夠使CObject的派生類具有在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建對(duì)象的功能。4. 序列化宏序列化宏DECLARE_SERIAL() 和和IMPLEMENT_S
38、ERIAL() / 在頭文件MyClass.h中class CMyClass : public CObjectDECLARE_DYNAMIC(CMyClass)public:void SomeFunction(void); ; 例例 定義類MyClass,使用RUNTIME_CLASS()宏的基本對(duì)象診斷功能。 / 在實(shí)現(xiàn)文件MyClass.cpp中#include MyClass.hIMPLEMENT_DYNAMIC(CMyClass, CObject)void CMyClass:SomeFunction(void) CObject* pObject=new CMyClass; if(pOb
39、ject-IsKindOf(RUNTIME_CLASS(CMyClass) CMyClass* pMyObject=(CMyClass*) pObject;AfxMessageBox(MyObject is an object of the class CMyClass); else AfxMessageBox(MyObject is not an object of the class CMyClass); delete pObject;7.5.2 MFC調(diào)試宏調(diào)試宏 跟蹤聲明和斷言在查找程序設(shè)計(jì)錯(cuò)誤時(shí)是非常有用的。跟蹤聲明可以讓程序在運(yùn)行過(guò)程中遇到跟蹤聲明時(shí)在輸出窗口顯示指定的信息,而斷言
40、使程序在斷言條件不成立時(shí)暫停程序的運(yùn)行。MFC提供了一些跟蹤聲明和斷言宏用于程序調(diào)試,這些宏只能用于DEBUG版本應(yīng)用程序的調(diào)試狀態(tài)。1TRACE()宏語(yǔ)法說(shuō)明如下:TRACE (); 其中參數(shù)是由輸出格式和變量等組成的輸出表達(dá)式,其格式與函數(shù)printf()的參數(shù)一樣,它指定調(diào)試時(shí)要在Output窗口輸出的內(nèi)容。 char* szName = “LiMing”;int nAge = 18;TRACE(“Name = %s, Age = %d n”, szName, nAge ); 例例1 對(duì)于以下代碼: 調(diào)試時(shí)在Output窗口輸出以下內(nèi)容:Name = LiMing, Age = 18 例
41、例2 設(shè)自定義一個(gè)CFrameWnd的派生類CMyFrame,在程序中構(gòu)建一個(gè)與CMyFrame相關(guān)聯(lián)的文檔模板對(duì)象,并為構(gòu)鍵的文檔模板創(chuàng)建框架窗口: CMyFrame* pFrame=(CMyFrame*) AfxGetMainWnd(); ASSERT(pFrame-IsKindOf(RUNTIME_CLASS (CMyFrame); / 判斷pFrame的類型 pFrame-DoSomeOperation(); 7.6.1 CRuntimeClass結(jié)構(gòu)結(jié)構(gòu) lCRuntimeClass在MFC中是以結(jié)構(gòu)的方式定義,它含有使用CRuntimeClass結(jié)構(gòu)的類的有關(guān)信息,與CObject
42、類一同實(shí)現(xiàn)運(yùn)行時(shí)類型識(shí)別RTTI的功能。CRuntimeClass結(jié)構(gòu)包含了類名、對(duì)象所占存儲(chǔ)空間大小及類的版本號(hào)等成員變量和動(dòng)態(tài)對(duì)象創(chuàng)建、派生關(guān)系判斷等成員函數(shù)。 l每個(gè)從CObject類派生的類都有一個(gè)CRuntimeClass對(duì)象同它關(guān)聯(lián)。要使用CRuntimeClass結(jié)構(gòu),必須結(jié)合使用RUNTIME_CLASS()宏和其它有關(guān)運(yùn)行時(shí)類型識(shí)別的MFC宏。 7.6 常用的常用的MFC類類 7.6.2 CObject類類 l由于MFC中大部分類是從CObject類繼承而來(lái)的,CObject類描述了幾乎所有的MFC類的一些公共特性,CObject類為程序員提供了對(duì)象診斷、運(yùn)行時(shí)類型識(shí)別和序列
43、化等功能。 l對(duì)象診斷。MFC提供了兩種診斷特性:利用成員函數(shù)AssertValid()進(jìn)行對(duì)象有效性檢查,使得類可以在繼續(xù)運(yùn)行前對(duì)自己進(jìn)行正確性檢查;利用成員函數(shù)Dump()輸出對(duì)象的數(shù)據(jù)成員的值。 l運(yùn)行時(shí)訪問(wèn)類的信息:提供GetRuntimeClass()和IskindOf()兩個(gè)成員函數(shù)來(lái)支持運(yùn)行時(shí)類型識(shí)別。l對(duì)象序列化。 void CHuman:AssertValid() const CObject:AssertValid(); ASSERT(m_year0); ASSERT(m_year120); 例例1 通過(guò)“Insert|New Class”定義一個(gè)CObject的派生類CHuman。在類CHuman中重載AssertValid()函數(shù),利用ASSERT宏把人
溫馨提示
- 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ù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年石家莊市稅務(wù)系統(tǒng)遴選面試真題附帶題目詳解含答案
- 2024年移動(dòng)互聯(lián)網(wǎng)行業(yè)市場(chǎng)前景及投資研究報(bào)告-培訓(xùn)課件
- 麻醉學(xué)中級(jí)題庫(kù)(附答案)
- 老年居家安全課件
- 老師職業(yè)介紹課件下載
- 2025年搬運(yùn)車行業(yè)市場(chǎng)突圍建議及需求分析報(bào)告
- 鏟車司機(jī)職業(yè)病防治及健康保障協(xié)議
- 財(cái)務(wù)分析智能財(cái)務(wù)咨詢顧問(wèn)解決方案軟件合同
- 廠房搬遷與智能化生產(chǎn)系統(tǒng)合同
- 高新技術(shù)企業(yè)廠房租賃中介服務(wù)合同樣本
- 人工智能倫理規(guī)則
- 工程物探-第五章電法勘探課件
- 婦產(chǎn)科護(hù)理學(xué)教材(課后思考題參考答案)
- 二年級(jí)數(shù)學(xué)無(wú)紙化監(jiān)測(cè)試題
- 臺(tái)區(qū)線損綜合分析臺(tái)區(qū)線損分類及計(jì)算方法
- 全同態(tài)加密算法概述
- 【酒店管理系統(tǒng)的設(shè)計(jì)與開發(fā)(論文)】
- 電流、電壓指針儀表校驗(yàn)報(bào)告
- 六年級(jí)下冊(cè)英語(yǔ)素材-Unit-6-General-revision-3-知識(shí)點(diǎn)-人教精通版
- 2023年云南玉溪市直事業(yè)單位選調(diào)45人筆試備考試題及答案解析
- BS2000標(biāo)準(zhǔn)操作規(guī)程
評(píng)論
0/150
提交評(píng)論