創(chuàng)建一個(gè)窗口的過程
1:創(chuàng)建一個(gè)窗口首先要注冊(cè)一個(gè)窗口類,用一個(gè)窗口過程處理窗口消息;
2:windows的程序調(diào)用
LoadIcon:加載圖標(biāo)
LoadCursor:加載鼠標(biāo)指針
GetStockObject:獲取圖形對(duì)象
RigisterClass:為程序窗口注冊(cè)窗口類
MessageBox:顯示消息框
CreateWindow:根據(jù)窗口類創(chuàng)建一個(gè)窗口
ShowWindow:在屏幕上顯示窗口
UpdateWindow:指示窗口刷新自身
GetMessage:從消息隊(duì)列中獲取消息
TranslateMessage:轉(zhuǎn)換某些鍵盤信息
DispatchMessage:將消息發(fā)送給窗口過程
PlaySound:播放一個(gè)聲音文件
BeginPaint:開始窗口繪制
GetClientRect:獲取窗口客戶區(qū)的尺寸
DrawText:顯示文本串
EndPaint:結(jié)束窗口繪制;
PostQuitMessage:消息隊(duì)列中插入一條 退出信息
DefWindowProc:執(zhí)行默認(rèn)的消息處理
3:大寫標(biāo)識(shí)符的前綴表示的含義
CS:類風(fēng)格選項(xiàng)
CW:創(chuàng)建窗口選項(xiàng)
DT:繪制文本選項(xiàng)
IDI:圖標(biāo)ID號(hào)
IDC:光標(biāo)ID號(hào)
MB:消息框選項(xiàng)
SND聲音選項(xiàng)
WM:窗口消息
WS:窗口風(fēng)格
4:新的數(shù)據(jù)類型
在源程序中的其他標(biāo)識(shí)符是新的數(shù)據(jù)類型,在Windows頭文件中使用typedef語句加以定義;
UINT:一個(gè)unsigned int(無符號(hào)整數(shù))32位
PSTR:指向一個(gè)字符串的指針(char*)
WPARAM:定義成一個(gè)UINT(32位無符號(hào)整數(shù))
LPARAM:定義成一個(gè)LONG(32位有符號(hào)整數(shù))
LRESULT:是WndProc函數(shù)的返回值,定義成一個(gè)LONG
WINAPI:WinMain函數(shù)的類型,頭文件中的所有Windows函數(shù)都被指定成這個(gè)類型
CLASSBACK:WndProc指定為該類型(WINAPI和CLASSBACK均為__stdcall類型,指在Windows本身和用戶的應(yīng)用程序之間發(fā)生的函數(shù)調(diào)用的特殊調(diào)用序列)
5:Windows頭文件定義的四種數(shù)據(jù)結(jié)構(gòu)
MSG:消息結(jié)構(gòu)
WNDCLASS:窗口類結(jié)構(gòu)
PAINTSTRUCT:繪圖結(jié)構(gòu)
RECT:矩形結(jié)構(gòu)
6:三個(gè)句柄
句柄是一個(gè)32位的數(shù),代表一個(gè)對(duì)象;程序通過調(diào)用Windows函數(shù)獲取句柄,在Windows函數(shù)中引用句柄,以引用它所代表的對(duì)象,句柄的實(shí)際值對(duì)程序無關(guān)緊要,
但Windows模塊知道如何使用它來引用相應(yīng)的對(duì)象。
HINSTANCE:實(shí)例句柄(程序自身)
HWND:窗口句柄
HDCP:設(shè)備描述句柄
7:匈牙利表示法(變量名既能描述變量的作用,又描述了其數(shù)據(jù)類型,這就能比較容易的避免產(chǎn)生數(shù)據(jù)類型不搭配的錯(cuò)誤)
在Windows程序中,使用匈牙利表示法給變量命名,變量名以一個(gè)或者多個(gè)小寫字母開始,這些字母表示變量的數(shù)據(jù)類型;
sz 表示以零結(jié)尾的字符串
hInstance,hPrevInstance中的h前綴表示句柄
iCmdShow中的i前綴表示 整數(shù)
wPraram 更適合叫uiPraram(無符號(hào)整數(shù))
c:char活WHAR或TCHAR的前綴
by:BYTE(無符號(hào)字符)的前綴
n:short的前綴
i:int的前綴
x,y:int分別用作x坐標(biāo)或y坐標(biāo)
cx,cy:int分別用作x長(zhǎng)度,和y的長(zhǎng)度;c代表count;
b,f:b代表bool;f代表flag;
w:WORD(無符號(hào)short);
l:LONG(長(zhǎng)整數(shù))
dw:DWORD(無符號(hào)長(zhǎng)整數(shù))
fn:function(函數(shù))
s:string(串)
sz:以零字節(jié)結(jié)尾的串
lpfn:只想函數(shù)的長(zhǎng)指針
h:句柄
p:指針
cb:字節(jié)數(shù)
hbr:一個(gè)刷子的句柄
8:結(jié)構(gòu)的命名
可以用結(jié)構(gòu)名的小寫,或結(jié)構(gòu)名縮寫的小寫給結(jié)構(gòu)名命名;
9:注冊(cè)窗口類
窗口總是在窗口類的基礎(chǔ)上創(chuàng)建的,窗口類用以標(biāo)示處理窗口信息的消息過程。
(1)首先注冊(cè)一個(gè)窗口類WNDCLASS wndclass
在程序創(chuàng)建窗口之前,必須首先調(diào)用RegisterCLASS注冊(cè)一個(gè)窗口類;
該函數(shù)只要一個(gè)參數(shù),即一個(gè)指向類型為WNDCLASS的結(jié)構(gòu)指針。
補(bǔ)充:WNDCLASS結(jié)構(gòu)簡(jiǎn)介
此結(jié)構(gòu)包括兩個(gè)指向字符串的域,因此結(jié)構(gòu)在WINUSER.H頭文件中定義了兩種不用的方式。(ASCII版本和Unicode版本)
ASCII版本的WNDCLASSA
typedef struct tagWNDCLASSA
{
UINT
style;
類風(fēng)格
WNDPROC
lpfnWndPROC;
基于這個(gè)類創(chuàng)建的窗口所使用的窗口過程的地址;
int
cbClsExtra;
int
cbWndExtra;
類結(jié)構(gòu)和窗口結(jié)構(gòu)中預(yù)留一些額外空間,程序可以根據(jù)需要使用預(yù)留的空間
HINSTANCE
hinstance;
程序的實(shí)例句柄,是WinMain的參數(shù)之一
HICON
hicon;
為所有基于這個(gè)窗口類建立的窗口設(shè)置一個(gè)圖標(biāo),圖標(biāo)是一個(gè)小的位圖圖像
HCURSOR
hCursor;
HBRUSH
hbrBackground;
LPCSTR
lpszMinuName;
LPCSTR
lpszClassName;
窗口類的文本名
}
WNDCLASS,*PWNDCLASSA,NEAR *NPWNDLASSA,FAR *LPWINDCLASSA;
補(bǔ)充:WINUSER.H定義了WNDCLASS和指向WNDCLASS的結(jié)構(gòu)體,及一些向后兼容的代碼
(2)初始化wndclass中的各個(gè)域
wnd.style = CS_HREDRAW|CS_VREDRAW;
wnd.lpfnWndProc = WndProc;
將窗口類的窗口過程設(shè)置為WndProc,及HEELLOWIN.H中的第二個(gè)函數(shù),用于處理基于這個(gè)窗口類創(chuàng)建的所有窗口的全部消息。WndProc是函數(shù)的指針;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
設(shè)置程序的實(shí)例句柄
wndclass.hIcon = LOADIcon(NULL,IDI_APPLICATION)
此函數(shù)返回圖標(biāo)的句柄,用于設(shè)置hIcon的值,第一個(gè)參數(shù)設(shè)置為Null,來獲取預(yù)先定義的圖標(biāo)句柄;第二個(gè)參數(shù)設(shè)置為IDI_APPLICATION(為圖標(biāo)的標(biāo)識(shí)符,在WINUSER.H中定義)
wndclass.hCusor = LoadCursor(null, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHIT_BRUSH);
指定這個(gè)類創(chuàng)建的窗口背景的顏色;
補(bǔ)充:刷子,刷子是圖形學(xué)上的一個(gè)術(shù)語,指用來填充一個(gè)域的著色像素模式。Windows有幾個(gè)標(biāo)準(zhǔn)刷子;GetStockObject調(diào)用返回一個(gè)白色刷子句柄
wndclass.lpszMenuName = NULL;指定窗口類菜單
wndclass.lpszClassName =
szAppName;給出類名,該串由ASCII字符組成還是有Unicode字符組成取決于是否定義了UNICODE標(biāo)識(shí)符
(3)調(diào)用RigisterClass來注冊(cè)這個(gè)窗口類;
Register(&wndclass)這個(gè)函數(shù)只有一個(gè)參數(shù),即指向WNDCLASS的指針
補(bǔ)充:許多windows函數(shù)需要分配內(nèi)存,如RegisterClass函數(shù)需要分配內(nèi)存,以保存關(guān)于窗口類的信息。
(4)創(chuàng)建窗口
窗口類定義了窗口的一般特征,因此可以使用同一窗口類創(chuàng)建許多不同的窗口,調(diào)用CreateWindow創(chuàng)建窗口時(shí),可能指定窗口有關(guān)的更詳細(xì)的信息;
補(bǔ)充:窗口類及窗口的區(qū)別,以及createWindow函數(shù)和RegisterClass函數(shù)的區(qū)別
傳給RegisterClass的函數(shù)信息在一個(gè)數(shù)據(jù)結(jié)構(gòu)中說明,傳遞給CreateWindows的函數(shù)的信息作為函數(shù)的單獨(dú)參數(shù)。
補(bǔ)充:HWMD
hwnd;創(chuàng)建一個(gè)窗口的句柄,存放在變量hwnd中,HWND為窗口句柄類型,Windows中每個(gè)窗口都有一個(gè)句柄,程序用句柄引用窗口。許多windows函數(shù)需要使用hwnd作為參數(shù),這樣,Windows才能知道函數(shù)是針對(duì)那個(gè)窗口的,如果一個(gè)程序創(chuàng)建了很多窗口,則每個(gè)窗口均有一個(gè)句柄。(窗口句柄是Windows程序處理的最重要的句柄之一);
窗口風(fēng)格:WS_OVERLAPPEDWINDOW是一個(gè)標(biāo)準(zhǔn)風(fēng)格的函數(shù)
(5)顯示窗口
ShowWindow(hwnd, iCmdShow);
UpateWindow(hwnd);
(6)消息循環(huán)
調(diào)用UpdateWindow之后,窗口就出現(xiàn)在視頻顯示器上,程序現(xiàn)在必須準(zhǔn)備讀入用戶用鍵盤和鼠標(biāo)輸入的數(shù)據(jù)。Windows
為當(dāng)前運(yùn)行的每個(gè)Windows程序維護(hù)一個(gè)消息隊(duì)列。當(dāng)發(fā)生輸入事件之后,Windows將事件轉(zhuǎn)換為一個(gè)消息,并將消息放在程序的消息隊(duì)列中。
程序通過執(zhí)行一塊被成為消息循環(huán)的代碼從消息隊(duì)列中取出消息
while(GetMessage(&msg,NULL,0,0))
{
TracslateMessage(&msg);
DispatchMessage(&msg);
}
補(bǔ)充:msg變量是類型為MSG的結(jié)構(gòu),MSG類型在WINUSER.H中定義如下:
type struct tagMSG
{
HWND
hwnd; 該程序擁有的唯一窗口
UINT message;
消息標(biāo)示符。是一個(gè)數(shù)值,用來標(biāo)示消息。對(duì)于每個(gè)消息,均有一個(gè)標(biāo)識(shí)符與之對(duì)應(yīng)。這些標(biāo)示符定義在Windows頭文件中。以前綴WM開頭。
例如:用戶將鼠標(biāo)光標(biāo)放在客戶區(qū)域之內(nèi),并按下左鍵,則Windows在消息隊(duì)列中放入一消息,該消息的message域等于WM_LBUTTONDOWN(是一個(gè)常量);
WPARAM
wParam;32的消息參數(shù),其含義和數(shù)值根據(jù)消息的不同而不同;
LPARAM
IParam;一個(gè)32位的消息參數(shù),其含義與消息有關(guān)
DWORD
time; 消息放入消息隊(duì)列的時(shí)間
POINT
pt;
消息放入隊(duì)列的鼠標(biāo)坐標(biāo)
}
typedef struct tagPOINT
{
LONG
X;
LONG
Y;
}
發(fā)生輸入事件后,Windows將其轉(zhuǎn)換為一個(gè)消息放入消息隊(duì)列中,程序從消息隊(duì)列取出消息,只要從消息隊(duì)列取出消息的message域不為WM_QUIT,則GetMessage就返回一個(gè)非零值;
TranslateMessage(&msg);將msg結(jié)構(gòu)傳給Windows,
DispatchMessage(&msg);
又將msg結(jié)構(gòu)回傳給Windows。然后Windows將該消息發(fā)送給適當(dāng)?shù)拇翱谶^程,讓它進(jìn)行處理。
注:Windows調(diào)用窗口過程,這個(gè)窗口過程是WndPro函數(shù),處理完消息后,WndProc返回到Windows,此時(shí)Windows還停留在DispatchMessage調(diào)用中,在結(jié)束DispatchMessage調(diào)用的處理之后,Windows回到HELLOWIN中,并且從下一個(gè)GetMessage調(diào)用開始循環(huán)消息;
(7)窗口過程
注:準(zhǔn)備性工作,注冊(cè)窗口類-》創(chuàng)建窗口-》顯示窗口-》程序進(jìn)入消息循環(huán)-》從消息隊(duì)列中取出一條消息-》窗口過程進(jìn)行處理
窗口過程確定了在窗口的客戶區(qū)域中顯示些什么,以及窗口怎么響應(yīng)用戶輸入;
一個(gè)WINDOWS程序可以包含多個(gè)窗口過程,一個(gè)窗口過程總是于調(diào)用RigisterClass注冊(cè)的特定窗口類相關(guān)聯(lián)。CreateWindow函數(shù)根據(jù)特定的窗口類創(chuàng)建一個(gè)窗口。但基于一個(gè)窗口類可以創(chuàng)建多個(gè)窗口。
窗口過程的定義:
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,
LPARAM iParam)
程序通常不直接調(diào)用窗口調(diào)用,窗口調(diào)用通常有WINDOWS本身調(diào)用。通過SendMessage函數(shù),程序能夠直接調(diào)用它自己的窗口過程
(8)處理消息
窗口過程接受的每個(gè)消息均是用一個(gè)數(shù)值來標(biāo)示的,也就是傳給窗口過程的message參數(shù)。WINDOWS頭文件WINUSER.H為每個(gè)消息參數(shù)定義為WM為前綴的標(biāo)識(shí)符;
WINDOWS程序員使用switch和case結(jié)構(gòu)來確定窗口過程接受的是什么消息,以及如何適當(dāng)?shù)奶幚硭?,窗口過程在處理消息時(shí)必須返回零,窗口過程不予處理的所有消息應(yīng)該被傳給名為DefWindowProc的WINDOWS函數(shù)。從DefWindowProc返回的值必須有窗口過程返回。
補(bǔ)充:調(diào)用DefWindowProc來為窗口過程不予處理的所有消息提供默認(rèn)處理。
(9)播放聲音文件
窗口過程接受的第一個(gè)消息,WM_CREATE,也是WndProc選擇處理的第一個(gè)消息。
接受消息的機(jī)制:
當(dāng)程序調(diào)用CreateWindow函數(shù)時(shí),WINDOWS調(diào)用Wndproc,將其第一個(gè)參數(shù)設(shè)置為句柄,第二個(gè)參數(shù)設(shè)置為wm_create;
WndProc處理WM_CREATE消息,并將控制返回給WINDOWS;
WINDOWS從CreateWindow調(diào)用中返回到程序,繼續(xù)下一步的處理。
(10) WM_PAINT消息
這個(gè)消息在Windows程序設(shè)計(jì)中很重要,當(dāng)窗口客戶區(qū)域的一部分或全部變?yōu)闊o效時(shí),以至于必須重新刷新時(shí),將有這個(gè)消息通知程序;
補(bǔ)充:最初創(chuàng)建窗口時(shí),整個(gè)客戶區(qū)都是無效的,因?yàn)槌绦蜻€沒有在窗口上畫什么東西。第一個(gè)WM_PAINT消息指示窗口過程在客戶區(qū)域上畫些東西;
用戶改變窗口大小時(shí),客戶區(qū)重新變得無效,然后窗口過程將收到一個(gè)wm_paint消息
對(duì)wm_paint的處理總是從一個(gè)BeginPaint調(diào)用開始,以一個(gè)EndPaint調(diào)用哪個(gè)結(jié)束;這兩個(gè)調(diào)用中,第一個(gè)參數(shù)是程序的窗口句柄,第二個(gè)參數(shù)是指向類型為PAINTSTRUCT的結(jié)構(gòu)指針(該結(jié)構(gòu)中包含一些窗口過程,用來刷新客戶區(qū)域的指針);BeginPain調(diào)用使整個(gè)客戶區(qū)有效,并返回一個(gè)設(shè)備描述表句柄。設(shè)備描述表是指物理輸出設(shè)備及其他設(shè)備驅(qū)動(dòng)程序。在窗口的客戶區(qū)域顯示文本和圖形需要設(shè)備描述表句柄(不能用從BeginPaint返回的設(shè)備描述表句柄在客戶區(qū)域之外繪圖);EndPaint釋放設(shè)備描述表句柄,使之不在有效;
調(diào)用完BeginPaint之后,WndProc接著調(diào)用GetClientRect;其第一個(gè)參數(shù)是程序窗口的句柄,第二個(gè)參數(shù)是一個(gè)指向RECT結(jié)構(gòu)類型的指針;
補(bǔ)充:rectangle結(jié)構(gòu)有四個(gè)LONG域,分別為left,top,right,botton。表示窗口客戶區(qū)域的尺寸,left和top設(shè)置為0,right和bottom設(shè)置為客戶區(qū)域的寬度和高度。(像素點(diǎn)數(shù));
將RECT指針作為DrawText的第四個(gè)參數(shù)傳遞,不在做其他處理;當(dāng)客戶區(qū)變得無效,WndProc就接受一個(gè)新的wm_paint消息,WndProc通過調(diào)用GetClientRect獲取變化后的窗口大小,并在新窗體的中央現(xiàn)實(shí)文本。
(11)WM_DESTROY消息
該消息提示,WINDOWS正在根據(jù)用戶輸入的命令來清楚窗口。(用戶單擊CLoce按鈕或者在程序的系統(tǒng)菜單上選擇close時(shí)發(fā)生);程序通過調(diào)用PostQuitMessage以標(biāo)準(zhǔn)方式響應(yīng)WM_DESTROY消息;該函數(shù)在程序的消息隊(duì)列中插入一個(gè)WM_QUIT消息,當(dāng)GetMessage取得一個(gè)wm_quit消息時(shí),返回0,這將導(dǎo)致WinMain退出消息循環(huán)并終止程序;
(12)Window編程的難點(diǎn)
在HELLOWIN中,WinMain包含了注冊(cè)窗口類,創(chuàng)建窗口,從消息隊(duì)列中取得消息和發(fā)送消息等相關(guān)的代碼;
程序所有的動(dòng)作均在窗口過程中發(fā)生,實(shí)際上,WINDOWS程序所做的一切都是響應(yīng)發(fā)送給窗口過程的消息;
(13)別調(diào)用我,我會(huì)調(diào)用你
在WINDOWS程序設(shè)計(jì)中,WINDOWS有1000個(gè)以上的函數(shù)可供程序調(diào)用,但WINDOWS也在調(diào)用用戶程序;例如前面定義的窗口過程WndProc,窗口過程與一個(gè)窗口類相關(guān)聯(lián),窗口類是程序調(diào)用RegisterCLASS注冊(cè)的。基于該類創(chuàng)建的窗口使用這個(gè)窗口過程來處理窗口的所有消息,WINDOWS通過調(diào)用窗口過程來給窗口發(fā)送一個(gè)消息;
所有的WndProc調(diào)用都以消息的方式進(jìn)行,大多數(shù)WINDOWS程序中,程序的主要部分都用來處理消息;(WINDOWS可以發(fā)送給窗口過程的消息通常都以WM打頭的標(biāo)識(shí)符,并且都在WINUSER.H中定義);在WINDOWS中窗口中發(fā)生的一切都以消息的形式傳給窗口過程,然后窗口過程以某種方式響應(yīng)這個(gè)消息;
注:一個(gè)窗口過程能處理基于同一個(gè)窗口創(chuàng)建的多個(gè)窗口的消息,參數(shù)hwnd讓窗口過程知道那個(gè)窗口接受消息;
(14)WinProc窗口過程的各個(gè)參數(shù)
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM
wParam,LPARAM IParam)
參數(shù)message是WM_SIZW,消息WM_SIZE的參數(shù)wParam
參數(shù)wPARAM在WINUSER.H中定義為數(shù)字0到4表明窗口是非最小化還是非最大化
參數(shù)IParam包含新窗口的大??;
注:有時(shí)候,DefWindowProc處理完消息后會(huì)產(chǎn)生其他消息;窗口過程用來處理消息;
|