Windows 编程基础(四)
視窗和消息
進行 Windows 程式設計,實際上是在進行一種物件導向的程式設計(OOP)。
裝飾對話方塊表面的還有各式各樣的按鍵、單選按鈕、核取方塊、清單方
塊、卷動列和文字輸入區域。其中每一個小的視覺物件都是一個視窗。更確切
地說,這些都稱為【子視窗】或【控制項視窗】或【子視窗控制項】。
所謂【Windows 給程式發送訊息】,是指 Windows 呼叫程式中的一個函式,該函式的參數描述了這個特定訊息。這種位于 Windows 程式中的函式稱為【視窗訊息處理程式】。
視窗通常是在【視窗類別】的基礎上建立的。視窗類別標識了處理視窗訊息的視窗訊息處理程式。
Windows 程式開始執行后,Windows 為該程式建立一個【訊息佇列】。這個
訊息佇列用來存放該程式可能建立的各種不同視窗的訊息。程式中有一小段程式碼,叫做【訊息回圈】,用來從佇列中取出訊息,并且將它們發送給相應的視窗訊息處理程式。有些訊息直接發送給視窗訊息處理程式,不用放入訊息佇列中。
HELLOWIN 程式
必須把hellowin.wav文件放在工程的同一個夾子下。
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)函數解析:
LRESULT是一個數據類型,即長整形。
CALLBACK 即回調函數,通過函數指針調用的函數。CALLBACK就是 __stdcall(回調函數),這里也叫窗口函數,來執行窗口的消息循環。
HWND 是窗口的句柄。hwnd用來接收當前消息的窗口句柄
UINT 也談過,就是unsigned int 無符號整型,兩個字節。message是被傳過來的消息。
WPARAM WP是前綴名,表示寬字符指針。wParam 是用來附加在消息上的數據。和 MSG 結構體一樣
LPARAM LP是前綴名,表示長指針。lParam 也是用來附加在消息上的數據。和 MSG 結構體一樣。
HDC:設備上下文 句柄(可以理解為指向DC結構的指針),它指向一塊描述設備的相關的內容的內存塊。
DC: 設備上下文(設備描述表),是WINDOWS的一種數據類型。
HDC設備上下文 是一種包含有關某個設備(如顯示器或打印機)的繪制屬性信息的 Windows 數據結構。
所有繪制調用都通過設備上下文對象進行,這些對象封裝了用于繪制線條、形狀和文本的 Windows API
PAINTSTRUCT:和繪圖有關的結構體
typedef struct tagPAINTSTRUCT { HDC hdc; BOOL fErase; RECT rcPaint; BOOL fRestore; BOOL fIncUpdate; BYTE rgbReserved[32]; } PAINTSTRUCT, *PPAINTSTRUCT;hdc 是用于繪制的句柄,
fErase 如果為非零值則擦除背景,否則不擦除背景,
rcPaint 通過制定左上角和右下角的坐標確定一個要繪制的矩形范圍,該矩形單位相對于客戶區左上角,
后面三個參數都是系統預留的,編程一般用不到。
PAINTSTRUCT 包含了用于繪制窗口客戶區的信息。例如要更新的客戶區的矩形區域的大小等等。
程序處理 WM_PAINT 消息時將會用到它,該結構體的作用就是重繪客戶區的。
每個窗口要有一個PAINTSTRUCT結構來記錄一些繪制信息,PAINTSTRUCT結構保存了窗口繪制客戶區的一些信息。例如,繪制客戶區時是否要清除背景色,要更新的客戶區的矩形區域的大小等等。
RECT:也是一個結構體,用來顯示窗口的位置的
typedef struct _RECT {LONG left; LONG top;LONG right;LONG bottom; } RECT, *PRECT;從結構體命名上很清楚地表明了結構體的作用。
switch(message) 語句:
WM_CREATE 是窗口消息中的 請求創建窗口時的消息
PlaySound() 原型:
BOOL PlaySound(LPCSTR pszSound, HMODULE hmod,DWORD fdwSound);
PlaySound參數:pszSound 是指定了要播放聲音的字符串,該參數可以是WAVE文件的名字,或是WAV資源的名字,或是內存中聲音數據的指針,或是在系統注冊表WIN.INI中定義的系統事件聲音。如果該參數為NULL則停止正在播放的聲音。
參數:hmod 是應用程序的實例句柄,除非pszSound的指向一個資源標識符
(即fdwSound被定義為SND_RESOURCE),否則必須設置為NULL。
參數:fdwSound是標志的組合。若成功則函數返回TRUE,否則返回FALSE。
返回值:非零表示成功,零表示失敗。
WM_PAINT 是窗口消息中的 客戶區重繪消息
當窗口顯示區域的一部分顯示內容或者全部變為“無效”,以致于必須“更新畫面”時,將由這個消息通知程序。
當需要繪制一部分應用窗口的時候,這個消息被Windows或者其他應用程序繪制調用。
對WM_PAINT的處理幾乎總是從一個 BeginPaint() 調用開始:hdc = BeginPaint (hwnd, &ps) ;
而以一個 EndPaint() 調用結束:EndPaint (hwnd, &ps) ;
在這兩個調用中,第一個參數都是程序的窗口句柄,第二個參數是指向型態為PAINTSTRUCT的結構指針。
PAINTSTRUCT結構中包含一些窗口消息處理程序,可以用來更新顯示區域的內容。
BeginPaint調用令整個顯示區域有效,并傳回一個“設備上下文句柄”。在窗口的顯示區域顯示文字和圖形需要設備上下文句柄。
但是從BeginPaint傳回的設備上下文句柄不能在顯示區域之外繪圖。EndPaint釋放設備上下文句柄,使之不再有效。
調用完BeginPaint之后,WndProc接著調用GetClientRect:
GetClientRect (hwnd, &rect) ;
第一個參數是程序窗口的句柄。第二個參數是一個指針,指向一個RECT型態的rectangle結構。
該結構有四個LONG字段,分別為left、top、right和bottom。GetClientRect將這四個字段設定為窗口顯示區域的尺寸。
left和top字段通常設定為0,right和bottom字段設定為顯示區域的寬度和高度(像素點數)。
WndProc除了將該RECT結構指針作為DrawText的第四個參數傳遞外,不再對它做其它處理。
DrawText() 原型:
int DrawText(HDC hdc, LPCTSTR lpString, int nCount, LPRECT lpRect, UINT uFormat);
參數:
hdc:設備環境句柄。
lpString:指向將被寫入的字符串的指針,如果參數nCount是-1,則字符串必須是以\0結束的。
如果uFormat包含DT_MODIFYSTRING,則函數可為此字符串增加4個字符,存放字符串的緩沖區必須足夠大,能容納附加的字符。
nCount:指向字符串中的字符數。如果nCount為-1,則lpString指向的字符串被認為是以\0結束的,DrawText() 會自動計算字符數。
lpRect:指向結構RECT的指針,其中包含正文將被置于其中的矩形的信息(按邏輯坐標)。
uFormat:指定格式化正文的方法。該值都是 DT_*** 的樣式。
返回值:如果函數調用成功,返回值是正文的高度;如果函數調用失敗,返回值是0。
第三個 case 語句: WM_DESTROY 是窗口消息中的 窗口摧毀消息
PostQuitMessage() 該函數向系統表明有個線程有終止請求。通常用來響應 WM_DESTROY 消息。
函數原型:VOID PostQuitMessage(int nExitCode);
參數 nExitCode:指定應用程序退出代碼。此值被用作消息 WM_QUIT 的 wParam 參數。
PostQuitMessage寄送一個WM_QUIT消息給線程的消息隊列并立即返回;此函數向系統表明有個線程請求在隨后的某一時間終止。
當線程從消息隊列里取得WM_QUIT消息時,應當退出消息循環并將控制返回給系統。返回給系統的退出值必須是消息WM_QUIT的。
返回值:無
DefWindowProc() 調用缺省的窗口過程來為應用程序沒有處理的任何窗口消息提供缺省的處理。
函數功能:該調用DefWindowProc函數時使用窗口過程接收的相同參數。
函數原型:LRESULT DefWindowProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
DefWindowProc這個函數是默認的窗口處理函數,我們可以把不關心的消息都丟給它來處理。
這個函數在處理關閉窗口消息WM_CLOSE時,是調用 DestroyWindow() 關閉窗口并且發 WM_DESTROY 消息給應用程序。
而它對WM_DESTROY這個消息是不處理的,我們在應用程序中對這個消息的處理是發出WM_QUIT消息。
因此WM_CLOSE、WM_DESTROY、WM_QUIT這三個消息是先后產生的。
hWnd:指向接收消息的窗口過程的句柄。
Msg:指定消息類型。
wParam:指定其余的、消息特定的信息。該參數的內容與Msg參數值有關。
IParam:指定其余的、消息特定的信息。該參數的內容與Msg參數值有關。
返回值:返回值就是消息處理結果,它與發送的消息有關。
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)函數解析:
HWND 的數據類型表示 句柄:
一個句柄是指使用的一個唯一的整數值,即一個4字節(64位程序中為8字節)長的數值。用來標識應用程序中的不同對象和同類中的不同的實例。
應用程序能夠通過句柄訪問相應的對象的信息,但是句柄不是指針,程序不能利用句柄來直接閱讀文件中的信息。
句柄是Windows用來標志應用程序中建立的或是使用的唯一整數,Windows大量使用了句柄來標識對象。
句柄與普通指針的區別在于,指針包含的是引用對象的內存地址,而句柄則是由系統所管理的引用標識。
該標識可以被系統重新定位到一個內存地址上。這種間接訪問對象的模式增強了系統對引用對象的控制。
WINDOWS程序中并不是用物理地址來標識一個內存塊,文件,任務或動態裝入模塊的。
相反,WINDOWS API給這些項目分配確定的句柄,并將句柄返回給應用程序,然后通過句柄來進行操作。
一個句柄,只有當唯一地確定了一個項目的時候,它才開始有意義。
句柄對應著項目表中的一項,而只有WINDOWS本身才能直接存取這個表,應用程序只能通過API函數來處理不同的句柄。
總而言之:句柄就是對窗口及窗口的控件進行標識的,如果要改變窗口或它的控件的話,就需要指定窗口或控件對它進行改變。
MSG是 Windows 程序中的結構體。在Windows程序中,消息是由MSG結構體來表示的。
typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG,*PMSG;成員變量含義:
第一個成員變量 hwnd 表示消息所屬的窗口。我們通常開發的程序都是窗口應用程序,一個消息一般都是與某個窗口相關聯的。
第二個成員變量message指定了消息的標識符。在Windows中,消息是由一個數值來表示的,不同的消息對應不同的數值。但是由于數值不便于記憶,所以Windows將消息對應的數值定義為WM_XXX宏(WM是Window Message的縮寫)的形式。
第三、第四個成員變量wParam和lParam,用于指定消息的附加信息。
例如,當我們收到一個字符消息的時候,message成員變量的值就是WM_CHAR,但用戶到底輸入的是什么字符,那么就由wParam和lParam來說明。wParam、lParam表示的信息隨消息的不同而不同。如果想知道這兩個成員變量具體表示的信息,可以在MSDN中關于某個具體消息的說明文檔查看到。
最后兩個變量分別表示消息投遞到消息隊列中的時間和鼠標的當前位置。
WNDCLASS
WNDCLASS是一個由系統支持的結構,用來儲存某一類窗口的信息,如ClassStyle,消息處理函數,Icon,Cursor,背景Brush等。
也就是說,CreateWindow只是將某個WNDCLASS定義的窗體變成實例。
結構體 WNDCLASS 包含一個窗口類的全部信息,也是Windows編程中使用的基本數據結構之一,應用程序通過定義一個窗口類確定窗口的屬性。
RegisterClass() :
RegisterClass注冊后再調用 CreatWindow() 中使用的窗口類。
該函數的聲明: ATOM RegisterClass(__inCONST WNDCLASS *lpWndClass);
lpWndClass:指向一個 WNDCLASS 結構的指針。在將它傳遞給函數之前,必須在該結構中填充適當的類屬性。
ATOM類型為Windows中定義的新數據類型,其即unsigned short類型。
如果函數成功,返回值是唯一標識已注冊的類的一個原子;如果函數失敗,返回值為0。
CreatWindow() :
HWND CreateWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HANDLE hlnstance, LPVOID lpParam );主要參數:
lpClassName
指向一個空結束的字符串或整型數atom。如果該參數是一個整型量,它是由此前調用theGlobalAddAtom函數產生的全局量。
這個小于0xC000的16位數必須是lpClassName參數字的低16位,該參數的高位必須是0。
如果lpClassName是一個字符串,它指定了窗口的類名。
這個類名可以是任何用函數RegisterClass注冊的類名,或是任何預定義的控制類名。
LPWindowName
指向一個指定窗口名的空結束的字符串指針。
如果窗口風格指定了標題條,由lpWindowName指向的窗口標題將顯示在標題條上。
當使用Createwindow函數來創建控制例如按鈕,選擇框和靜態控制時,可使用lpWindowName來指定控制文本。
dwStyle
指定創建窗口的風格。該參數可以是下列窗口風格的組合再加上說明部分的控制風格。
X
指定窗口的初始水平位置。對一個層疊或彈出式窗口,X參數是屏幕坐標系的窗口的左上角的初始X坐標。
對于子窗口,x是子窗口左上角相對父窗口客戶區左上角的初始X坐標。
如果該參數被設為CW_USEDEFAULT則系統為窗口選擇缺省的左上角坐標并忽略Y參數。
CW_USEDEFAULT只對層疊窗口有效,如果為彈出式窗口或子窗口設定,則X和y參數被設為零。
Y
指定窗口的初始垂直位置。對一個層疊或彈出式窗口,y參數是屏幕坐標系的窗口的左上角的初始y坐標。
對于子窗口,y是子窗口左上角相對父窗口客戶區左上角的初始y坐標。
對于列表框,y是列表框客戶區左上角相對父窗口客戶區左上角的初始y坐標。
如果層疊窗口是使用WS_VISIBLE風格位創建的并且X參數被設為CW_USEDEFAULT,則系統將忽略y參數。
nWidth
以設備單元指明窗口的寬度。對于層疊窗口,nWidth或是屏幕坐標的窗口寬度或是CW_USEDEFAULT。
若nWidth是CW_USEDEFAULT,則系統為窗口選擇一個缺省的高度和寬度:
缺省寬度為從初始X坐標開始到屏幕的右邊界,缺省高度為從初始Y坐標開始到目標區域的頂部。
CW_USEDEFAULT只對層疊窗口有效;如果為彈出式窗口和子窗口設定CW_USEDEFAULT標志則nWidth和nHeight被設為零。
nHeight
以設備單元指明窗口的高度。對于層疊窗口,nHeight是屏幕坐標的窗口寬度。
若nWidth被設為CW_USEDEFAULT,則系統忽略nHeight參數。
hWndParent
指向被創建窗口的父窗口或所有者窗口的句柄。若要創建一個子窗口或一個被屬窗口,需提供一個有效的窗口句柄。
這個參數對彈出式窗口是可選的。Windows NT 5.0;創建一個消息窗口,
可以提供HWND_MESSAGE或提供一個己存在的消息窗口的句柄。
hMenu
菜單句柄,或依據窗口風格指明一個子窗口標識。對于層疊或彈出式窗口,hMenu指定窗口使用的菜單:
如果使用了菜單類,則hMenu可以為NULL。對于子窗口,hMenu指定了該子窗口標識(一個整型量),
一個對話框使用這個整型值將事件通知父類。
應用程序確定子窗口標識,這個值對于相同父窗口的所有子窗口必須是唯一的。
hlnstance
與窗口相關聯的模塊實例的句柄。
lpParam
指向一個值的指針,該值傳遞給窗口 WM_CREATE 消息。該值通過在IParam參數中的 CREATESTRUCT 結構傳遞。
如果應用程序調用CreateWindow創建一個MDI客戶窗口,則lpParam必須指向一個CLIENTCREATESTRUCT結構。
返回值:如果函數成功,返回值為新窗口的句柄:如果函數失敗,返回值為NULL。
備注:
在返回前,CreateWindow給窗口過程發送一個WM_CREATE消息。
對于層疊,彈出式和子窗口,CreateWindow給窗口發送WM_CREATE,WM_GETMINMAXINFO和WM_NCCREATE消息。
消息WM_CREATE的IParam參數包含一個指向CREATESTRUCT結構的指針。
如果指定了WS_VISIBLE風格,CreateWindow向窗口發送所有需要激活和顯示窗口的消息。
ShowWindow() :
函數功能:該函數設置指定窗口的顯示狀態。
函數原型:BOOL ShowWindow(HWND hWnd, int nCmdShow);
參數:
hWnd:指窗口句柄。
nCmdShow:指定窗口如何顯示。
如果發送應用程序的程序提供了STARTUPINFO結構,則應用程序第一次調用ShowWindow時該參數被忽略。
否則,在第一次調用ShowWindow函數時,該值應為在函數WinMain中nCmdShow參數。
返回值:如果窗口之前可見,則返回值為非零。如果窗口之前被隱藏,則返回值為零。
備注:
應用程序第一次調用ShowWindow時,應該使用WinMain函數的nCmdshow參數作為它的nCmdShow參數。
在隨后調用ShowWindow函數時,必須使用列表中的一個給定值,而不是由WinMain函數的nCmdSHow參數指定的值
UpdateWindow() :
如果窗口更新的區域不為空,UpdateWindow函數就發送一個 WM_PAINT 消息來更新指定窗口的客戶區。
函數繞過應用程序的消息隊列,直接發送WM_PAINT消息給指定窗口的窗口過程,如果更新區域為空,則不發送消息。
函數原型:
BOOL UpdateWindow(
HWND hWnd // 窗口的句柄
);
返回值:如果函數調用成功,返回值為非零值。如果函數調用不成功,返回值為零。
GetMessage() :
函數聲明:
GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax)
參數:
lpMsg:指向MSG結構的指針,該結構從線程的消息隊列里接收消息信息。
hWnd:取得其消息的窗口的句柄。當其值取NULL時,GetMessage為任何屬于調用線程的窗口檢索消息,線程消息通過PostThreadMessage寄送給調用線程。
wMsgFilterMin:指定被檢索的最小消息值的整數。
wMsgFilterMax:指定被檢索的最大消息值的整數。
返回值:如果函數取得WM_QUIT之外的其他消息,返回非零值。
如果函數取得WM_QUIT消息,返回值是零。如果出現了錯誤,返回值是 -1。例如,當hWnd是無效的窗口句柄或 lpMsg 是無效的指針時。
備注:
應用程序通常用返回值來確定是否終止主消息循環并退出程序。
GetMesssge只接收與參數hWnd標識的窗口或子窗口相聯系的消息,子窗口由函數IsChild決定。
消息值的范圍由參數wMsgFilterMin和wMsgFilterMax給出。
如果hWnd為NULL,則GetMessage接收屬于調用線程的窗口的消息,線程消息由函數PostThreadMessage寄送給調用線程。
GetMessage不接收屬于其他線程或其他線程的窗口的消息,即使hWnd為NULL。
由PostThreadMessage寄送的線程消息,其消息hWnd值為NULL。
如果wMsgFilterMin和wMsgFilterMax都為零,GetMessage返回所有可得的消息(即,無范圍過濾)。
常數 WM_KEYFIRST和WM_KEYLAST可作為過濾值取得與鍵盤輸入相關的所有消息:
常數WM_MOUSEFIRST和WM_MOUSELST可用來接收所有的鼠標消息。
如果wMsgFilterMin和wMsgFilterMax都為零,GetMessage返回所有可得的消息(即,無范圍過濾)。
GetMessage不從隊列里清除WM.PAINT消息。該消息將保留在隊列里直到處理完畢。
注意,此函數的返回值可非零、零或-1,應避免如下代碼出現:
while(GetMessage(IpMsg,hwnd,0,0))…
返回-1時處理錯誤而不是繼續循環。
TranslateMessage() :
函數用于將虛擬鍵消息轉換為字符消息。
字符消息被寄送到調用線程的消息隊列里,當下一次線程調用函數 GetMessage 或 PeekMessage 時被讀出。
函數原型:
BOOL TranslateMessage( CONST MSG*lpMsg );
IpMsg:指向含有消息的MSG結構的指針,該結構里含有用函數GetMessage或PeekMessage從調用線程的消息隊列里取得的消息信息。
返回值:如果消息被轉換(即,字符消息被寄送到調用線程的消息隊列里),返回非零值。
如果消息是WM_KEYDOWN,WM_KEYUP WM_SYSKEYDOWN或WM_SYSKEYUP,返回非零值,不考慮轉換。
如果消息沒被轉換(即,字符消息沒被寄送到調用線程的消息隊列里),返回值是零。
備注:此函數不修改由參數IpMsg指向的消息。
DispatchMessage() :
函數功能:該函數分發一個消息給窗口程序。通常消息從GetMessage函數獲得或者TranslateMessage函數傳遞的。
消息被分發到回調函數(過程函數),作用是消息傳遞給操作系統,
然后操作系統去調用我們的回調函數,也就是說我們在窗體的過程函數中處理消息。
函數原型:LONG DispatchMessage (CONST MSG*lpmsg);
參數:
lpmsg:指向含有消息的MSG結構的指針。
返回值:返回值是窗口程序返回的值。盡管返回值的含義依賴于被調度的消息,但返回值通常被忽略。
備注:MSG結構必須包含有效的消息值。
如果參數lpmsg指向一個WM_TIMER消息,并且WM_TIMER消息的參數IParam不為NULL,則調用IParam指向的函數,而不是調用窗口程序。
(注意,幾乎所有的 API 函數發生錯誤,都可以調用 GetLastError() 來獲取錯誤信息。GetLastError() 返回一個錯誤代碼,可以根據錯誤代碼找到相關信息。函數名后帶有 EX 的表示該函數的擴展函數)
總結
以上是生活随笔為你收集整理的Windows 编程基础(四)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cordova编译crosswalk-w
- 下一篇: spring boot+thymelea