day04

来源:互联网 发布:手机游戏优化工具 编辑:程序博客网 时间:2024/04/29 23:57
1)GetMessage 函数负责从消息队列中得到消息,并将其内容填入msg结构体
BOOL GetMessage (
LPMSG lpMsg,//消息结构
HWND hWnd,//窗口句柄,若非NULL则只获取特定窗口消息
UINT uMsgFilterMin,\
>若非0,则获取两个数字之间的消息
UINT uMsgFilterMax/
);
收到WM_QUIT消息返回FALSE,收到其他的消息返回TRUE
case WM_DESTROY:
PostQuitMessage (0);
return 0;
PostQuitMessage 函数在消息队列放入一个WM_QUIT消息.
2)TranslateMessage 函数负责对部分消息(与可见字符相关,键盘消息)进行翻译
BOOL TranslateMessage (
const MSG* lpMsg//消息结构
);
如果消息被翻译了返回TRUE,否则返回FALSE
根据CapsLock键的状态判断大小写
3)DispatchMessage 派发消息
LONG DispatchMessage (const MSG* lpmsg) 
{
根据lpmsg->hWnd获取相应的窗口类;
从窗口类的lpfnWndProc成员确定窗口过程函数的地址;
return lpMsg->hWnd.窗口过程函数(lpMsg->hWnd, lpMsg->uMsg, lpMsg->wParam, lpMsg->lParam);
}
4)一旦GetMessage函数从消息队列中取到WM_QUIT消息即返回FALSE,消息循环结束,线程终止。
----------------------------------------------------------------
一、消息处理
1.每个窗口必须具有窗口过程函数
LPRESULT CALLBACK WindowProc (
HWND hWnd,//窗口句柄
UINT uMsg,//消息标识
WPARAM wParam, //消息参数
LPARAM lParam //消息参数
);
窗口过程函数负责对消息做具体处理
2.窗口过程函数除了被DispatchMessage 函数调用以外,也可以被其他API函数调用,因此需要重入.
3.窗口过程函数并不需要处理所有的消息,对于应用程序不感兴趣的消息直接交给缺省窗口过程函数处理即可
LRESULT CALLBACKDefWindowProc (
HWND hWnd,//窗口句柄
UINT uMsg,//消息标识
WPARAM wParam, //消息参数
LPARAM lParam //消息参数
);
窗口过程函数基本范式:
LPRESULT CALLBACK MyWindowProc (
HWND hWnd,//窗口句柄
UINT uMsg,//消息标识
WPARAM wParam, //消息参数
LPARAM lParam //消息参数
)
{
switch (uMsg) {
case WM_XXX:
处理WM_XXX消息
return 0;
}
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}


二、常见消息
1.WM_DESTROY - 窗口被销毁时受到次罅隙,无参数。常用于在窗口销毁之前释放动态分配的资源,发送WM_QUIT消息结束消息循环.
点击窗口关闭按钮 -> WM_SYSCOMMAND(wParam == SC_CLOSE) -> DefWindowProc () ->
CloseWindow () -> WM_CLOSE -> DefWindowProc () -> DestroyWindow ()
-> WM_DESTROY
2.WM_SYSCONMAND - 系统命令消息,当点击窗口的最大化,最小化,关闭等按钮时受到此消息,可以根据wParam的不同取值判断点击的不同按钮.
wParam - 具体命令,如SC_CLOSE等
lParam - 鼠标位置,LOWORD水平位置,HIWORD垂直位置。
3.WM_CREATE - 在CreateWindow/CreateWindowEx函数执行过程中,受到此消息,只有在处理该消息的窗口过程函数返回以后CreateWindow/CreateWindowEx函数才返回。常用语初始化窗口状态、分配资源,创建子窗口.
wParam - 没用.
lParam  - CREATESTRUCT结构体指针,保存了调用CreateWindow/CreateWindowEx函数所传递的参数
这个消息返回-1失败返回0表示成功。
利用CREATESTRUCT结构体的lpCreateParams成员可以向窗口过程函数WM_CREATE消息处理代码传递自定义的初始化数据.
若窗口过程函数在WM_CREATE消息的处理过程中发生错误,则可以return -1,以使CreateWindow/CreateWindowEx函数执行失败,返回NULL
4.WM_SIZE - 当窗口的大小发生变化时,收到此消息。
常用于调整窗口的显示或子控件的布局。
wParam - 窗口大小变化的原因。
lParam - 变化后客户区的大小。LOWORD宽度、HIWORD高度
5.WM_QUIT - 用于结束消息循环
wParam - PostQuitMessage 函数的参数,退出码
6.其他消息
WM_PAINT - 绘图消息
WM_KEYDOWN - 按键消息
WM_MOUSEMOVE - 鼠标移动消息
WM_TIMER - 定时器消息
......
三、获取消息和查看消息
1.获取消息GetMessage
一旦通过GetMessage从消息队列中获取了某个消息,则该消息即从消息队列中消失。如果消息队列中没有符合条件消息,则该函数会阻塞。
2.查看消息:PeekMessage
以查看的方式从消息队列中获取消息,可以只看不拿。非阻塞函数。
如果符合条件的消息,该函数会返回TRUE,否则返回FALSE。
BOOL PeekMessage (
LPMSG lpMsg,//消息结构
HWND hWnd,//窗口句柄
UINT wMsgFilterMin,
UINT wMsgFilterMax
UINT wRemoveMsg//PM_NOREMOVE 不取走消息//PM_REMOVE 取走
);


消息循环1:
MSG msg = {0};
for (;;)
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
{
if (msg.message == WM_QUIT) break;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
else
{
空闲处理;
}




消息循环2:
MSG msg = {0};
for (;;)
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) {
{
if (! Getmessage (&msg, NULL, 0, 0) ) break;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
else
{
空闲处理;
}


四、发送消息和投递消息
1.发送消息:SendMessage
不将消息放入消息队列,而是直接以消息为参数去调用相应的窗口过程函数
LRESUTL SendMessage (
HWND hWnd,//窗口句柄
UINT uMsg,//消息标识
WPARAM wParam, //消息参数
LPARAM lParam //消息参数
);
返回窗口过程函数的返回值
避免下面这样使用该函数:
case WM_XXX
SendMessage (hWnd, WM_XXX, 0, 0);
2.投递消息
将消息放入消息队列即返回.
BOOL PostMessage (
HWND hWnd,//窗口句柄
UINT uMsg,//消息标识
WPARAM wParam, //消息参数
LPARAM lParam //消息参数
);
成功返回TRUE,失败返回FALSE。


case WM_A :
对A的处理;
return 0;
case WM_B:
对B的处理;
return 0;




case WM_MAN:
DrawMan ();
reutrn 0;
case WM_FAMILY:
DrawWoman ();
SendMessage (hWnd, WM_MAN, 0, 0);
DrawChild ();
return 0;


对于需要立即处理的消息使用SendMessage发送,而对于不需要立即处理的消息最好使用PostMessage投递。
五、消息分类
1.系统消息:0x0000 - 0x03FF
由系统定义的消息,可以在程序中直接使用。
2.用户消息:0x0400(WM_USER) - 0x7FFF
由用户定义的消息,自己发出自己处理。
#define WM_EATWM_USER+1
#define WM_SLEEPWM_USER+2


3.应用程序消息: 0x8000(WM_APP) - 0xBFFF
用于应用程序间通信.
#define WM_WROKWM_APP+1
#define WM_RESTWM_APP+2
4.系统注册消息: 0xC000 - 0xFFFF
在系统中注册并生成相应消息,然后在应用程序中使用该消息。
六、消息队列
消息队列是用于存放消息的队列型容器.消息在队列中先进先出(FIFO),所有的窗口程序都有消息队列,每个线程最多有一个消息队列。
系统消息队列: 由系统维护的消息队列,存放系统产生的消息。如鼠标、键盘等。
程序消息队列: 属于每一个线程的消息队列,由线程自己维护。
消息队列关系: 
A.当鼠标、键盘产生消息时,操作系统将此消息放入系统消息队列;
B.操作系统根据系统消息队列中每个消息的具体信息,找到相应窗口所属于的进程。
C.将该消息投递到程序消息队列中。
七、队列消息与非队列消息
1.队列消息:消息发送后首先进入消息队列,然后通过消息循环,从消息队列中获取。
GetMessage() <- 程序消息队列
PeekMessage () <- 程序消息队列
PostMessage () <- 系统消息队列
2.非队列消息:消息发送后,不经过消息队列,直接调用敞口过程函数
SendMessage() -> 窗口过程函数
3.诸如WM_PAINT、键盘、鼠标、定时器等对于顺序性、及时性要求较低的消息,常被处理为队列消息。
诸如WM_CREATE、WM_SIZE等对于及时性要求较高的消息,常被处理为非消息队列消息.












































































0 0
原创粉丝点击