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