day05

一、深入GetMessage、PeekMessage
從消息隊列中獲取/查看消息.
BOOL GetMessage (
LPMSG lpMsg,
HWND hWnd,
UINT uMsgFilterMin,
UINT uMsgFilterMax
)
{
check_prog_mq:
if (程序消息隊列中是否有滿足hWnd、uMsgFilterMin、uMsgFilterMax限制的消息)
{
將該消息填入lpMsg所指向的MSG結構體;
從程序消息隊列中刪除該消息;
return lpMsg-> message != WM_QUIT ? TRUE : FALSE;
}
check_sys_mq:
if (系統消息隊列中有屬於本程序的消息)
{
要求系統將該消息轉發到程序消息隊列中;
goto check_prog_mq;
}
if (當前程序中存在需要重繪的窗口(包含無效區))
{
產生WM_PAINT消息,追加到系統消息隊列中;
goto check_sys_mq;
}
if (當前程序中存在已經到期的定時器)
{
if (該定時器存在自己的處理函數)
調用定時器處理函數;
else {
產生WM_TIMER消息,追加到系統消息隊列中。
goto check_sys_mq;
}
}
整理資源;
goto check_prog_mq;
}


BOOL PeekMessage (
LPMSG lpMsg,
HWND hWnd,
UINT uMsgFilterMin,
UINT uMsgFilterMax,
UINT wRemoveMsg
)
{
check_prog_mq:
if (程序消息隊列中是否有滿足hWnd、uMsgFilterMin、uMsgFilterMax限制的消息)
{
將該消息填入lpMsg所指向的MSG結構體;
if (wRemoveMsg == PM_REMOVE)
從程序消息隊列中刪除該消息;
return TRUE;
}
check_sys_mq:
if (系統消息隊列中有屬於本程序的消息)
{
要求系統將該消息轉發到程序消息隊列中;
goto check_prog_mq;
}
if (當前程序中存在需要重繪的窗口(包含無效區))
{
產生WM_PAINT消息,追加到系統消息隊列中;
goto check_sys_mq;
}
if (當前程序中存在已經到期的定時器)
{
if (該定時器存在自己的處理函數)
調用定時器處理函數;
else {
產生WM_TIMER消息,追加到系統消息隊列中。
goto check_sys_mq;
}
}
整理資源;
return FALSE;
}
注意: WM_PAINT和WM_TIMER消息可能因爲其他消息過多而被延遲處理。
二、窗口繪製消息:WM_PAINT
WM_PAINT - 當窗口中存在需要重繪的部分(無效區域)時,收到此消息。
wParam - 不使用
lParam - 不使用




收到WM_PAINT消息的時機:
1窗口首次顯示
UpdateWindow ()把窗口製爲無效區
2改變大小 - 縮小不會重繪
3從最小化恢復
4倍遮擋或移除屏幕恢復顯示;
5人爲將窗口中某些區域置爲無效(InvalidateRect)


無效區域:窗口中需要重新繪製的部分。
無效矩形:所有無效區域的外接矩形


人爲這頂無效區域矩形:
BOOL InvalidateRect (
HWND hWnd, //窗口句柄
CONST RECT* lpRect, //無效矩形,NULL表示整個客戶區
BOOL bErase //是否重刷背景
);
成功返回TRUE,失敗返回FALSE
4.WM_PAINT消息的處理步驟
1)開始繪圖: 獲取設備上下文,爲後續繪圖函數的調用做準備.
HDC BeginPaint (
HWND hWnd, //窗口句柄
LPPAINTSTRUCT lpPaint //繪圖結構
);
成功返回設備上下文句柄,失敗返回NULL
typedef struct tag_PAINTSTRUCT {
...
RECT rcPaint; //無效矩形
...
};
如:
PAINTSTRUCT ps;
HDC hDC = BeginPaint (hWnd, &ps);
...
2)執行繪圖: 創建必要的GDI對象(畫筆、畫刷、字體) -> 將所創建GDI對象放入設備上下文,同時備份其原有的GDI對象 -> 調用繪圖函數 -> 恢復設備上下文 -> 銷燬GDI對象
....


默認 
畫筆:黑子
畫刷:白色
字體:系統字體


HPEN hpenNew = CreatePen (PS_SOLID, 1, REB(255, 0, 0));
HPEN hpenOld = SelectObject (hDC, hpenNew);
Ellipse (hDC, ....);
SelectObject (hDC, hpenOld);
DelectObject (hpenNew);
....
3)結束繪圖:釋放BeginPaint函數所分配的資源,結束繪圖過程。
BOOL EndPaint (
HWND hWnd, //窗口句柄
CONST LPPAINTSTRUCT lpPaint //繪圖結構
);
在任何時候都返回TRUE
...
EndPaint (hWnd, &ps);


5.擦除窗口的背景:WM_ERASEBKGND:
wParam - 設備上下文句柄
這個消息是在WM_PAINT消息之前處理的。如果沒有設置這個消息,他就會使用窗口類中定義的刷子,我們可以通過對於他的控制來
重新匯出一個背景








三、鍵盤消息
1.系統鍵、普通鍵、字符鍵
1)系統鍵:F10、Alt、Alt+其他鍵
2)普通鍵:按鍵時沒有同時按住Alt鍵
3)字符鍵:對應可顯示字符的普通鍵
2.按鍵消息
WM_SYSKEDOWN - 系統鍵按下,可能連續出現
WM_SYSKEYUP - 系統鍵彈起,不可能連續出現
WM_KEYDOWN - 普通鍵按下,可能連續出現
WM_KEYUP - 普通鍵彈起,不會連續出現
wParam - 虛鍵碼
lParam - 附加信息,如連續按鍵次數


3.字符消息
WM_CHAR - TranslateMessage 函數針對字符鍵的WM_KEYDOWN消息翻譯所得
wParam - ASCII字符編碼
BOOL TranslateMessage (const MSG* lpMsg) {
if (lpMsg->message != WM_KEYDOWN)
return FALSE;
if (根據lpMsg->wParam虛鍵碼判斷不是字符鍵)
return FALSE;
WPARAM wParam = lpMsg -> wParam;
LPARAM lParam = lpMsg -> lParam;
...
if (CapsLock 未打開)
wParam += 'a' - 'A';
}
PostMessage (lpMsg -> hWnd, WM_CHAR, wParam, lParam);
return TRUE;
}


注意:每按一次字符鍵連續的出現三個消息:
WM_KEYDOWN->WM_CHAR->WM_KEYUP


VK_UP
VK_DOWN
VK_LEFT
VK_RIGHT
MSDN中有宏








四、鼠標消息
1.基本消息
WM_LBUTTONDOWN - 左鍵按下
WM_LBUTTONUP - 左鍵彈起
WM_MBUTTONDOWN - 中鍵按下
WM_MBUTTONUP - 中鍵彈起
WM_RBUTTONDOWN - 右鍵按下
WM_RBUTTONUP - 右鍵彈起
WM_MOUSEMOVE - 移動


wParam - 其他按鍵狀態,以下值得位或
MK_LBUTTON - 左鍵
MK_MBUTTON - 中鍵
MK_RBUTTON - 右鍵
MK_CONTROL - Ctrl鍵
MK_SHIFT - Shift鍵


lParam - 鼠標光標位置,LOWORD水平座標,HIWORD垂直座標


注意:鼠標單擊消息是不會連續出現的。按下消息和彈起消息一定是成對出現的。


2.雙擊消息
WM_LBUTTONDBLCLK - 左鍵雙擊
WM_MBUTTONDBLCLK - 中鍵雙擊
WM_RBUTTONDBLCLK - 右鍵雙擊


wParam - 其他按鍵狀態,以下值得位或
MK_LBUTTON - 左鍵
MK_MBUTTON - 中鍵
MK_RBUTTON - 右鍵
MK_CONTROL - Ctrl鍵
MK_SHIFT - Shift鍵


lParam - 鼠標光標位置,LOWORD水平座標,HIWORD垂直座標


如果窗口類風格中沒有CS_DBLCLKS,那麼這個窗口不會收到鼠標雙擊消息,如果左鍵雙擊
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDOWN
WM_LBUTTONUP
反之,窗口類風格中有CS_DBLCLKS,那麼窗口就可以收到鼠標雙擊消息,如左鍵雙擊
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WMLBUTTONUP


3.滾輪消息
WM_MOUSEWHEEL - 轉動鼠標滾輪
wParam - HIWORD 滾動量(120的整數倍) , LOWORD 按鍵狀態 ()
lParam - 鼠標光標位置,LOWORD水平座標,HIWORD垂直座標
需要告訴編譯器當前操作系統的版本高於NT 4.0, 以使WM_MOUSEWHEEL宏有定義:
在#include <windows.h>之前加上
#define _WIN32_WINNT 0x0400


滾動量有正負之分,表示滾動方向,需要用short類型變量表示.



















































































發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章