02 windows 應(yīng)用程序架構(gòu)分析_第1頁
02 windows 應(yīng)用程序架構(gòu)分析_第2頁
02 windows 應(yīng)用程序架構(gòu)分析_第3頁
02 windows 應(yīng)用程序架構(gòu)分析_第4頁
02 windows 應(yīng)用程序架構(gòu)分析_第5頁
已閱讀5頁,還剩13頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、第二章WINDOWS應(yīng)用程序結(jié)構(gòu)創(chuàng)建窗口只需調(diào)用CreateWindow函數(shù)即可,但實際上并不這么簡單。但實際上并非真得這么簡單。雖然創(chuàng)建窗口的函數(shù)確實被命名為CreateWindow,但您將發(fā)現(xiàn)CreateWindow的第一個參數(shù)就是所謂的“窗口類名稱”,并且該窗口類連接所謂的“窗口過程”。在我們調(diào)用CreateWindow之前,有一點(diǎn)背景知識會對您大有幫助。WINDOWS應(yīng)用程序的基本結(jié)構(gòu)進(jìn)行Windows程序設(shè)計,實際上是在進(jìn)行一種面向?qū)ο蟮某绦蛟O(shè)計(OOP)。這一點(diǎn)在Windows中使用得最多的對象身上表現(xiàn)最為明顯。這種對象正是Windows之所以命名為“Windows”的原因,它具有

2、人格化的特征,這就是那個叫做“窗口”的對象。一、總體結(jié)構(gòu)桌面上最明顯的窗口就是應(yīng)用程序窗口。這些窗口含有顯示程序名稱的標(biāo)題欄、菜單,甚至可能還有工具欄和滾動條。另一類窗口是對話框,它可以有標(biāo)題欄也可以沒有標(biāo)題欄。裝飾對話框表面的還有各式各樣的按鈕、單選鈕、復(fù)選框、列表框、滾動條和文本輸入?yún)^(qū)域。其中每一個小的可視對象都是一個窗口。更確切地說,這些都稱為“子窗口”或“控件窗口”或“子窗口控件”。作為對象,用戶會在屏幕上看到這些窗口,并通過鍵盤和鼠標(biāo)直接與它們進(jìn)行交互操作。更有趣的是,程序員的觀點(diǎn)與用戶的觀點(diǎn)極其類似。窗口以“消息”的形式接收窗口的輸入,窗口也用消息與其他窗口通訊。對消息的理解將是學(xué)

3、習(xí)如何編寫Windows程序必須逾越的障礙之一。這有一個windows的消息示例:我們知道,大多數(shù)的windows程序都有大小合適的應(yīng)用程序窗口。也就是說,您能夠通過鼠標(biāo)拖動窗口的邊框來改變窗口的大小。通常,程序?qū)⑼ㄟ^改變窗口中的內(nèi)容來響應(yīng)這種大小的變化。是Windows本身而不是應(yīng)用程序正在處理與用戶重新調(diào)整窗口大小相關(guān)的全部代碼。由于應(yīng)用程序能改變其顯示的格式,所以它也“知道”窗口大小改變了。應(yīng)用程序是如何知道用戶改變了窗口的大小的呢?由于程序員習(xí)慣了常規(guī)的字符模式程序,操作系統(tǒng)沒有設(shè)置將此類消息通知給用戶的機(jī)制。問題的關(guān)鍵在于理解Windows所使用的體系結(jié)構(gòu)。當(dāng)用戶改變窗口的大小時,W

4、indows給程序發(fā)送一條消息指出新窗口的大小。然后程序就可以調(diào)整窗口中的內(nèi)容,以反映大小的變化?!癢indows給程序發(fā)送消息?!蔽覀兿Mx者不要對這句話視而不見。它到底表達(dá)了什么意思呢?我們在這里討論的是程序代碼,而不是一個電子郵件系統(tǒng)。操作系統(tǒng)怎么給程序發(fā)送消息呢?其實,所謂“Windows給程序發(fā)送消息”,是指Windows調(diào)用程序中的一個函數(shù),該函數(shù)的參數(shù)描述了這個特定消息。這種位于Windows程序中的函數(shù)被稱為“窗口過程”。無疑,讀者對程序調(diào)用操作系統(tǒng)的思路是很熟悉的。例如,程序在打開磁盤文件時就要使用有關(guān)的系統(tǒng)調(diào)用。讀者所不習(xí)慣的,可能是操作系統(tǒng)調(diào)用程序,而這正是Windows

5、面向?qū)ο篌w系結(jié)構(gòu)的基礎(chǔ)。程序創(chuàng)建的每一個窗口都有相關(guān)的窗口過程。這個窗口過程是一個函數(shù),既可以在程序中,也可以在動態(tài)鏈接庫中。Windows通過調(diào)用窗口過程來給窗口發(fā)送消息。窗口過程根據(jù)此消息進(jìn)行處理,然后將控制返回給Windows。更確切地說,窗口通常是在“窗口類”的基礎(chǔ)上創(chuàng)建的。窗口類標(biāo)識了處理窗口消息的窗口過程。使用窗口類使多個窗口能夠基于同一個窗口類,并且使用同一個窗口過程。例如,所有Windows程序中的所有按鈕均基于同一個窗口類。這個窗口類與一個位于Windows動態(tài)鏈接庫(處理所有的按鈕窗口消息)的窗口過程相聯(lián)系。在面向?qū)ο蟮某绦蛟O(shè)計中,對象是代碼與數(shù)據(jù)的組合。窗口是一種對象,其

6、代碼是窗口過程。數(shù)據(jù)是窗口過程保存的信息,以及Windows為每個窗口系統(tǒng)中那個窗口類保存的信息。窗口過程處理給窗口發(fā)送的消息。這些消息經(jīng)常是告知窗口,用戶正使用鍵盤或鼠標(biāo)進(jìn)行輸入。這正是按鈕窗口知道它被“按下”的奧妙所在。在窗口大小改變或窗口表面需要重畫時,由其他消息通知窗口。Windows程序開始執(zhí)行后,Windows為該程序創(chuàng)建一個“消息隊列”。這個消息隊列用來存放該程序可能創(chuàng)建的各種不同窗口的消息。程序中有一小段代碼,叫做“消息循環(huán)”,用來從隊列中取出消息,并且將它們發(fā)送給相應(yīng)的窗口過程。有些消息直接發(fā)送給窗口過程,不用放人消息隊列中。如果您對這段有關(guān)Windows體系結(jié)構(gòu)的過于簡略的

7、描述將信將疑,就讓我們?nèi)タ纯丛趯嶋H的程序中,窗口、窗口類、窗口過程、消息隊列、消息循環(huán)和窗口消息是如何相互配合的。這或許對您會有些幫助。創(chuàng)建一個窗口首先需要注冊一個窗口類,那需要一個窗口過程來處理窗口消息。這包括一段幾乎出現(xiàn)在每一個Window程序中的固定代碼。程序2.1所示的HELLOWIN程序就是一個包括這段固定代碼的簡單程序。二、程序2.1#includeLRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,PSTRszCmdLi

8、ne,intiCmdShow)staticTCHARszAppName=TEXT(HelloWin);HWNDhwnd;MSGmsg;WNDCLASSwndclass;wndclass.style=CS_HREDRAW|CS_VREDRAW;wndclass.lpfnWndProc=WndProc;wndclass.cbClsExtra=0;wndclass.cbWndExtra=0;wndclass.hInstance=hInstance;wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);wndclass.hCursor=LoadCursor(NUL

9、L,IDC_ARROW);wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);wndclass.lpszMenuName=NULL;wndclass.lpszClassName=szAppName;if(!RegisterClass(&wndclass)MessageBox(NULL,TEXT(ThisprogramrequiresWindowsNT!),szAppName,MB_ICONERROR);return0;hwnd=CreateWindow(szAppName,/windowclassnameTEXT(TheHell

10、oProgram),/windowcaptionWS_OVERLAPPEDWINDOW,/windowstyleCW_USEDEFAULT,/initialxpositionCW_USEDEFAULT,/initialypositionCW_USEDEFAULT,/initialxsizeCW_USEDEFAULT,/initialysizeNULL,/parentwindowhandleNULL,/windowmenuhandlehInstance,/programinstancehandleNULL);/creationparametersShowWindow(hwnd,iCmdShow)

11、;UpdateWindow(hwnd);while(GetMessage(&msg,NULL,0,0)TranslateMessage(&msg);DispatchMessage(&msg);returnmsg.wParam;LRESULTCALLBACKWndProc(HWNDhwnd,UINTmessage,WPARAMwParam,LPARAMlParam)HDChdc;PAINTSTRUCTps;RECTrect;switch(message)caseWM_CREATE:PlaySound(TEXT(hellowin.wav),NULL,SND_FILENAME|SND_ASYNC);

12、return0;caseWM_PAINT:hdc=BeginPaint(hwnd,&ps);GetClientRect(hwnd,&rect);DrawText(hdc,TEXT(Hello,Windows98!),-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);EndPaint(hwnd,&ps);return0;caseWM_DESTROY:PostQuitMessage(0);return0;returnDefWindowProc(hwnd,message,wParam,lParam);三、總體考慮實際上,每一個Windows程序代碼中都包括HE

13、LLOWIN.C程序的大部分。沒人能真正記住編寫此代碼的全部語法;通常,Windows程序員在開始一個新程序時總是復(fù)制一個現(xiàn)有的程序,然后再做相應(yīng)的修改。上面提到,HELLOWIN將在其窗口的中央顯示文本串。那不完全正確。文本實際顯示在程序客戶區(qū)的中央,它在圖中是標(biāo)題欄和邊界范圍內(nèi)的大片白色區(qū)域。這種特性對我們很重要;客戶區(qū)就是程序自由繪圖并且向用戶交付可觀輸出的窗口區(qū)域。如果您認(rèn)真思考一下,將會發(fā)現(xiàn)雖然只有80行代碼,這個窗口卻令人驚訝地具有許多功能。您可以用鼠標(biāo)按住標(biāo)題欄,在屏幕上移動窗口;可以按住邊框,改變窗口的大小。在窗口大小改變時,程序自動地將“hello,windows98!”文本

14、串重新定位在客戶區(qū)域的中央。您可以按最大化按鈕,放大HELLOWIN以充滿整個屏幕;也可以按最小化按鈕,將程序壓縮為一個圖標(biāo)。您可以從系統(tǒng)菜單(標(biāo)題欄最左端的小圖際)中執(zhí)行所有選項;也可以通過從系統(tǒng)萊單中選擇Close選項,或者通過單未標(biāo)題欄最右端的關(guān)閉按鈕,或者通過雙擊標(biāo)題欄最左端的圖標(biāo)來關(guān)閉窗口以終止程序的執(zhí)行。當(dāng)然,我們首先要從整體上看一下。HELLOWIN.C也有一個WinMain函數(shù),但它還有另外一個函數(shù),名為WndProc。這就是窗口過程。注意,在HELLOWIN,C中沒有調(diào)用WndProc的代碼。然而,在WinMain中有對WndProc的聲明,這就是函數(shù)要在程序頂部附近聲明的原

15、因。Windows函數(shù)調(diào)用HELLOWIN至少調(diào)用了18個Windows函數(shù)。下面以它們在HELLOWIN.C中出現(xiàn)的次序列出這些函數(shù)以及各自的簡明描述:LoadIcon加載圖標(biāo)供程序使用;LodCursor加載鼠標(biāo)指針供程序使用;GetStockObject獲取一個圖形對象,在這個例子中,是獲取繪制窗口背景的刷子RegisterClass為程序窗口注冊窗口類;MessageBox顯示消息框;CreateWindow根據(jù)窗口類創(chuàng)建一個窗口;ShowWindow在屏幕上顯示窗口;UpdateWindow指示窗口刷新自身;GetMessage從消息隊列中獲取消息;TranslateMessage轉(zhuǎn)

16、換某些鍵盤消息;DispatchMessage將消息發(fā)送給窗口過程;PlaySound播放一個聲音文件;BeginPaint開始窗口繪制;GetClientRect獲取窗口客戶區(qū)的尺寸;DrawText顯示文本串;EndPaint結(jié)束窗口繪制;PostQuitMessage在消息隊列中插入一條“退出”消息;DefWindowProc執(zhí)行默認(rèn)的消息處理。這些函數(shù)均在平臺SDK文檔中說明,并在不同的頭文件中聲明,其中絕大多數(shù)在WINUSERH中聲明。大寫的標(biāo)識符大家可能注意到,在IIELIDWINC中有很多大寫的標(biāo)識符,這些標(biāo)識符都是在Windows的頭文件中定義的。其中有些標(biāo)識符包含由兩個字母或

17、者三個字母組成并后跟一個下劃線的前綴:CS_HREDRAWCS_VREDRAWIDI_APPLICATIONIDC_ARROWMB_ICONERRORWS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,這些都是簡單的數(shù)值常量。前綴指示該常量所屬的類別,如下頁表所示。在編寫Windows程序時,不用去記這些數(shù)值常量。實際上,Windows中使用的每個數(shù)值常量在頭文件中均有相應(yīng)的標(biāo)識符定義。表3.1前綴類別CS類風(fēng)格選項CW創(chuàng)建窗口選項DT繪制文本選項IDI圖標(biāo)ID號IDC光標(biāo)ID號MB消息框選項S

18、ND聲音選項WM窗口消息WS窗口風(fēng)格新的數(shù)據(jù)類型HELLOWIN.C中的其他標(biāo)識符是新的數(shù)據(jù)類型,也在Window頭文件中使用typedef語句或者#define語句加以定義。這最初是為了便于將Windows程序從原來的16位系統(tǒng)上移植到本來的基于32位(或者其他)技術(shù)的操作系統(tǒng)上。這種作法并不如當(dāng)時每個人想象的那樣順利,但是這種概念基本上是正確的。有時這些新的數(shù)據(jù)類型只是為了方便起見的一個縮寫。例如,用于WinProc的第二個參數(shù)的UINT數(shù)據(jù)類型只是一個unsignedint(無符號整數(shù)),在Windows98中,這是一個32位的值。用于WinMain的第三個參數(shù)的PSTR數(shù)據(jù)類型是指向一

19、個字符串的指針,即是一個char*。其他數(shù)據(jù)類型的含義不太明顯。例如,WndProc的第三和第四個參數(shù)分別被定義WPARAM和LPARAM,這些名字的來源有點(diǎn)歷史背景:當(dāng)Window是一種16位系統(tǒng)時,WndProc的第三個參數(shù)被定義為一個WORD,這是一個歷位的無符號短整數(shù),而第四個參數(shù)被定義為一個LONG,這是一個32位有符號的長整數(shù),從而導(dǎo)致了對單詞“PARAM”加前綴“W”和“L”。當(dāng)然,在32位的Windows中,WPARAM被定義為一個UINT,而LPARAM被定義為一個LONG(就是C中的long數(shù)據(jù)類型),因此窗口過程的這兩個參數(shù)都是32位的值。這也許有點(diǎn)奇怪,因為WORD數(shù)據(jù)

20、類型在Windows98中仍然被定義為16位的無符號整數(shù),因此“PARAM”的“W”在某種意義上是不正確的名字。WndProc函數(shù)返回一個類型為LRESULT的值,該值簡單地被定義為一個LONGoWinMain函數(shù)被指定為一個WINAPI類型(在頭文件中定義的所有Windows函數(shù)都被指定這種類型),而WndProc函數(shù)被指定為一個CALLBACK類型。這兩個標(biāo)識符都被定義為_stdcall,指在Windows本身和用戶的應(yīng)用程序之間發(fā)生的函數(shù)調(diào)用的特殊調(diào)用序列。HELLOWIN還使用了Windows頭文件中定義的4種數(shù)據(jù)結(jié)構(gòu)(我們將在本章稍后加以討論)。這些數(shù)據(jù)結(jié)構(gòu)如表所示。表中前面兩個數(shù)據(jù)

21、結(jié)構(gòu)在WinMain中使用,分別定義了兩個名為msg和wndclass的結(jié)構(gòu),后面兩個數(shù)據(jù)結(jié)構(gòu)在WndProc中使用,分別定義了ps和rect結(jié)構(gòu)。結(jié)構(gòu)含義MSC消息結(jié)構(gòu)WNDCLASS窗口類結(jié)構(gòu)PAINTSTRUCT繪圖結(jié)構(gòu)RECT矩形結(jié)構(gòu)句柄簡介最后,還有3個大寫標(biāo)識符(見表),用于不同類型的“句柄”。標(biāo)識符含義HINSTANCE實例(程序自身)句柄HWND窗口句柄HDC設(shè)備描述表句柄句柄在Windows中使用非常頻繁。在本章結(jié)束之前,我們將遇到HICON(圖標(biāo)句柄)、HCURSOR鼠標(biāo)指針句柄)和HBRUSH(圖形刷句柄)。句柄是一個數(shù)(通常為32位),它代表一個對象。Windows中的

22、句柄類似傳統(tǒng)C或者M(jìn)SDOS程序設(shè)計中使用的文件句柄。程序幾乎總是通過調(diào)用Windows函數(shù)獲取句柄。程序在其他Window函數(shù)中使用這個句柄,以引用它代表的對象。句柄的實際值對程序來說是無關(guān)緊要的。但是,向您的程序提供句柄的Windows模塊知道如何使用它來引用相應(yīng)的對象。5匈牙利表示法要在Windows上開發(fā)應(yīng)用程序,就必須對Windows程序設(shè)計有所了解。在編程時,變量、函數(shù)的命名是一個極其重要的問題。好的命名方法使變量易于記憶且程序可讀性大大提高。Microsoft采用匈牙利命名法來命名WindowsAPI函數(shù)和變量。匈牙利命名法是由Microsoft的著名開發(fā)人員,Excel的主要設(shè)

23、計者查爾斯西蒙尼在他的博士論文中提出來的,由于西蒙尼的國籍是匈牙利,所以這種命名法叫匈牙利命名法。匈牙利命名法為C標(biāo)識符的命名定義了一種非常標(biāo)準(zhǔn)化的方式,這種命名方式是以下面兩條規(guī)則為基礎(chǔ)的:(1)標(biāo)識符的名字以一個或者多個小寫字母開頭,用這些字母來指定數(shù)據(jù)類型。下表列出了常用的數(shù)據(jù)類型的標(biāo)準(zhǔn)前綴。(2)在標(biāo)識符內(nèi),前綴以后就是一個或者多個第一個字母大寫的單詞,這些單詞清楚地指出了源代碼內(nèi)那個對象的用途。比如,m_szStudentName表示一個學(xué)生名字的類成員變量,數(shù)據(jù)類型是字符串型。表1.2在Windows里定義數(shù)據(jù)類型的一此標(biāo)準(zhǔn)前綴前綴數(shù)據(jù)類型c字符(char)s短整數(shù)(short)c

24、b用于定義對象(一般為一個結(jié)構(gòu))尺寸的整數(shù)n整數(shù)(integer)sz以0結(jié)尾的字符串b字節(jié)iint(整數(shù))x短整數(shù)(坐標(biāo)X)y短整數(shù)(坐標(biāo)Y)fBOOLw字(WORD,無符號短整數(shù))l長整數(shù)(long)hHANDLE(無符號int)m_類成員變量fn函數(shù)(function)dw雙字(DWORD,無符號長整數(shù))6.頭包含Windows應(yīng)用程序中使用的各種WindowsAPI函數(shù)聲明,宏定義,數(shù)據(jù)類型定義,windows.h是主要的包含文件,它包含了其他windows的頭文件,這些頭文件的某些也包含了其他頭文件。這些頭文件中最重要的和最基本的是:WINDEF.H基本類型定義;WINNT.H支持U

25、nicode的類型定義;WINBASE.H內(nèi)核函數(shù);WINUSER.H用戶接口函數(shù)WINGDU.H圖形設(shè)備接口函數(shù)。這些頭文件定義了Windows的所有數(shù)據(jù)類型、函數(shù)調(diào)用、數(shù)據(jù)結(jié)構(gòu)和常數(shù)標(biāo)識符,它是Windows文檔中的一個重要部分。使用VisualC+DeveloperStudio的Edit菜單中的FindinFiles搜索這些頭文件非常方便。還可以在DeveloperStudio中打開這些頭文件,并直接閱讀它們。注冊窗體類函數(shù)窗口總是在窗口類的基礎(chǔ)上創(chuàng)建的,窗口類用以標(biāo)識處理窗口消息的窗口過程。可以在單個窗口類的基礎(chǔ)上創(chuàng)建多個窗口。例如Windows中的所有按鈕窗口一包括下壓按鈕。復(fù)選框,

26、以及單選按鈕都是基于同一窗口類創(chuàng)建的。窗口類定義了窗口過程和基于此類創(chuàng)建的窗口的其他一些特征。在創(chuàng)建窗口時要定義一些窗口所獨(dú)有的特征。在為程序創(chuàng)建窗口之前,必須首先調(diào)用RegisterClass注冊一個窗口類。該函數(shù)只需要一個參數(shù)即一個指向類型為WNDCLASS的結(jié)構(gòu)指針。一注冊窗體類函數(shù)聲明建立窗體之前,首先要對決定窗體顯示風(fēng)格的窗體類進(jìn)行注冊。注冊窗體類函數(shù)聲明如下:ATOMRegisterClassEx(CONSTWNDCLASSEX*lpwcx);二形參lpwcx是一個指向窗體類結(jié)構(gòu)類型的指針變量。窗體類結(jié)構(gòu)類型定義如下:typedefstruct_WNDCLASSEXUINTcbSi

27、ze;/窗體類結(jié)構(gòu)類型長度;UINTstyle;/窗體風(fēng)格;WNDPROClpfnWndProc;/窗體過程指針;intcbClsExtra;/系統(tǒng)保留;intcbWndExtra;/系統(tǒng)保留;HANDLEhInstance;/實例句柄;HICONhIcon;/窗體圖標(biāo);HCURSORhCursor;/窗體光標(biāo);HBRUSHhbrBackground;/窗體客戶區(qū)背景色;LPCTSTRlpszMenuName;/窗體菜單指針;LPCTSTRlpszClassName;/窗體類名稱;HICONhIconSm;/窗體小圖標(biāo)。WNDCLASSEX;1窗體風(fēng)格選項:窗體風(fēng)格各個選項可以用OR(|)運(yùn)算

28、符聯(lián)合表示。CS_BYTEALIGNCLIENTCS_BYTEALIGNWINDOWCS_CLASSDCCS_DBLCLKSCS_GLOBALCLASSCS_HREDRAWCS_NOCLOSECS_OWNDCCS_PARENTDCCS_SAVEBITSCS_VREDRAW2窗體客戶區(qū)背景色選項:COLOR_ACTIVEBORDERCOLOR_ACTIVECAPTIONCOLOR_APPWORKSPACECOLOR_BACKGROUNDCOLOR_BTNFACECOLOR_BTNSHADOWCOLOR_BTNTEXTCOLOR_CAPTIONTEXTCOLOR_GRAYTEXTCOLOR_HIG

29、HLIGHTCOLOR_HIGHLIGHTTEXTCOLOR_INACTIVEBORDERCOLOR_INACTIVECAPTIONCOLOR_MENUCOLOR_MENUTEXTCOLOR_SCROLLBARCOLOR_WINDOWCOLOR_WINDOWFRAMECOLOR_WINDOWTEXT三返回值如果成功返回非0值,否則返回0。建立窗體函數(shù)窗口類定義了窗口的一般特征,因此可以使用同一窗口類創(chuàng)建許多不同的窗口。實際調(diào)用CreateWindow創(chuàng)建窗口時,可能指定有關(guān)窗口的更詳細(xì)的信息。新的Window程序員有時會混淆窗口類和窗口之間的區(qū)別,以及為什么一個窗口的所有特征不能被一步到位地指

30、定。實際上,以這種方式分開這些風(fēng)格信息是非常方便的。例如,所有的按鈕窗口都可以基于同樣的窗口類來創(chuàng)建。與這個窗口類相關(guān)的窗口過程位于Windows內(nèi)部。由窗口類來負(fù)責(zé)處理按鈕的鍵盤和鼠標(biāo)輸入,并定義按鈕在屏幕上的外觀形象。從這一點(diǎn)看來,所有的按鈕都是以同樣的方式工作的。但是并非所有的按鈕都是一樣的。它們可以有不同的大小,不同的屏幕位置,以及不同的正文串。后面的這樣一些特征是窗口定義的一部分,而不是窗口類定義的。建立窗體函數(shù)用于建立平鋪式,彈出式或子窗體。一、函數(shù)聲明HWNDCreateWindowEx(DWORDdwExStyle,LPCTSTRlpClassName,LPCTSTRlpWin

31、dowName,DWORDdwStyle,intx,inty,intnWidth,intnHeight,HWNDhWndParent,HMENUhMenu,HINSTANCEhInstance,LPVOIDlpParam);形參:dwExStyle:擴(kuò)展窗體風(fēng)格;擴(kuò)展窗體風(fēng)格各個選項可以用OR(|)運(yùn)算符聯(lián)合表示,各個選項如下:WS_EX_ACCEPTFILESWS_EX_APPWINDOWWS_EX_CLIENTEDGEWS_EX_CONTEXTHELPWS_EX_CONTEXTHELPWS_EX_CONTROLPARENTWS_EX_DLGMODALFRAMEWS_EX_LEFTWS_EX

32、_LEFTSCROLLBARWS_EX_LTRREADINGWS_EX_MDICHILDWS_EX_NOPARENTNOTIFYWS_EX_OVERLAPPEDWINDOWWS_EX_PALETTEWINDOWWS_EX_RIGHTWS_EX_RIGHTSCROLLBARWS_EX_RTLREADINGWS_EX_STATICEDGEWS_EX_TOOLWINDOWWS_EX_TOPMOSTWS_EX_TRANSPARENTWS_EX_WINDOWEDGElpClassName:窗體類名稱;lpWindowName:窗體名稱;如果窗體名稱用下列選項之一,則建立的是控件窗體。BUTTONCOMB

33、OBOXEDITLISTBOXMDICLIENTRichEditRICHEDIT_CLASSSCROLLBARSTATICdwStyle:窗體風(fēng)格;窗體風(fēng)格各個選項可以用OR(|)運(yùn)算符聯(lián)合表示各個選項如下:WS_BORDERWS_CAPTIONWS_CHILDWS_CHILDWINDOWWS_CLIPCHILDRENWS_CLIPSIBLINGSWS_DISABLEDWS_DLGFRAMEWS_GROUPWS_HSCROLLWS_ICONICWS_MAXIMIZEWS_MAXIMIZEBOXWS_MINIMIZEWS_MINIMIZEBOXWS_OVERLAPPEDWS_OVERLAPPED

34、WINDOWWS_POPUPWS_POPUPWINDOWWS_SIZEBOXWS_SYSMENUWS_TABSTOPWS_THICKFRAMEWS_TILEDWS_TILEDWINDOWWS_VISIBLEWS_VSCROLLx:窗體左上角X坐標(biāo);y:窗體左上角Y坐標(biāo);nWidth:窗體寬度;nHeight:窗體高度;hWndParent:父窗體句柄;hMenu:菜單句柄;hlnstance:實例句柄;lpParam:系統(tǒng)保留。返回值如果成功返回新窗體句柄,否則返回NULL。二、實例分析傳遞給RegisterClass函數(shù)的信息在一個數(shù)據(jù)結(jié)構(gòu)中說明,而傳遞給CreateWindow函數(shù)的信息作

35、為函數(shù)的單獨(dú)參數(shù)來說明。下面是HELLOWIN.C中的CreateWindow調(diào)用,每一個域都做了完整的注釋:此程序創(chuàng)建的窗口是一個普通的重疊式窗口。它含有一個標(biāo)題欄,標(biāo)題欄左邊有一個系統(tǒng)菜單框,標(biāo)題欄右邊有縮小、放大和關(guān)閉圖標(biāo),四周還有一個表示窗口大小的邊框。這是標(biāo)準(zhǔn)風(fēng)格的窗口,名為WSOVERLAPPEDWINDOW,該參數(shù)按“窗口風(fēng)格”出現(xiàn)在CreateWindow中。當(dāng)創(chuàng)建一個“最高級”窗口,如應(yīng)用程序窗口時,注釋為“父窗口句柄”的參數(shù)設(shè)置為NULL。通常,如果有窗口之間存在父子關(guān)系,則子窗口總是出現(xiàn)在父窗口的上面。應(yīng)用程序窗口出現(xiàn)在桌面窗口的上面,但不必為調(diào)用CreateWindow

36、而找出桌面窗口的句柄。因為窗口沒有菜單,所以“窗口菜單句柄”也設(shè)置為NULL?!俺绦?qū)嵗浔痹O(shè)置為實例句柄,它是作為WinMain的參數(shù)傳遞給這個程序的。最后,“創(chuàng)建參數(shù)”指針設(shè)置為NULL,可以用這個指針訪問以后想要引用的程序中的數(shù)據(jù)。CreateWindow調(diào)用返回被創(chuàng)建的窗口的句柄,該句柄存放在變量hwnd中,后者被定義為HWND類型(“窗口句柄類型”)。Windows中的每個窗口都有一個句柄,程序用句柄來引用窗口。許多Windows函數(shù)需要使用hwnd作為參數(shù),這樣,Window才能知道函數(shù)是針對哪個窗口的。如果一個程序創(chuàng)建了許多窗口,則每個窗口均有一個句柄。窗口句柄是Windows

37、程序處理的最重要的句柄之一。顯示和更新窗體函數(shù)在CreateWindow調(diào)用返回之后,Window內(nèi)部已經(jīng)創(chuàng)建了這個窗口。這就是說,Windows已經(jīng)分配了一塊內(nèi)存,用來保存關(guān)于在CleateWindow調(diào)用中指定窗口的全部信息,再加上Windows在隨后所能找到的所有其他信息。然而,窗口并未在視頻顯示器上出現(xiàn),這就需要再來兩個調(diào)用,它們是:ShowWindow和UpdateWindow。一、顯示窗體客戶區(qū)函數(shù)聲明BOOLShowWindow(HWNDhWnd,intnCmdShow);形參:hWnd:窗體句柄;(是剛剛用CreateWindow創(chuàng)建的窗口句柄)nCmdShow:窗體顯示方式,

38、與WinMain函數(shù)定義的窗體顯示方式相同。它確定最初如何在屏幕上顯示窗口,是常規(guī)、最小化還是最大化。返回值:如果顯示窗體是可見的,返回TRUE,否則返回FALSE。二、更新窗體客戶區(qū)函數(shù)聲明BOOLUpdateWindow(HWNDhWnd);形參:hWnd:窗體句柄;Handletothewindowtobeupdated.返回值:如果成功返回TRUE,否則返回FALSE。ShowWindow函數(shù)在顯示器上顯示窗口。如果ShowWindow的第二個參數(shù)是SW_SHOWNORMAL,則窗口的客戶區(qū)域就被窗口類中定義的背景刷子所覆蓋。函數(shù)調(diào)用UpdateWindow(hwnd);導(dǎo)致客戶區(qū)域被

39、繪制。它通過給窗口過程(即HELLOWINC中的WndProc函數(shù))發(fā)送一個WM_PAINT消息來做到這一點(diǎn)。后面,我們將說明WndProc如何處理這個消息。建立消息循環(huán)調(diào)用UpdateWindow之后,窗口就出現(xiàn)在視頻顯示器上。程序現(xiàn)在必須準(zhǔn)備讀入用戶用鍵盤和鼠標(biāo)輸入的數(shù)據(jù)。Windows為當(dāng)前運(yùn)行的每個Windows程序維護(hù)一個“消息隊列”。在發(fā)生輸入事件之后,Windows將事件轉(zhuǎn)換為一個“消息”,并將消息放入程序的消息隊列中。程序通過執(zhí)行一塊被稱為“消息循環(huán)”的代碼從消息隊列中取出消息:while(GetMessage(&msg,NULL,0,0)TranslateMessage(&m

40、sg);DispatchMessage(&msg);msg變量是類型為MSG的結(jié)構(gòu),類型MSG在WINUSER.H中定義如下:消息結(jié)構(gòu)類型用于描述一個線程的消息隊列中的消息。其定義如下:typedefstructtagMSGHWNDhwnd;/接受消息窗體過程的窗體句柄;UINTmessage;/消息類型;WPARAMwParam;/消息附加值;LPARAMlParam;/消息附加值;DWORDtime;/消息傳送時間;POINTpt;/消息傳送時光標(biāo)在屏幕上的位置;MSG;POINT結(jié)構(gòu)類型也是一個結(jié)構(gòu),它在WINDEF.H中定義如下:typedefstructtagPOINTLONGx;/

41、光標(biāo)在屏幕上的X坐標(biāo);LONGy;/光標(biāo)在屏幕上的Y坐標(biāo);POINT;消息循環(huán)以CetMessage調(diào)用開始,它從消息隊列中取出一個消息獲取消息函數(shù):GetMessage(&msg,NULL,0,0)這一調(diào)用傳給Windows一個指向名為msg的MSG結(jié)構(gòu)的指針。第二、第三和第四個參數(shù)設(shè)置為NULL或者0,表示程序接收它自己創(chuàng)建的所有窗口的所有消息。獲取消息函數(shù)用于從一個線程的消息隊列中獲取消息,其聲明如下:BOOLGetMessage(LPMSGlpMsg,HWNDhWnd,UINTwMsgFilterMin,UINTwMsgFilterMax);形參lpMsg:消息結(jié)構(gòu)類型變量指針;hWn

42、d:接受消息窗體過程的窗體句柄;wMsgFilterMin:消息值下限過濾器;wMsgFilterMax:消息值上限過濾器。返回值如果獲取的消息是WM_QUIT消息,則返回非0值,否則返回0。只要從消息隊列中取出消息的message域不為WM_QUIT。GetMessage就返回一個非0值。WM_QUIT消息將導(dǎo)致GetMessage返回0。TranslateMessage(&msg)將msg結(jié)構(gòu)傳給Windows,語句DispatchMessage(&msg);又將msg結(jié)構(gòu)回傳給Windowso然后,Wndows將該消息發(fā)送給適當(dāng)?shù)拇翱谶^程,讓它進(jìn)行處理。這也就是說,Windows將調(diào)用窗

43、口過程。在HELLOWIN中,這個窗口過程就是WndProc函數(shù)。處理完消息之后,WndProc返回到Windows。此時,Windows還停留在DispatchMessage調(diào)用中。在結(jié)束DispatchMessage調(diào)用的處理之后,Windows回到HELLLWIN,并且接著從下一個GetMessage調(diào)用開始消息循環(huán)。翻譯消息函數(shù):翻譯消息函數(shù)聲明翻譯消息函數(shù)用于把虛鍵值翻譯成字符的ASCII值,其聲明如下:BOOLTranslateMessage(CONSTMSG*lpMsg);形參lpMsg:消息結(jié)構(gòu)類型變量指針。返回值如果翻譯的消息來源于某個線程的消息隊列,則返回TRUE,否則返回

44、FALSE。?發(fā)送消息函數(shù)發(fā)送消息函數(shù)聲明發(fā)送消息函數(shù)用于把消息發(fā)送窗體過程,其聲明如下:LONGDispatchMessage(CONSTMSG*lpmsg);形參lpMsg:消息結(jié)構(gòu)類型變量指針。返回值接受消息窗體過程的函數(shù)指針。窗體過程以上我們所討論的實在只是準(zhǔn)備性的工作:注冊窗口類,創(chuàng)建窗口,然后在屏幕上顯示窗口,程序進(jìn)入消息循環(huán),從消息隊列中取出一條消息。實際的動作發(fā)生在窗口過程中。窗口過程確定了在窗口的客戶區(qū)域中顯示些什么,以及窗口怎樣響應(yīng)用戶輸入。在HELLOWIN中,窗口過程是命名為WndProc的函數(shù)。窗口過程可任意命名(只要不和其他名字發(fā)生沖突)。一個Windows程序可以

45、包含多個窗口過程。一個窗口過程總是與調(diào)用RegisterClass注冊的特定窗口類相關(guān)聯(lián)。CreateWindow函數(shù)根據(jù)特定窗口類創(chuàng)建一個窗口。但基于一個窗口類,可以創(chuàng)建多個窗口。一、窗口過程定義為:LRESULTCALLBACKWndProc(HWNDhwnd,UINTmessage,WPARAMwParam,LPARAMlParam)注意,窗口過程的4個參數(shù)與MSG結(jié)構(gòu)的前4個域是相同的。第一個參數(shù)hwnd是接收消息的窗口的句柄,它與CreateWindow函數(shù)的返回值相同。對于與HELLOWIN相似的程序(只創(chuàng)建一個窗口),這個參數(shù)是程序所知道的唯一窗口句柄。如果程序是基于同一窗口類(

46、同時也是同一窗口過程)創(chuàng)建多個窗口,則hwnd標(biāo)識接收該消息的特定窗口。第二個參數(shù)與MSG結(jié)構(gòu)中的message域相同,它是標(biāo)識該消息的數(shù)字。最后兩個參數(shù)都是32位的消息參數(shù),它提供關(guān)于消息的更多信息。這些參數(shù)包含每個消息類型的詳細(xì)信息。有時消息參數(shù)是兩個存放在一起的16位值,而有時消息參數(shù)又是一個指向正文串或數(shù)據(jù)結(jié)構(gòu)的指針。程序通常不直接調(diào)用窗口過程。窗口過程通常由Window本身調(diào)用。通過調(diào)用endMessage函數(shù),程序能夠直接調(diào)用它自己的窗口過程。我們將在后面的章節(jié)討論SendMessage函數(shù)。二、處理消息窗口過程接收的每個消息均是用一個數(shù)值來標(biāo)識的,也就是傳給窗口過程的messag

47、e參數(shù)。Windows頭文件WINUSER.H為每個消息參數(shù)定義以“WM”(窗口消息)為前綴的標(biāo)識符。一般來說,Windows程序員使用switch和case結(jié)構(gòu)來確定窗口過程接收的是什么消息,以及如何適當(dāng)?shù)靥幚硭?。窗口過程在處理消息時,必須返回幾窗口過程不予處理的所有消息應(yīng)該被傳給名為DefWindoProc的Windows函數(shù)。從DefwindowProc返回的值必須由窗口過程返回。在HELLOWIN中,WndProc只選擇處理三種消息:WM_CREATE、WM_PAINT和WM_DESTROY。調(diào)用DefWindowProc來為窗口過程不予處理的所有消息提供默認(rèn)處理,這是很重要的。除非能

48、按常規(guī)運(yùn)行,比如能在不工作時終止程序。三、播放聲音文件窗口過程接收的第一個消息也是WndProc選擇處理的第一個消息一WM_CREATE。當(dāng)Windows在WinMain中處理CreateWindow函數(shù)時,WndProc接收這個消息。即當(dāng)HELLOWIN調(diào)用CreateWindow時,WndProc將做一些它必須做的工作。在這些工作中,Windows調(diào)用WndProc,將第一個參數(shù)設(shè)置為窗口句柄,第二個參數(shù)設(shè)置為WM_CREATEOWindows然后可以從CreateWindow調(diào)用中返回到HELLOWIN,繼續(xù)在WinMain中進(jìn)行下一步的處理。通常,窗口過程在WM_CREATE處理期間進(jìn)

49、行一次窗口初始化。HELLOWND對這條消息的處理中播放一個名為HELLOWND.WAV的聲音文件。它使用簡單的PlaySound函數(shù)來做到這一點(diǎn)。PlaySound的第一個參數(shù)是聲音文件的名稱。第二個參數(shù)只有當(dāng)聲音文件是一種資源時才被使用。第三個參數(shù)指定一些選項。在這個例子中,指定第一個參數(shù)是一個文件名,并且異步地播放聲音,即PlaySound函數(shù)調(diào)用在聲音文件開始播放時立即返回,而不會等待它的完成。在這種方法下,程序能夠繼續(xù)初始化。WndProc通過從窗口過程中返回0結(jié)束整個WM_CREATE的處理。四、WM_PRINT消息WndProc處理的第二個消息為WM_PAINT。這個消息在Win

50、dows程序設(shè)計中是很重要的。當(dāng)窗口客戶區(qū)域的一部分或者全部變?yōu)椤盁o效”,以致于必須“刷新”時,將由這個消息通知程序??蛻魠^(qū)域怎么會變得無效呢?在最初創(chuàng)建窗口的時候,整個客戶區(qū)域都是無效的,因為程序還沒有在窗口上畫什么東西。第一個WM_PAINT消息(通常發(fā)生在WinMain中調(diào)用UpDateWindow時)指示窗口過程在客戶區(qū)域上畫一些東西。在用戶改變HELLOWIN窗口的大小后,客戶區(qū)域重新變得無效。讀者應(yīng)該還記得,HELLOWIN中wndclass結(jié)構(gòu)的style域設(shè)置為標(biāo)志CS_HREDRAW和CS_VREDRAW,這一風(fēng)格指示W(wǎng)indows,在窗口大小改變后,使整個窗口無效。然后,窗

51、口過程將收到一個WM_PAINT消息。當(dāng)用戶將HELLOWIN最小化,然后再次將窗口恢復(fù)為以前的大小時Windows將不會保存客戶區(qū)域的內(nèi)容。在圖形環(huán)境下,這涉及的數(shù)據(jù)量很大。因此,Windows令窗口無效,窗口過程接收一個WM_PAINT消息,并自動恢復(fù)其窗口的內(nèi)容。在移動窗口以使其相互重疊時,Windows不保存一個窗口中被另一個窗口所遮蓋的內(nèi)容。在這一部分不再被遮蓋之后,它就被標(biāo)志為無效。窗口過程接收到一個WM_PAINT消息,以刷新窗口的內(nèi)容。對WM_PAINT的處理幾乎總是從一個BeginPaint調(diào)用開始:hdc二BeginPaint(hwnd,&ps);而以一個EndPaint調(diào)

52、用結(jié)束:EndPaint(hwnd,&ps);在這兩個調(diào)用中,第一個參數(shù)都是程序的窗口句柄,第二個參數(shù)是指向類型為PAINTSTRUCT的結(jié)構(gòu)指針。PAINTSTRUCT結(jié)構(gòu)中包含一些窗口過程,可以用來刷新客戶區(qū)域的內(nèi)容。我們將在下面的章節(jié)中討論該結(jié)構(gòu)的各個域?,F(xiàn)在我們只在BeginPaint和EndPaint函數(shù)中用到它。在BeginPaint調(diào)用中,如果客戶區(qū)域的背景還未被刪除,則由Windows來刪除。它使用注冊窗口類的WNDCIASS結(jié)構(gòu)的hbrBackGround域中指定的刷子來刪除背景。在HELLOWIN中,這是一個白色備用刷子。這意味著,Windows將通過把窗口背景設(shè)置為白色來

53、刪除窗口背景。BeginPaint調(diào)用使整個客戶區(qū)域有效,并返回一個“設(shè)備描述表句柄”。設(shè)備描述表是指物理輸出設(shè)備(如視頻顯示器)及其設(shè)備驅(qū)動程序。在窗口的客戶區(qū)域顯示文本和圖形需要設(shè)備描述表句柄。但是不能用從BeginPaint返回的設(shè)備描述表句柄在客戶區(qū)域之外繪圖,讀者可以試一試。EndPaint釋放設(shè)備描述表句柄,使之不再有效。如果窗口過程不處理WM_PAINT消息(這是非常少見的情況),它們必須被傳送給DefWindowProc。DefWindowProc只是依次調(diào)用BeginPaint和EndPaint,以使客戶區(qū)域有效。調(diào)用完BeginPaint之后,WndProc接著調(diào)用GetC

54、lientRect:GetClientRect(hwnd,rect);第一個參數(shù)是程序窗口的句柄。第二個參數(shù)是一個指針,指向一個RECF類型的rectangle結(jié)構(gòu)。該結(jié)構(gòu)有4個LONG域,分別為left、top、right和bottom。GetClientRect將這個域設(shè)置為窗口客戶區(qū)域的尺寸。left和top域通常設(shè)置為0,right和bottom域設(shè)置為客戶區(qū)域的寬度和高度(像素點(diǎn)數(shù))。WndProc除了將該RECT結(jié)構(gòu)指針作為DrawText的第4個參數(shù)傳遞外,不再對它做其他處理:DrawText(hdc,TEXT(“Hello,Windows98!”),l,rect,DT_SING

55、LELINE|DT_CENTER|DT_VCENTRE);DrawText可以輸出文本(正如其名字所表明的一樣)。由于該函數(shù)要輸出文本,第一個參數(shù)是從BeginPaint返回的設(shè)備描述表句柄,第二個參數(shù)是要輸出的文本,第三個參數(shù)是-l,指示文本串是以字節(jié)0終結(jié)的。DrawText最后一個參數(shù)是一系列位標(biāo)志,它們均在WINUSER.H中定義。標(biāo)志指示了文本必須顯示在一行上,水平方向和垂直方向都位于第4個參數(shù)指定的矩形中央。因此,這個函數(shù)調(diào)用將導(dǎo)致串“HellO,Windows98!”顯示在客戶區(qū)域的中央。一旦客戶區(qū)域變得無效(正如在改變大小時所發(fā)生的情況一樣),WndProc就接收一個新的WM_PAINT消息。WndProc通過調(diào)用GetClientRect獲取變化后的窗口大小,并在新窗口的中央顯示文本。五、WM_DESTROY消息WM_DESTROY消息是另一個重要消息。這一個消息指示W(wǎng)indows正在根據(jù)用戶輸入的命令來清除窗口。該消息是用戶單擊Close按鈕或者在程序的系統(tǒng)菜單上選擇Close時發(fā)生的。(在本章的后面,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論