電子課件實(shí)踐教程第二章_第1頁(yè)
電子課件實(shí)踐教程第二章_第2頁(yè)
電子課件實(shí)踐教程第二章_第3頁(yè)
電子課件實(shí)踐教程第二章_第4頁(yè)
電子課件實(shí)踐教程第二章_第5頁(yè)
已閱讀5頁(yè),還剩77頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論