版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第二章
MFC編程基礎(chǔ)知識(shí)本章介紹MFC的基本原理Windows操作系統(tǒng)采用了圖形用戶界面,借助于它提供的API(
Application
ProgrammingInterface)函數(shù),用戶可以編出具有漂亮圖形界面的程序。Windows本身是面向?qū)ο蟮?,因此采用面向?qū)ο蟮某绦蛟O(shè)計(jì)更為自然。V
C++的微軟基礎(chǔ)類庫(kù)(MicrosoftFoundationClassLibrary,MFC)封裝了大部分API函數(shù),并提供了一個(gè)應(yīng)用程序框架,簡(jiǎn)化和標(biāo)準(zhǔn)化了Windows程序設(shè)計(jì),因此MFC編程被稱為標(biāo)準(zhǔn)Windows程序設(shè)計(jì)。第二章
MFC編程基礎(chǔ)知識(shí)(選讀)2.1
傳統(tǒng)的Windows編程2.3
MFC基礎(chǔ)類及其層次結(jié)構(gòu)2.5
MFC對(duì)象和Windows對(duì)象2.4 MFC編程2.7
MFC中的文件處理2.6 MFC的消息映射2.2
Windows對(duì)象句柄2.1
傳統(tǒng)的Windows
編程Windows操作系統(tǒng)的特征:Windows操作系統(tǒng)是多任務(wù)、圖形界面的操作系統(tǒng)。
Windows擁有一個(gè)圖形用戶界面(GUI)。用戶可以用鍵盤和鼠標(biāo)與顯示器上的圖形實(shí)現(xiàn)直接交互。Windows支持多任務(wù)操作,可在同一時(shí)刻運(yùn)行多個(gè)程序,并可在程序間進(jìn)行信息交互。每個(gè)程序只能在稱為“窗口”的屏幕矩形區(qū)中實(shí)現(xiàn)輸出。Windows的圖形設(shè)備接口(GDI),實(shí)現(xiàn)了程序與設(shè)備的無(wú)關(guān)性,即為Windows編寫的應(yīng)用程序可以運(yùn)行于任何具有Windows設(shè)備驅(qū)動(dòng)程序的硬件環(huán)境中,方便了使用。2.1
傳統(tǒng)的Windows
編程API函數(shù):為使程序員在編寫應(yīng)用程序時(shí)實(shí)現(xiàn)這些特征,
Windows提供了一個(gè)應(yīng)用程序編程接口,稱WindowsAPI(Application
Programming
Interface),這是
Windows支持的函數(shù)定義、參數(shù)定義和消息格式的集合,可供應(yīng)用程序調(diào)用。這上千個(gè)API函數(shù)包含了各種窗口類和系統(tǒng)資源(內(nèi)存管理、文件、線程等等)。利用這些函數(shù)就可以編出具有Windows風(fēng)格的程序。Windows
API也是
Windows操作系統(tǒng)自帶的在Windows環(huán)境下運(yùn)行的軟件開發(fā)包(SDK)。程序員總是直接或間接引用API進(jìn)行應(yīng)用程序的開發(fā),所以Windows應(yīng)用程序就有大致相同的用戶界面。2.1
傳統(tǒng)的Windows
編程C/C++調(diào)用API函數(shù)的優(yōu)勢(shì):Windows環(huán)境下的最佳編程語(yǔ)言就是C/C++語(yǔ)言,因?yàn)閃indows
API函數(shù)本身就是用C語(yǔ)言編寫的,C和C++調(diào)用C語(yǔ)言的API函數(shù)是直接調(diào)用,而其他語(yǔ)言則多一道轉(zhuǎn)換。C/C++編程可以很方便地利用計(jì)算機(jī)的底層資源,其程序運(yùn)行速度遠(yuǎn)遠(yuǎn)高于其他語(yǔ)言。2.1
傳統(tǒng)的Windows
編程標(biāo)準(zhǔn)Win32
API函數(shù)分類:系統(tǒng)服務(wù)通用控件庫(kù)圖形設(shè)備接口網(wǎng)絡(luò)服務(wù)用戶接口系統(tǒng)ShellWindows系統(tǒng)信息2.1
傳統(tǒng)的Windows
編程傳統(tǒng)的Windows編程:直接采用API進(jìn)行的C/C++程序設(shè)計(jì)【例2.1】一個(gè)對(duì)話框的簡(jiǎn)單Windows程序:#include<windows.h>int
APIENTRY
WinMain(HINSTANCE
hInstance,HINSTANCE
hPreinstance,LPSTR
lpCmdLine,int
nCmdshow){MessageBox(NULL,"This
is
a
MessageBox
windowsexample","Ex2_1",MB_OK);return
0;}2.1
傳統(tǒng)的Windows
編程說(shuō)明:windows.h是windows程序最基本的頭文件,它包含了其它幾個(gè)
windows頭文件,它們定義了windows的所有數(shù)據(jù)類型、數(shù)據(jù)結(jié)構(gòu)、符號(hào)常量和API函數(shù)原型聲明。MessageBox是一個(gè)API函數(shù),顯示一個(gè)消息框。其中:第一個(gè)參數(shù)指明此消息框的父窗口句柄,為NULL則說(shuō)明沒(méi)有父窗口;第二、三個(gè)參數(shù)類型均為字符型指針,分別指向消息框中要顯示的字符串和消息框標(biāo)題欄顯示的字符串;第四個(gè)參數(shù)是一個(gè)無(wú)符號(hào)整數(shù),表明消息框中顯示的按鈕和風(fēng)格。#define
MB_OK
0x00000000L#define
MB_OKCANCEL
0x00000001L//OK按鈕//OK和CANCEL兩個(gè)按鈕#define
MB_ABORTRETYRIGNORE
0x00000002L//ABORT,RETRY和IGNORE3個(gè)按鈕#define
MB_YESNOCANCEL
0x00000003L//YES、NO和CANCEL共3個(gè)按鈕2.1
傳統(tǒng)的Windows
編程(3)
WinMain函數(shù)是windows程序的入口函數(shù),包含4個(gè)參數(shù):
hInstance是唯一標(biāo)識(shí)本程序的實(shí)例句柄,系統(tǒng)和其它應(yīng)用程序通過(guò)該句柄與本程序通訊。hPrevInstance是本程序的前一個(gè)實(shí)例句柄,由于32位windows采用進(jìn)程-線程模式,每一線程擁有自己的句柄,因此該參數(shù)始終為空。lpCmdLine是一個(gè)字符串指針,指向命令行參數(shù)字符串,沒(méi)有命令行參數(shù)時(shí)為空。nCmdShow指明程序最初運(yùn)行時(shí)窗口打開方式,如正常方式、最大化或最小化運(yùn)行。WinMain返回一個(gè)整數(shù)值,作為退出代碼。APIENTRY表示函數(shù)調(diào)用約定,函數(shù)調(diào)用時(shí)參數(shù)按從左至右的順序壓入棧,由被調(diào)用者將參數(shù)彈出棧。2.1
傳統(tǒng)的Windows
編程典型的Windows程序結(jié)構(gòu):Windows程序采用事件驅(qū)動(dòng)、消息傳遞方式,由入口函數(shù)和窗口函數(shù)兩部分組成。入口函數(shù)中有一個(gè)由while語(yǔ)句組成的消息循環(huán),其中調(diào)用了諸如獲取消息、鍵盤消息轉(zhuǎn)換、派送消息和窗口處理函數(shù)等API函數(shù),循環(huán)直到取得退出消息(WIN-QUIT)結(jié)束。在應(yīng)用程序中還有由操作系統(tǒng)的API函數(shù)回調(diào)(callback)的窗口處理函數(shù)(簡(jiǎn)稱窗口函數(shù)),根據(jù)消息值轉(zhuǎn)向相應(yīng)的消息處理,這是由switch語(yǔ)句組成的多向選擇。如果不能處理則轉(zhuǎn)缺省的窗口函數(shù)。參見圖2.3。2.1
傳統(tǒng)的Windows
編程圖2.3
Windows消息流程2.1
傳統(tǒng)的Windows
編程【例2.2】顯示一個(gè)窗口的Windows應(yīng)用程序。#include<windows.h>
//包含windows.h頭文件
LRESULT
CALLBACK
WndProc(HWND,UINT,WPARAM,LPARAM);
//窗口函數(shù)聲明/*入口函數(shù)WinMain()*/int
APIENTRY
WinMain(HINSTANCE
hInstance,HINSTANCE
hPrevInstance,
LPSTR
lpCmdLine,intnCmdShow){WNDCLASS
wndclass;HWND
hwnd;MSG
msg;//定義窗口類結(jié)構(gòu)變量//定義窗口句柄//定義消息結(jié)構(gòu)變量2.1
傳統(tǒng)的Windows
編程/*窗口類使用步驟*//*定義窗口類的各屬性*/wndclass.style
=
CS_HREDRAW|CS_VREDRAW;//改變窗口大小則重畫wndclass.lpfnWndProc
=
WndProc;
//窗口函數(shù)為
WndProcwndclass.cbClsExtra
=
0;
//窗口類無(wú)擴(kuò)展wndclass.cbWndExtra
=
0;
//窗口實(shí)例無(wú)擴(kuò)展wndclass.hInstance
=
hInstance;
//注冊(cè)窗口類實(shí)例句柄wndclass.hIcon
=
LoadIcon(NULL,IDI_APPLICATION);//用默認(rèn)光標(biāo)wndclass.hCursor
=
LoadCursor(NULL,IDC_ARROW);//用箭頭光標(biāo)
wdclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
//背景為白色wndclass.lpszMenuName=NULL;
//窗口缺省無(wú)菜單
wndclass.lpszClassName="Ex2_2";
//窗口類名為Ex2_22.1
傳統(tǒng)的Windows
編程/*設(shè)置后,必須注冊(cè)窗口類設(shè)置才生效*/if(!
RegisterClass(&wndclass))return
FALSE;/*前面只是定義了窗口類,下面創(chuàng)建窗口*/hwnd
=
CreateWindow("Ex2_2",
//窗口類名
Ex2_2"Ex2_2",
//窗口名EX2_2WS_OVERLAPPEDWINDOW,//重疊式窗口CW_USEDEFAULT,
CW_USEDEFAULT,//左上角屏幕坐標(biāo)
CW_USEDEFAULT,CW_USEDEFAULT,//寬度和高度NULL,NULL,hInstance,NULL);//此窗口無(wú)父窗口//此窗口無(wú)主菜單//創(chuàng)建此窗口的實(shí)例句柄//此窗口無(wú)創(chuàng)建參數(shù)2.1
傳統(tǒng)的Windows
編程/*顯示并更新窗口*/ShowWindow(hwnd,nCmdShow);
//顯示窗口//更新窗口的客戶區(qū)UpdateWindow
(hwnd);/*消息循環(huán)*///獲取消息,遇WM_QUIT退出循環(huán)while(GetMessage
(&msg,NULL,0,0))
{TranslateMessage
(&msg);DispatchMessage
(&msg);//鍵盤消息轉(zhuǎn)換//派送消息給窗口函數(shù)}return
msg.wParam;//返回退出值}2.1
傳統(tǒng)的Windows
編程/*窗口函數(shù)*/LRESULT
CALLBACK
WndProc(HWND
hwnd,UINT
message,WPARAM
wParam,
LPARAM
lParam){//根據(jù)消息值轉(zhuǎn)相應(yīng)的消息處理
switch
(message){case
WM_PAINT:
//重畫窗口客戶區(qū)消息處理HDChdc;PAINTSTRUCT
ps;//定義設(shè)備描述表句柄//定義繪圖信息結(jié)構(gòu)變量//獲取要重畫的窗口的設(shè)備描述表句柄
hdc=BeginPaint
(hwnd,&ps);TextOut
(hdc,0,0,"This
is
my
Windows
application”,26);//輸出文本EndPaint
(hwnd,&ps);
//結(jié)束重畫,釋放設(shè)備描述表句柄
return
0;2.1
傳統(tǒng)的Windows
編程case
WM_DESTROY:
//撤消窗口消息處理PostQuitMessage
(0);
//產(chǎn)生退出程序消息WM_QUITreturn
0;wParam,
lParam);}return
DefWindowProc
(hwnd,
message,//其它轉(zhuǎn)缺省窗口函數(shù)}程序的運(yùn)行結(jié)果:事件驅(qū)動(dòng)、消息傳遞事件與消息:事件-----在Windows環(huán)境下,應(yīng)用程序啟動(dòng)后,系統(tǒng)等待用戶在圖形用戶界面內(nèi)的輸入選擇,如鼠標(biāo)按鍵、鍵盤按鍵、窗口被創(chuàng)建、關(guān)閉、改變大小、移動(dòng)等,對(duì)系統(tǒng)來(lái)說(shuō),這都是事件。只要有事件發(fā)生,系統(tǒng)即產(chǎn)生特定的消息。消息描述了事件的類別,包含了相關(guān)信息,Windows應(yīng)用程序利用消息與系統(tǒng)及其它應(yīng)用程序進(jìn)行信息交換。由于windows事件的發(fā)生的是隨機(jī)的,程序的執(zhí)行先后順序也無(wú)法預(yù)測(cè),系統(tǒng)采用消息隊(duì)列來(lái)存放事件發(fā)生的消息,然后從消息隊(duì)列中依次取出消息進(jìn)行相應(yīng)的處理。事件驅(qū)動(dòng)、消息傳遞消息結(jié)構(gòu)的定義如下:typedef
struct
tagMSG
{HWNDUINThWnd;message;//指定消息發(fā)向的窗口句柄//標(biāo)識(shí)消息的消息值WPARAM
wParam;//消息參數(shù)LPARAM
lParam;DWORD
time;//消息參數(shù)//消息進(jìn)入隊(duì)列的時(shí)間POINT
pt;//消息進(jìn)入隊(duì)列時(shí)鼠標(biāo)指針的屏幕坐標(biāo)}MSG,*PMSG,NEAR
*NPMSG,
FAR
*
LPMSG;事件驅(qū)動(dòng)、消息傳遞消息結(jié)構(gòu)中各個(gè)成員的意義:message——是標(biāo)識(shí)消息的消息值或消息名。每個(gè)消息都有唯一一個(gè)數(shù)值標(biāo)識(shí),常用不同前綴的符號(hào)常量以示區(qū)別。例如,WM_表示窗口消息。Windows常用的窗口消息和消息值定義于winuser.h中#define
WM_CREATE0X0001
//創(chuàng)建窗口產(chǎn)生的消息#define
WM_DESTROY
0X0002
//撤銷窗口產(chǎn)生的消息#define
WM_PAINT#define
WM_CLOSE#define
WM_CHAR#define
WM_USER0X000F
//重畫窗口產(chǎn)生的消息0X0010
//關(guān)閉窗口產(chǎn)生的消息0X0102
//按下非系統(tǒng)鍵產(chǎn)生的字符消息0X0400
//用戶自定義消息事件驅(qū)動(dòng)、消息傳遞wParam,lParam——消息參數(shù),均為32位其數(shù)據(jù)類型在windef.h中定義如下:typedeftypedefUINTLONGWPARAM;LPARAM;pt——表示消息進(jìn)入消息隊(duì)列時(shí)鼠標(biāo)指針的屏幕坐標(biāo),數(shù)據(jù)類型POINT是定義在windef.h中的結(jié)構(gòu)體,表示屏幕上一點(diǎn),定義如下:typedef
struct
tagPOINT
{LONGLONGx;
//表示點(diǎn)的屏幕橫坐標(biāo)y;
//表示點(diǎn)的屏幕縱坐標(biāo)}POINT,
*PPOINT,NEAR
*NPPOINT,FAR
*LPPOINT;Windows數(shù)據(jù)類型數(shù)據(jù)類型說(shuō)
明BYTE8位無(wú)符號(hào)字符PSTR32位字符指針COLORREF32位整數(shù),表示一個(gè)顏色WORD16位無(wú)符號(hào)整數(shù)LONG32位有符號(hào)整數(shù)DWORD32位無(wú)符號(hào)整數(shù),是WORD的兩倍長(zhǎng)度UINT32位無(wú)符號(hào)整數(shù)BOOL布爾值,值為TRUE或FALSEHANDLE句柄常用windows數(shù)據(jù)類型:Windows數(shù)據(jù)類型數(shù)據(jù)類型說(shuō)
明LPSTR32位指針,指向字符LPCSTR32位指針,指向字符串常量LPTSTR32位指針,指向字符串,此字符串可移植到Unicode和DBCS雙字符集LPCTSTR32位指針,指向字符串常量,此串可移植到Unicode和DBCS雙字符集LPVOID32位指針,可指向任何類型數(shù)據(jù)LPRESULT32位數(shù)值,作為窗口函數(shù)或CALLBACK函數(shù)的返回類型WNDPROC32位指針,指向一個(gè)窗口函數(shù)LPARAM32位數(shù)值,作為窗口函數(shù)和CALLBACK函數(shù)的參數(shù)WPARAM作為窗口函數(shù)和CALLBACK函數(shù)的參數(shù),在win
16中是
16位,在win
32中是32位窗口類及其使用步驟窗口結(jié)構(gòu)類型:typedef
struct
tagWNDCLASS
{//窗口風(fēng)格UINTstyle;WNDPROClpfnWndProc;int
cbClsExtra;int
cbWndExtra;HINSTANCE
hInstance;HICON
hIcon;HCURSORhCursor;HBRUSH
hbrBackGround;LPCSTR
lpszMenuName;LPCSTR
lpszClassName;//指向窗口處理函數(shù)的函數(shù)指針//窗口結(jié)構(gòu)中的預(yù)留字節(jié)數(shù)//為其它創(chuàng)建窗口預(yù)留字節(jié)數(shù)//注冊(cè)該窗口類的實(shí)例句柄//代表該窗口類的圖標(biāo)句柄//該窗口客戶區(qū)鼠標(biāo)光標(biāo)句柄//該窗口背景顏色句柄//指向窗口菜單名的字符指針//指向窗口名的字符指針}
WNDCLASS,
*PWNDCLASS,NEAR
*NPWNDCLASS,FAR
*LPWNDCLASS;窗口類及其使用步驟WinMain()函數(shù)完成第一項(xiàng)工作——建立一個(gè)窗口定義一個(gè)窗口類,包括定義窗口對(duì)象并對(duì)它的相關(guān)成員賦值。注冊(cè)窗口類,調(diào)用RegisterClass()注冊(cè)窗口類,并判斷是否注冊(cè)成功。其參數(shù)是WNDCLASS結(jié)構(gòu)類型指針,用需要注冊(cè)的窗口對(duì)象地址進(jìn)行調(diào)用。創(chuàng)建窗口,定義注冊(cè)窗口后,可以創(chuàng)建一個(gè)或多個(gè)同類型的窗口;由API函數(shù)CreateWindow()創(chuàng)建窗口,并返回所創(chuàng)建窗口的句柄。調(diào)用API函數(shù)ShowWindow()和UpdateWindow()顯示并更新窗口,它們的參數(shù)相同,第一個(gè)參數(shù)是要顯示的窗口句柄,第二個(gè)參數(shù)是窗口顯示的方式。消息循環(huán)與消息傳遞消息循環(huán)(while循環(huán))GetMessage()函數(shù)從應(yīng)用程序消息隊(duì)列中讀取消息,TranslateMessage()函數(shù)進(jìn)行鍵盤消息轉(zhuǎn)換,然后由DispatchMessag()將消息派送給相應(yīng)的窗口函數(shù)進(jìn)行處理;當(dāng)消息隊(duì)列為空時(shí),應(yīng)用程序進(jìn)入等待狀態(tài),等待用戶輸入。GetMessage()函數(shù)聲明如下:BOOL WINAPI
GetMessage
(LPMSG,
HWND,
UINT,
UINT
);其中第1個(gè)參數(shù)為存放消息的MSG結(jié)構(gòu)指針,第2個(gè)參數(shù)表示接收消息的窗口句柄,第3、4個(gè)參數(shù)分別表示要獲取的最大和最小消息值。當(dāng)后3個(gè)參數(shù)值設(shè)為NULL或0時(shí),表示應(yīng)用程序接收它所創(chuàng)建的所有窗口的所有消息。當(dāng)GetMessage()獲取到WM_QUIT消息時(shí),返回FALSE,結(jié)束消息循環(huán)。消息循環(huán)與消息傳遞TranslateMessage()函數(shù)負(fù)責(zé)鍵盤消息轉(zhuǎn)換。
擊鍵消息除字符鍵消息外,其它擊鍵操作產(chǎn)生虛擬鍵消息,包括WM_KEYDOWN,WM_SYSKEYDOWN,WM_KEYUP,WM_SYSKEYUP,這些虛擬鍵消息必須通過(guò)轉(zhuǎn)換成字符消息程序才能響應(yīng)。消息循環(huán)與消息傳遞消息派送流程DispatchMessage函數(shù)根據(jù)消息所包含的信息,將消息派送到相應(yīng)的窗口函數(shù),過(guò)程如圖:MSGhWndMessagewParawIparamTimePtHWNDEx2_2Ex2_2…StyleWndproc…Ex2_2Ex2_2WNDCLASS窗口處理函數(shù)WndProc()應(yīng)用程序創(chuàng)建的每一個(gè)窗口或?qū)υ捒蚨紝?duì)應(yīng)一個(gè)窗口處理函數(shù),處理來(lái)自窗口的消息。對(duì)于應(yīng)用程序,WinMain()函數(shù)都差不多,編程的主要任務(wù)就是編寫窗口函數(shù)。
WndProc()的原型如下:LRESULT
CALLBACK WndProc(HWND
hwnd,UINT
message,WPARAM
wParam,
LPARAM
lParam);其中,第一個(gè)參數(shù)表示對(duì)應(yīng)窗口的句柄,第二個(gè)參數(shù)是需要處理的消息的消息值,第三、四個(gè)參數(shù)包含了相應(yīng)消息的某些信息,如消息發(fā)生時(shí)鼠標(biāo)位置等。WndProc()函數(shù)的結(jié)構(gòu)是一個(gè)switch語(yǔ)句,根據(jù)消息值不同,選擇不同的case子句執(zhí)行,如WM_PAINT消息表示窗口客戶區(qū)需要重畫,WM_DESTROY消息表示窗口要被撤銷等。如果message參數(shù)的值與各個(gè)case子句的常量都不同,則調(diào)用
DefWindowProc()函數(shù)處理。進(jìn)隊(duì)和不進(jìn)隊(duì)消息窗口函數(shù)一般由系統(tǒng)調(diào)用,應(yīng)用程序不直接調(diào)用它,而是通過(guò)PostMessage()和SendMessage()函數(shù)傳遞消息來(lái)間接調(diào)用窗口函數(shù)。消息分為進(jìn)隊(duì)消息和不進(jìn)隊(duì)消息。(1)進(jìn)隊(duì)消息是由windows放入應(yīng)用程序消息隊(duì)列、由應(yīng)用程序消息循環(huán)從消息隊(duì)列中取出并派送到窗口函數(shù)的消息。進(jìn)隊(duì)消息一般由用戶操作產(chǎn)生,如鼠標(biāo)移動(dòng)、點(diǎn)擊產(chǎn)生的消息,鍵盤按鍵消息,重畫窗口消息等。調(diào)用API函數(shù)
PostMessage()可以郵送(post)一條消息到指定窗口的消息隊(duì)列,其原型如下:BOOL
WINAPI
PostMessage(HWND
hWnd, UINT
Msg,WPARAM
wParam,
LPARAM
lParam)
;其中Msg參數(shù)指定了要發(fā)送的消息值(名)。
PostQuitMessage()調(diào)用本函數(shù)郵送消息。進(jìn)隊(duì)和不進(jìn)隊(duì)消息(2)
不進(jìn)隊(duì)消息,直接發(fā)送(send)給指定窗口的窗口函數(shù)進(jìn)行處理。程序中調(diào)用某些特定的API函數(shù)會(huì)產(chǎn)生不進(jìn)隊(duì)消息。如調(diào)用CreateWindow()創(chuàng)建窗口時(shí)發(fā)送的WM_CREATE消息,調(diào)用UpdateWindow()更新窗口時(shí)發(fā)送的WM_PAINT消息及調(diào)用DestroyWindow()時(shí)發(fā)送的WM_DESTROY消息都是不進(jìn)隊(duì)消息??梢酝ㄟ^(guò)調(diào)用SendMessage()函數(shù)直接發(fā)送消息給窗口:LRESULT
WINAPI
SendMessage((HWND
hWnd,UINT
Msg,WPARAM
wParam,LPARAM
lParam);有的不進(jìn)隊(duì)消息來(lái)自進(jìn)隊(duì)消息,如退出應(yīng)用程序時(shí)會(huì)產(chǎn)生一條進(jìn)隊(duì)消息WM_CLOSE,消息循環(huán)將其派送到窗口函數(shù),處理這一消息一般是調(diào)用DestroyWindow()函數(shù)撤銷并關(guān)閉窗口,并發(fā)送不進(jìn)隊(duì)消息WM_DESTROY到窗口函數(shù)。有的用戶操作可能既產(chǎn)生進(jìn)隊(duì)消息,又產(chǎn)生不進(jìn)隊(duì)消息。消息是否進(jìn)入隊(duì)列由Windows自行操作,程序設(shè)計(jì)人員只要關(guān)心窗口函數(shù)的編寫。設(shè)備描述表繪圖信息數(shù)據(jù)結(jié)構(gòu)定義:typedef
struct
tagPAINTSTRUCT{HDC
hdc;
//設(shè)備描述表句柄BOOL
fErase;//布爾值,若背景要重畫,則為非0,否則為0RECT
rcPaint;BOOL
fRestore;BOOL
fIncUpdate;//指定窗口客戶區(qū)無(wú)效區(qū)域//保留//保留BYTE
rgbReserved[32];
//保留}PAINTSTRUCT,*
PPAINTSTRUCT,*
NPPAINTSTRUCT,
*lPPAINTSTRUCT;設(shè)備描述表WM_PAINT是重畫窗口客戶區(qū)消息,當(dāng)窗口內(nèi)容被改變、移動(dòng)或窗口被覆蓋后,需要對(duì)窗口進(jìn)行重畫,一般應(yīng)用程序都需要處理這個(gè)消息,處理這一消息需要獲取設(shè)備描述表句柄。Windows的圖形設(shè)備接口GDI是一組API函數(shù),它提供與設(shè)備無(wú)關(guān)的圖形功能,使應(yīng)用程序在不同圖形設(shè)備(如打印機(jī),顯示器、繪圖儀等)上進(jìn)行相同的操作(調(diào)用GDI函數(shù)),而無(wú)需考慮設(shè)備
的硬件差異,設(shè)備無(wú)關(guān)性是通過(guò)設(shè)備描述表實(shí)現(xiàn)的。設(shè)備描述表設(shè)備描述表(Device
Context,DC)也稱為設(shè)備上下文,是GDI內(nèi)部定義的一個(gè)有圖形對(duì)象、圖形方式及其屬性的一個(gè)數(shù)據(jù)結(jié)構(gòu),與特定設(shè)備相關(guān),描述了硬件設(shè)備的具體特征信息。如需要執(zhí)行顯示任務(wù),就構(gòu)造一個(gè)顯示設(shè)備的DC,獲得其句柄;例如,需要執(zhí)行打印任務(wù),則構(gòu)造一個(gè)打印設(shè)備的DC,獲得其句柄,GDI函數(shù)以該句柄為參數(shù)完成相應(yīng)任務(wù)。與具體設(shè)備相關(guān)的操作交給DC,將應(yīng)用程序的設(shè)備無(wú)關(guān)圖形功能調(diào)用轉(zhuǎn)換為在設(shè)備驅(qū)動(dòng)程序下執(zhí)行的設(shè)備相關(guān)操作。應(yīng)用程序不能直接訪問(wèn)設(shè)備描述表,為了進(jìn)行圖形輸出,必須先獲取設(shè)備描述表句柄,然后以設(shè)備描述表句柄為參數(shù)調(diào)用GDI函數(shù),實(shí)現(xiàn)圖形功能。2.2
Windows對(duì)象句柄句柄的概念:早期的句柄Handle是一個(gè)16位的代號(hào)。在DOS操作系統(tǒng)中,必須用帶路徑的文件名,句柄是文件的代號(hào),文件讀/寫時(shí)只用這個(gè)代號(hào)就行了,而不必用很長(zhǎng)的路徑名。文件句柄只是一個(gè)代號(hào),它不是文件的地址。地址信息放在文件句柄指向的內(nèi)存中特定的文件管理區(qū)域的一個(gè)單元中,那里存放了入口地址和有關(guān)文件的其它信息。句柄的數(shù)據(jù)類型在winnt.h中說(shuō)明如下:typedef void
*
HANDLE;所以從物理上看句柄是一個(gè)泛型(無(wú)類型)指針。但它不是指向一個(gè)Windows對(duì)象的存儲(chǔ)首地址,而是指向包含了使用該對(duì)象有關(guān)信息的一塊內(nèi)存單元。所以從邏輯上說(shuō)它是一個(gè)代號(hào),一個(gè)對(duì)象的代號(hào)。2.2
Windows對(duì)象句柄句柄的使用:句柄所指向的內(nèi)容是不能由句柄操作來(lái)改變的,只能由系統(tǒng)來(lái)改變。句柄允許做的唯一操作是檢查它是否是一個(gè)有效句柄。不等于零是一個(gè)有效句柄,等于零是無(wú)效句柄。Windows操作系統(tǒng)中所謂“句柄”(handle)是唯一標(biāo)識(shí)某個(gè)Windows對(duì)象(如程序?qū)嵗?、窗口、圖標(biāo)、光標(biāo)、畫刷、菜單等)的一個(gè)32位無(wú)符號(hào)整數(shù),句柄是Windows對(duì)象的代號(hào)。Windows程序通常通過(guò)調(diào)用win32
API函數(shù)來(lái)獲得某個(gè)
Windows對(duì)象的句柄,只有有了句柄,程序才能使用與其對(duì)應(yīng)的Windows對(duì)象。形象地講,對(duì)象是學(xué)生,句柄是學(xué)號(hào)。建立一個(gè)Windows對(duì)象,自然就建立起一個(gè)實(shí)例句柄。要使一個(gè)句柄無(wú)效只須撤消對(duì)該對(duì)象的引用,不要銷毀句柄。2.2
Windows對(duì)象句柄表2.1
常用Windows句柄類型句柄類型說(shuō)明句柄類型說(shuō)明HANDLE一般句柄類型HICON圖標(biāo)句柄類型HWND窗口句柄類型HCURSOR光標(biāo)句柄類型HINSTANCE程序?qū)嵗浔鶫BRUSH畫刷句柄類型HDC設(shè)備描述表句柄HPEN畫筆句柄類型HMENC菜單句柄類型HFONT字體句柄類型HBITMAP位圖句柄類型HFILE文件句柄類型2.3
MFC基礎(chǔ)類及其層次結(jié)構(gòu)MFC開發(fā)的思路與過(guò)程:1989年微軟成立了Application
Framework(應(yīng)用程序框架)開發(fā)小組(AFX),其目的是要建立一個(gè)圖形應(yīng)用程序的通用C++類庫(kù),這是一個(gè)單一的類庫(kù),可以用來(lái)簡(jiǎn)化所有主流微機(jī)操作系
統(tǒng)應(yīng)用程序的開發(fā),AFX希望利用面向?qū)ο蟮募夹g(shù)來(lái)建立一個(gè)易
于使用的可移植的用戶圖形界面(GUI)。一年后失敗,最主要的原因是目標(biāo)太理想化,AFX小組過(guò)分
信任面向?qū)ο蟮某绦蛟O(shè)計(jì)方法的能力,純粹抽象的類,理想而不
實(shí)用。因此,AFX小組轉(zhuǎn)向開發(fā)MFC庫(kù),目標(biāo)不再理想,但是實(shí)用。不再追求多平臺(tái),而是采取對(duì)Windows
API函數(shù)進(jìn)行便于使用的封裝。不再試圖建立純粹抽象的類,而是重點(diǎn)建立切實(shí)可行的類。不再使用C++中復(fù)雜的多重繼承。不追求對(duì)API函數(shù)進(jìn)行完美的封裝,而使用戶可以方便地調(diào)用API函數(shù)直接完成某些任務(wù),即不追求純粹的面向?qū)ο蟮某绦蛟O(shè)計(jì),而是相當(dāng)?shù)膶捜荨?.3
MFC基礎(chǔ)類及其層次結(jié)構(gòu)AFX小組的MFC開發(fā)設(shè)計(jì)的原則:使用C++進(jìn)行Windows應(yīng)用程序設(shè)計(jì)的過(guò)程應(yīng)簡(jiǎn)單和直觀。用類封裝WindowsAPI和Windows對(duì)象,并按照API的方式進(jìn)行工作。使用標(biāo)準(zhǔn)的Windows命令的約定和編碼風(fēng)格。類庫(kù)應(yīng)有足夠的可擴(kuò)展性,以便跟隨Windows的更新發(fā)展。能更方便地使用API函數(shù),采用WindowsAPI的概念,函數(shù)和編程風(fēng)格。從這里可以看出MFC和Windows很好地連接起來(lái),使Windows下的C語(yǔ)言程序設(shè)計(jì),成為面向?qū)ο蟮腗FC。這里沒(méi)有追求純粹,而是包容和實(shí)用!圖2.6
根類CObject分類派生圖2.3
MFC基礎(chǔ)類及其層次結(jié)構(gòu)MFC是采用單一繼承,從根類Cobject層層派生出絕大多數(shù)MFC中的類,其層次結(jié)構(gòu)是最典型。參見圖2.6Cobject根類CCmdTarget
命令相關(guān)類CDC設(shè)備環(huán)境類CClientDC、CWindowDC、CPaintDC、……CGdiObject
繪畫工具類CPen、CBrush、CFont、CBitmap、CPalette、……CMenu菜單CArray、CList、CMap、……
群(集合)類CDatabase、CRecordset、…
ODBC數(shù)據(jù)庫(kù)支持CDatabase、CDataRecordset、……
DAO數(shù)據(jù)庫(kù)支持CFile
文件類CException
異常類CSyncObject同步對(duì)象類CInternetSession
因特網(wǎng)會(huì)話類CInternetConnection
因特網(wǎng)連接類CMemFile、COleStreamFile、CSocketFile、……CFtpConnection、CGopherConnection、CHelpConnection圖2.7Cobject派生類層次示意圖CObject根類CCmdTarget
命令處理類CWnd
窗口類
CWinThread
線程類CWinApp
Windows應(yīng)用程序類CDocument
文檔類CDocTemplate
文檔模板類CSingleDocTemplate
單文檔模板類CMultiDocTemplate
多文檔模板類
圖2.8應(yīng)用程序結(jié)構(gòu)Cobject根類派生的最重要的類組成一個(gè)應(yīng)用程序結(jié)構(gòu)
(ApplicationArchitecture)的集合,它是由CCmdTarget為基類派生出來(lái)的,其中主要部分參見圖2.10。CFrameWnd
框架窗口類CMDIFrameWnd、CMDIChildWnd、CMiniFrameWndCControlBar
控制條類CDialogBar、CToolBar、CStatusBarCSplitterWnd
窗口分割類CWnd
窗口類CProperty
屬性頁(yè)表CPropertSheet
屬性表類CDialog
對(duì)話框類CCommonDialog
公用對(duì)話框類CFileDialog、CColorDialog、…圖2.8應(yīng)用程序結(jié)構(gòu)CView
視圖類控制類CButton、CEdit、CListBox、CScrollBar、CStatic、CComboBoxCCtrlViewCEditView、CListView、CTreeView、CRichEditViewCFormViewCRecordView圖2.8應(yīng)用程序結(jié)構(gòu)基類Cobject的最基本功能:支持序列化(serialization)。序列化指如何讓一個(gè)對(duì)象保持持久不變,即把對(duì)象成員數(shù)據(jù)內(nèi)容存入一個(gè)文件或從一個(gè)文件中讀取內(nèi)容重構(gòu)對(duì)象的過(guò)程。運(yùn)行時(shí)(Run-time)類的信息獲取。提供特定的new,delete和=操作符,完成對(duì)象的建立與刪除。2.4 MFC
編程標(biāo)準(zhǔn)Windows程序設(shè)計(jì):VC++的微軟基礎(chǔ)類庫(kù)(Microsoft
FoundationClass
Library,MFC)封裝了大部分API函數(shù),并提供了一個(gè)應(yīng)用程序框架,簡(jiǎn)化了和標(biāo)準(zhǔn)了Windows程序設(shè)計(jì),所以用MFC編寫Windows應(yīng)用程序也稱為標(biāo)準(zhǔn)Windows程序設(shè)計(jì)。標(biāo)準(zhǔn)Windows程序設(shè)計(jì)把傳統(tǒng)的Windows程序設(shè)計(jì)轉(zhuǎn)向C++面向?qū)ο蟮腤indows程序設(shè)計(jì)2.4 MFC
編程MFC簡(jiǎn)介:MFC約有200個(gè)類,提供了Windows應(yīng)用程序框架和創(chuàng)建應(yīng)用程序的組件。其中只有5個(gè)核心類對(duì)應(yīng)用程序框架有影響:
Cwinapp,Cdocument,Cview,CFrameWnd和CDocTemplate。五個(gè)之中只有Cwinapp是必不可少的類,Cwinapp的對(duì)象在應(yīng)用程序中必須有一個(gè),也只有一個(gè),并是一個(gè)全局對(duì)象,它建立了應(yīng)用程序執(zhí)行的主線程(線程的概念參見本節(jié)后的附錄)。全局對(duì)象是在MFC初始化之前,也即當(dāng)Windows操作系統(tǒng)調(diào)用WinMain()時(shí),這個(gè)對(duì)象就先已建立,即主線程已建立。形象地說(shuō),執(zhí)行程序的通路已經(jīng)開通。2.4 MFC
編程入口函數(shù):在MFC編程中,入口函數(shù)WinMain(
)被封裝在MFC的應(yīng)用程序框架內(nèi),已經(jīng)不用也不可以再定義另一個(gè)WinMain()函數(shù)。應(yīng)用程序向?qū)В篗FC編程使用MFC的應(yīng)用程序向?qū)Чぞ撸篈ppWizardAppWizard為程序員提供了一種快捷方便的工具來(lái)定制基于MFC的應(yīng)用程序框架,程序員只需以此為基礎(chǔ),添加與修改程序代碼來(lái)實(shí)現(xiàn)所需功能。MFC編程包含三種類型的應(yīng)用程序:?jiǎn)挝臋n界面(SDI)應(yīng)用程序、多文檔界面(MDI)應(yīng)用程序和基于對(duì)話框(Dialog
Based)的應(yīng)用程序,它們都可以由AppWizard引導(dǎo)建立起來(lái)。2.4 MFC
編程接口與封裝:在類中必須有一部分成員函數(shù)置為公有,專供類外程序語(yǔ)句訪問(wèn),這些函數(shù)亦稱接口函數(shù)。其余成員函數(shù)是故意對(duì)外隱蔽起來(lái)的操作,它們是最復(fù)雜最關(guān)鍵的部分,越是復(fù)雜越是關(guān)鍵就越能體現(xiàn)出使用類封裝的必要和優(yōu)越。類中故意的隱藏也為以后的升級(jí)擴(kuò)展留下了余地,只要接口不變,內(nèi)部再變,也不必修改原來(lái)的程序,就象
MFC(微軟基礎(chǔ)類)升級(jí)后,由MFC底層類所編的程序完全不必修改,自動(dòng)升級(jí)。2.4 MFC
編程使用接口的優(yōu)點(diǎn):封裝有助于編程人員在處理好簡(jiǎn)單接口后,集中精力處理高層次開發(fā)的工作,MFC能被廣泛使用也正是有此優(yōu)點(diǎn)。用戶界面等的編程是底層的十分復(fù)雜和困難的事,MFC給解決了。程序員只管自己特定的任務(wù),編程的效率和可靠性大大提高。2.4 MFC
編程——進(jìn)程和線程進(jìn)程(process):運(yùn)行中的程序稱為進(jìn)程,程序是一個(gè)靜態(tài)的概念,進(jìn)程是一個(gè)動(dòng)態(tài)的概念。進(jìn)程的組成:一段可執(zhí)行程序(代碼)程序所需的相關(guān)數(shù)據(jù)(變量、工作空間、緩沖區(qū)等)(3)程序執(zhí)行的上下文環(huán)境其中執(zhí)行上下文環(huán)境(Execution
Context)亦稱進(jìn)程狀態(tài)(Process
State),是最為重要的。它包括操作系統(tǒng)管理進(jìn)程以及處理器執(zhí)行進(jìn)程所需要的所有信息,包括處理器的各寄存器的內(nèi)容,還包括操作系統(tǒng)使用的信息,如進(jìn)程優(yōu)先級(jí)以及進(jìn)程是否在等待特定的輸入輸出事件完成。2.4 MFC
編程——進(jìn)程和線程進(jìn)程的屬性與線程(thread):資源所有權(quán):一個(gè)進(jìn)程包括一個(gè)保存進(jìn)程映像的虛擬地址空間,并隨時(shí)分配對(duì)資源的控制或所有權(quán),包括內(nèi)存、I/O通道、I/O設(shè)備和文件。調(diào)度/執(zhí)行:進(jìn)程沿著通過(guò)一個(gè)或多個(gè)程序間的執(zhí)行路徑運(yùn)行,它與其他進(jìn)程的執(zhí)行路徑相互交錯(cuò)。把兩者分開,執(zhí)行部分(它實(shí)際是被操作系統(tǒng)調(diào)度并分配的實(shí)體)稱為線程(thread)。而資源所有權(quán)的部分仍稱作進(jìn)程。一個(gè)進(jìn)程可以擁有多個(gè)線程。2.4 MFC
編程——進(jìn)程和線程線程的優(yōu)點(diǎn):與無(wú)線程的進(jìn)程相比速度大為提高,原因是:(1)在已有進(jìn)程中創(chuàng)建一個(gè)新線程速度比創(chuàng)建一個(gè)全新的進(jìn)程快得多(可達(dá)10倍)。(2)終止一個(gè)線程比終止一個(gè)進(jìn)程花費(fèi)時(shí)間少。
(3)線程間切換比進(jìn)程間切換花費(fèi)時(shí)間少。(4)同一進(jìn)程的線程共享存儲(chǔ)空間和文件,無(wú)需調(diào)用操作系統(tǒng)內(nèi)核就可進(jìn)行通信,效率大大提高。所以現(xiàn)代的操作系統(tǒng)多為多進(jìn)程多線程的操作系統(tǒng)。2.4 MFC
編程——進(jìn)程和線程進(jìn)程-線程-窗口:32位Windows管理運(yùn)行的程序的模式。當(dāng)創(chuàng)建一個(gè)進(jìn)程的同時(shí)也創(chuàng)建了第一個(gè)線程,稱為“主線程”。主線程的入口函數(shù)是WinMain(相當(dāng)于控制臺(tái)應(yīng)用程序的main函數(shù))。之后,主線程可以在進(jìn)程中再創(chuàng)建一個(gè)或多個(gè)線程,即“多線程”,多個(gè)線程共享進(jìn)程的靜態(tài)部分(資源,地址等)。進(jìn)程1進(jìn)程2線程1.1線程1.2線程1.3窗口1.1.1窗口1.1.2窗口1.3.1線程2.1窗口2.1.1圖2.9
進(jìn)程、線程與窗口2.5
MFC對(duì)象和Windows對(duì)象....其它成員MFC對(duì)象:特指封裝了Window對(duì)象的C++對(duì)象。本節(jié)討論MFC對(duì)象與Window對(duì)象的聯(lián)系,以最典型的的窗口類(CWnd)為例,討論CWnd類對(duì)象與Windows窗口對(duì)象的關(guān)系。CWnd類對(duì)象
HWND句柄類型wnd
m_hWnd
hwndwindows對(duì)象句柄W
i
ndows
操作系統(tǒng)窗口對(duì)象圖2.10
MFC窗口對(duì)象與Windows窗口對(duì)象的關(guān)系參考程序段如下:CWnd
wnd;
//定義窗口類(CWnd)的對(duì)象wndHWND
hwnd;
//定義窗口句柄hwndhwnd=CreateWindows(......);//調(diào)用API函數(shù)CreateWindows(...)建立一個(gè)Windows窗口類實(shí)例
wnd.Attach(hwd);//把Windows窗口實(shí)例的句柄鏈到CWnd對(duì)象hwnd上......Destrory
Window(hwnd);
//調(diào)用API函數(shù)撤消Windows窗口MFC的窗口對(duì)象wnd是C++類的實(shí)例,即CWnd類或其派生類的實(shí)例。hwnd是HWND句柄類型的實(shí)例,為它建立了一個(gè)Windows操作系統(tǒng)的對(duì)象。然后把這個(gè)句柄放入CWnd類對(duì)象wnd的成員數(shù)據(jù)m_hwnd中。這樣wnd就包含了一個(gè)Windows操作系統(tǒng)的窗口對(duì)象。2.5
MFC對(duì)象和Windows對(duì)象MFC對(duì)象和對(duì)應(yīng)Windows對(duì)象:MFC封裝了幾乎所有Windows的API函數(shù),所以上面的
API函數(shù),可以用CWnd的成員函數(shù)代替。成員函數(shù)Create()可以代替API函數(shù)CreateWindows()并加上另一個(gè)成員函數(shù)Attach()的全部功能,建立一個(gè)Windows操作系統(tǒng)的窗口對(duì)象,并把句柄自動(dòng)保存在MFC窗口對(duì)象wnd的m_hwnd成員數(shù)據(jù)中。通常MFC程序員直接使用CWnd的成員函數(shù)就可以了。其它的MFC對(duì)象和對(duì)應(yīng)Windows對(duì)象也有類似的關(guān)系。見表2.22.5
MFC對(duì)象和Windows對(duì)象項(xiàng)目MFC類對(duì)象句柄應(yīng)用程序CWinAppHINSTANCE
m_hInstance窗口CWndHWND
m_hWnd菜單CMenuHMENU
m_hMenu設(shè)備環(huán)境CDCHDC
m_hDC矩形區(qū)域CRgnHRGN
m_hRgn畫刷CBrushHBRUSH
m_hBrush畫筆CPenHPEN
m_hPen字體CFontHFONT
m_hFont位圖CBitmapHBITMAP
m_hBitmap調(diào)色板CPalatteHPALATTE
m_hPalatte表2.2
常用MFC類與Windows對(duì)象句柄對(duì)應(yīng)關(guān)系2.5
MFC對(duì)象和Windows對(duì)象Windows窗口句柄通常是全局量,動(dòng)
態(tài)建立的Windows窗口對(duì)象也是全局性的。所以一個(gè)進(jìn)程或線程可以取得另一個(gè)進(jìn)程或線程的窗口句柄,并給它發(fā)送消息。注意:一個(gè)線程只能使用本線程創(chuàng)建的MFC窗口對(duì)象,不能使用其它線程創(chuàng)建的MFC窗口對(duì)象。2.5
MFC對(duì)象和Windows對(duì)象小結(jié):Windows對(duì)象是Windows操作系統(tǒng)的一個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu)的實(shí)例,由一個(gè)Windows系統(tǒng)全局的窗口句柄來(lái)唯一標(biāo)志,由API函數(shù)CreatWindow()創(chuàng)建,而由DestroyWindow()撤消。在MFC編程中,Windows對(duì)象通常在MFC對(duì)象建立以后,調(diào)用Create()建立Windows對(duì)象,并鏈接在MFC對(duì)象上。建立應(yīng)用程序的主框架窗口的程序段:CFrameWnd
*pFrame=new
CFrameWnd;//動(dòng)態(tài)建立框架窗口對(duì)象pFrame->Create(NULL,”Ex2_xx”,ws_OVERLAPPENDWINDOW,rect,NULL,MAKEINTRESOURCE(IDR_MENUI),0,NULL);//建立與動(dòng)態(tài)框架窗口對(duì)象相連的Windows框架窗口2.6
MFC的消息映射消息映射的概念:MFC由CWinApp類檢索和派送消息給相應(yīng)的窗口函數(shù),但是所有的MFC窗口函數(shù)都使用同一個(gè)窗口函數(shù)。MFC把設(shè)計(jì)窗口的任務(wù)細(xì)化為設(shè)計(jì)若干消息處理函數(shù),程序員要做的是為每一個(gè)要處理的消息提供一個(gè)消息處理(HandlingMessages)函數(shù),然后系統(tǒng)通過(guò)MFC提供的一套消息映射系統(tǒng)(messagesmappingsystem)來(lái)調(diào)用相應(yīng)的消息處理函數(shù)。消息映射就是消息與消息處理函數(shù)一對(duì)一的聯(lián)系。2.6
MFC的消息映射消息映射的模型:首先定義一個(gè)Msgmap的結(jié)構(gòu):struct
Msgmap{UINT
nMessage;LONG(*pfn)(HWND,UINT,WPARAM,LPARAM);};第一個(gè)數(shù)據(jù)成員為消息標(biāo)識(shí)代碼,為無(wú)符號(hào)整型數(shù)。第二個(gè)數(shù)據(jù)成員是指向消息處理函數(shù)的長(zhǎng)指針(實(shí)際上
Windows下全部為32位長(zhǎng)指針)。這樣便建立了一個(gè)一對(duì)一的映射關(guān)系。2.6
MFC的消息映射以這樣的結(jié)構(gòu)組成一個(gè)數(shù)組,以nMessage(消息代碼)為關(guān)鍵字進(jìn)行排序,采用對(duì)半查
找,這樣可以很快找到所需要的指向消息處理
函數(shù)的指針,進(jìn)入消息處理函數(shù)進(jìn)行消息處理。2.6
MFC的消息映射消息分類:窗口消息:由MFC的窗口類(CWnd)對(duì)象來(lái)處理,即這類消息處理函數(shù)一般是CWnd類的成員函數(shù)。有缺省窗口處理函數(shù)控制通知消息:來(lái)自子窗口的通知消息。參數(shù)中包含子窗口標(biāo)識(shí)和通知碼。通知碼是子窗口定義的一些常量。有缺省處理,但一般要重載。若CWnd派生類沒(méi)有重載上述兩類消息處理函數(shù),則消息映射機(jī)制會(huì)轉(zhuǎn)由其基類處理(最終是CWnd類);若CWnd類也沒(méi)有定義對(duì)應(yīng)的消息處理函數(shù),則調(diào)用
Windows默認(rèn)的窗口函數(shù)處理。2.6
MFC的消息映射命令消息處理:來(lái)自菜單、工具欄,加速鍵的通知消息,參數(shù)中包括命令標(biāo)識(shí)(ID)號(hào),它是應(yīng)用程序自定義的一些常量,由程序員編寫消息處理函數(shù)。MFC也定義了一些缺省的標(biāo)準(zhǔn)命令消息處理函數(shù)。VC++有一個(gè)ClassWizard(類向?qū)В?,它?huì)幫助用戶建立消息映射和消息處理函數(shù)的框架,消息和函數(shù)都由MFC缺省的命名方式命名。對(duì)于命令消息,MFC應(yīng)用程序框架會(huì)通過(guò)消息映射機(jī)制,按一定的搜索順序在各個(gè)CCmdTarget類(命令處理類)的派生類中查找對(duì)應(yīng)消息處理函數(shù)。參見圖2.11(a)。在編程序時(shí)應(yīng)該讓命令消息盡可能由與其關(guān)系密切的類來(lái)處理。也就是盡管消息處理函數(shù)可以任意安放在某一個(gè)類中,但那樣可讀性差,同時(shí)執(zhí)行時(shí)也可能出問(wèn)題。圖2.11
消息映射示意圖2.6
MFC的消息映射消息映射(Message
Mapping):圖2.11(a)表的示搜索的路線是按派生關(guān)系直線查找。但是,處理消息的C++類并不呈直線發(fā)展,作為應(yīng)用程序框架的重要結(jié)構(gòu)文檔/視結(jié)構(gòu),同樣也具有消息處理能力(文檔/視結(jié)構(gòu)在2.7節(jié)中討論)。因此消息的搜索路線是迂回曲折的,如圖2.11(b)所示。描述這個(gè)復(fù)雜的搜索路線的向?qū)D就是總的消息映射表(MessageMap)。參見圖2.12。在每一個(gè)相關(guān)類的局部消息映射表中查找對(duì)應(yīng)的消息處理函數(shù),直到找到為止。這里給每一個(gè)與消息有關(guān)的派生類建立一個(gè)局部消息映射表,由系統(tǒng)沿派生關(guān)系,從當(dāng)前所在類逐步向更深層次的基類搜索消息的處理函數(shù)。這樣映射表成了一個(gè)個(gè)相對(duì)的較小的表,系統(tǒng)是按一條固定路徑去查找。在MFC中這樣復(fù)雜分層的消息映射體系是由設(shè)計(jì)好的宏來(lái)完成的。圖2.12
消息映射表安排示意圖2.6
MFC的消息映射消息映射表結(jié)構(gòu):消息入口表為一鏈表,結(jié)點(diǎn)中有一個(gè)數(shù)據(jù)結(jié)構(gòu):struct
AFX_MSGMAP{AFX_MSGMAP*
pBaseMessageMap;//指向基類消息映射入口,即入口表鏈的下一個(gè)結(jié)點(diǎn)AFX_M
GMAP_ENTRY*lp
Entries;//指向局部消息映射表的指針}//注意指針與數(shù)組和數(shù)組元素的關(guān)系入口表第二個(gè)指針指向的消息和消息處理函數(shù)結(jié)構(gòu):struct
AFX_MSGMAP_ENTRY{UINT
nMessage;
//窗口消息的消息值UINT
nCode;
//控制消息的通知碼或WM_NOTIFY碼UINT
nID;
//控制ID(0為窗口消息)UINT
nLastID;
//用于指定控制ID的范圍UINT
nSig;
//消息行為類型或指向消息號(hào)的指針
AFX_PMSG
pfn;
//消息處理函數(shù)指針}2.6
MFC的消息映射程序類型搜索路徑SDI單文檔當(dāng)前視圖→當(dāng)前文檔→文檔模板→主框架窗口→應(yīng)用程序?qū)ο驧DI多文檔當(dāng)前視圖→當(dāng)前文檔→創(chuàng)建文檔的文檔模板→活動(dòng)的子框架窗口→主框架窗口→應(yīng)用程序?qū)ο髮?duì)話框當(dāng)前對(duì)話框→對(duì)話框的父窗口→應(yīng)用程序?qū)ο竺钕⑾鄳?yīng)消息處理函數(shù)搜索全過(guò)程:由菜單、工具欄等用戶界面對(duì)象產(chǎn)生的命令消息,首先送給主
框架窗口的標(biāo)準(zhǔn)MFC窗口函數(shù),然后窗口函數(shù)把命令傳給MFC主框架窗口對(duì)象,進(jìn)行命令消息的派送,并按下表的次序進(jìn)行
消息匹配。若找不到,則先繼續(xù)搜索其基類的消息映射入口表,若仍找不到,再迂回到下一個(gè)對(duì)象進(jìn)行處理。都找不到,則由缺省的Windows消息處理函數(shù)結(jié)束該命令消息2.6
MFC的消息映射消息緩沖池:為了提高消息匹配的效率,MFC內(nèi)部有一個(gè)消息緩沖池,使用以消息值為關(guān)鍵字的散列(哈希)查找,這里可存放512條最近使用過(guò)的消息映射入口表項(xiàng)的有關(guān)信息(只需放入口表項(xiàng),即兩個(gè)指針)。僅在消息緩沖池中匹配不到才進(jìn)行前文所敘的搜索過(guò)程。2.7
MFC中的文件處理MFC中的文件系統(tǒng),是廣義的文件系統(tǒng)。先討論MFC的文檔/視結(jié)構(gòu)(Document/view),再討論序列化(Serialization)與永久保存。2.7.1
文檔/視結(jié)構(gòu)2.7.2
存檔類序列化2.7.1
文檔/視結(jié)構(gòu)文檔與視的概念:文檔(document)指的是數(shù)據(jù)組合的抽象,它通常對(duì)應(yīng)磁盤文件,也可以對(duì)應(yīng)I/O端口(包括打印機(jī)、鍵盤)或一塊內(nèi)存空間(串流)。同樣的數(shù)據(jù),我們可以用不同的方式來(lái)表示。把純的數(shù)據(jù)放在文件中或數(shù)據(jù)庫(kù)中。而把顯示方
式分離出來(lái),可以讓一份數(shù)據(jù)有多種不同的顯示
方式,程序中的數(shù)據(jù)表現(xiàn)稱為“視”(view)。這樣就可以分別考慮數(shù)據(jù)的保存——文檔,和數(shù)
據(jù)的表現(xiàn)——視。2.7.1
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度水電工程招投標(biāo)合同5篇
- 2025年度新能源車輛采購(gòu)及運(yùn)營(yíng)合同3篇
- 2024食堂食品安全保障與供貨合同
- 2025年度智能家居系統(tǒng)采購(gòu)與施工安裝合同3篇
- 年度科創(chuàng)大數(shù)據(jù)市場(chǎng)分析及競(jìng)爭(zhēng)策略分析報(bào)告
- 年度分步重復(fù)光刻機(jī)競(jìng)爭(zhēng)策略分析報(bào)告
- 2025年私人房產(chǎn)交易合同范本下載6篇
- 2024-2025學(xué)年高中英語(yǔ)Unit4Learningeffectively單元復(fù)習(xí)課教師用書教案新人教版選修10
- 二零二四年南京二手房買賣合同及物業(yè)交接細(xì)則3篇
- 二零二五年度新能源電動(dòng)車銷售及分期付款協(xié)議2篇
- GA 1551.5-2019石油石化系統(tǒng)治安反恐防范要求第5部分:運(yùn)輸企業(yè)
- 拘留所教育課件02
- 沖壓生產(chǎn)的品質(zhì)保障
- 《腎臟的結(jié)構(gòu)和功能》課件
- 2023年湖南聯(lián)通校園招聘筆試題庫(kù)及答案解析
- 上海市徐匯區(qū)、金山區(qū)、松江區(qū)2023屆高一上數(shù)學(xué)期末統(tǒng)考試題含解析
- 護(hù)士事業(yè)單位工作人員年度考核登記表
- 天津市新版就業(yè)、勞動(dòng)合同登記名冊(cè)
- 產(chǎn)科操作技術(shù)規(guī)范范本
- 人教版八年級(jí)上冊(cè)地理全冊(cè)單元測(cè)試卷(含期中期末試卷及答案)
- 各種焊工證件比較和釋義
評(píng)論
0/150
提交評(píng)論