Windows桌面开发之消息
应用程序与消息
通常情况下,系统将消息发送给对应窗口的window procedure函数。
这个函数负责处理消息,如果它处理消息的时间过长,则系统认定该应用已经失去响应。
系统会生成一个ghost window,这个窗体能做一些简单的移动、拉伸等操作。
消息分类:
- 系统消息
- 系统生成,例如移动鼠标、按下键盘等等用户行为
- 系统定义的消息一般都以固定的前缀开头
- 例如,常见的系统消息是WM开头,包含了鼠标、键盘、剪贴板、计时器等等最常用的消息
- 应用消息
- 应用程序根据需要自行生成
- 有以下限制
- 0x0000 ~ 0x03FF 系统占用,不可使用
- 应用程序可以在 0x0400 ~ 0x7FFF 中挑选一个数字,然后标记成自定义的消息,进行传播。应用标记4.0,则 0x8000 ~ 0xBFFF范围也可以使用
- 注意这个消息在窗体类私有的,可能多个窗体类
- 使用方法 RegisterWindowMessageA来注册一个消息,返回值位于0xC000 ~ 0xFFFF 作为消息标识符。如果返回0,则注册失败
- 这样是为了防止其他应用程序也使用相同数字作为自己的消息,进行通信,导致进程之间处理错误的消息。
发送消息
系统发送消息时,有两种方式
- Queued Messages
- 系统为每一个GUI线程维护一个单独的消息队列
- 属于这个线程创建的所有窗口的Queued Message(例如:鼠标、键盘)都推送到队列中
- 应用程序不断的循环消息队列,取出消息,并再次发送给特定的窗口
- 系统放置消息的时候一般都是放到队尾
- 提取消息时,遇到WM_PAINT、WM_TIMER、WM_QUIT这三种消息,它们会在队列中暂存,除非再也没有其它消息处理了,原因是为了减少重绘次数,提升性能
- 有以下API可以发送处理消息:
- PeekMessage,仅查看消息
- GetMessage,提取消息
- DispatchMessage,发送给特定窗口的window procedure函数
- PostMessage、PostThreadMessage 把消息发送给其他线程
- 常见的Queued Message
- WM_MOUSEMOVE
- WM_LBUTTONDOWN
- WM_KEYDOWN
- WM_CHAR
- WM_TIMER
- WM_PAINT
- WM_QUIT
- Nonqueued Messages
- WM_ACTIVATE、 WM_SETFOCUS、WM_SETCURSOR
- 直接发送给特定的窗体的 window procedure 处理函数
- 使用以下API发送这类消息
- BroadcastSystemMessage, BroadcastSystemMessageEx
- SendMessage, SendMessageTimeout
- SendNotifyMessage
处理消息
一个window procedure处理消息时,会接收到4个参数
- window handle
- 指明哪个窗体处理此消息
- message identifier
- 消息内容
- message parameters(2个)
- 消息携带的额外数据
处理方法
MSG msg; BOOL bRet; while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) { if (bRet == -1) { // handle the error and possibly exit } else { TranslateMessage(&msg); DispatchMessage(&msg); } }