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类型变量表示.



















































































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