[ATL/WTL]_[初级]_[Windows消息循环初解]
来源:互联网 发布:知乐百度网盘 编辑:程序博客网 时间:2024/04/30 16:54
Windows 消息循环初解
场景
- Win32窗口编程, 肯定涉及到消息循环. Win32编程基本就是通过处理消息来处理系统任务, 所以Win32窗口编程, 弄懂消息循环是必然的.
说明
1.对于GUI线程,Win32消息循环使用两个队列来来存储消息, 一个是系统消息队列, 一个线程指定的队列. 消息队列是fifo的队列.
The system maintains a single system message queue and one thread-specific message queue for each GUI thread.
2.系统在创建线程时不会自动创建一个消息队列, 因为这样会浪费资源,并不是每个线程都需要响应系统消息的. 只有用户执行了一个需要消息队列的操作时系统才会创建消息队列. 比如GetMessage(),PeekMessage().
The system does not automatically create a message queue for each thread. Instead, the system creates a message queue only for threads that perform operations which require a message queue.
3.线程指定的消息循环是自己创建的, 消息队列是系统创建的, 一般的格式如下.
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); }}
4.PostMessage 会发送一个消息到消息队列末尾,并立即返回.
PostMessage places a message at the end of a thread's message queue and returns immediately, without waiting for the thread to process the message.
5.SendMessage 发送消息MSDN没说是发送到队列末尾, 但应该不会违反规则. SendMessage 发送消息到队列末尾并等待消息循环执行完消息才返回. 窗口过程仍旧是在GUI线程里执行,不是在其他线程里执行.
The SendMessage function is used to send a message directly to a window procedure. SendMessage calls a window procedure and waits for that procedure to process the message and return a result.
6.注意, 线程指定的消息循环不一定需要创建窗口. 我们也可以利用线程消息循环来处理非窗口任务, 看以下例子, 可以使用线程指定内置的消息队列来线程安全的执行消息任务. 这样就不需要自己写临界区或加锁在queue上了.
// test_message_loop1.cpp : 定义应用程序的入口点。//#include "stdafx.h"#include <windows.h> #include <assert.h>#include <iostream>#include "test_message_loop1.h"int PressAnyKey( const wchar_t *prompt ) { DWORD mode; HANDLE hstdin; INPUT_RECORD inrec; DWORD count; wchar_t default_prompt[] = L"Press a key to continue...\n"; /* Set the console mode to no-echo, raw input, */ /* and no window or mouse events. */ hstdin = GetStdHandle( STD_INPUT_HANDLE ); if (hstdin == INVALID_HANDLE_VALUE || !GetConsoleMode( hstdin, &mode ) || !SetConsoleMode( hstdin, 0 )) return 0; if (!prompt) prompt = default_prompt; /* Instruct the user */ WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), prompt, lstrlen( prompt ), &count, NULL ); FlushConsoleInputBuffer( hstdin ); /* Get a single key RELEASE */ do ReadConsoleInput( hstdin, &inrec, 1, &count ); while ((inrec.EventType != KEY_EVENT) || inrec.Event.KeyEvent.bKeyDown); /* Restore the original console mode */ SetConsoleMode( hstdin, mode ); return inrec.Event.KeyEvent.uChar.AsciiChar; } typedef enum MyMessage1{ kMessageCopyFile = WM_USER+100}MyMessage;DWORD WINAPI StartThread(void* data){ MSG msg; BOOL bRet; std::cout << "StartThread: " << ::GetCurrentThreadId() << std::endl; while( (bRet = GetMessage( &msg, (HWND)-1, 0, 0 )) != 0) { std::cout << "GetMessage: " << msg.message << " ThreadID: " << ::GetCurrentThreadId() << " wParam: " << msg.wParam << " lParam: " << msg.lParam << std::endl; Sleep(2000); if (bRet == -1) { // handle the error and possibly exit } else { //TranslateMessage(&msg); //DispatchMessage(&msg); } } std::cout << "StartThread END: " << ::GetCurrentThreadId() << std::endl; return 0;}class A{public: virtual ~A(){std::cout << "~A" << std::endl;}};class B : public A{public: ~B(){std::cout << "~B" << std::endl;}};int main(int argv,char* args[]){ std::cout << "main: " << ::GetCurrentThreadId() << std::endl; DWORD IDThread; HANDLE h1 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) StartThread,NULL,0,&IDThread); assert(h1); DWORD IDThread2; HANDLE h2 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) StartThread,NULL,0,&IDThread2); assert(h2); int code = 0; while((code = PressAnyKey(NULL))!= 'q') { std::cout << code << std::endl; if(code == 'c') { PostThreadMessage(IDThread,WM_QUIT,8,9); PostThreadMessage(IDThread2,WM_QUIT,8,9); }else { PostThreadMessage(IDThread,kMessageCopyFile,8,9); PostThreadMessage(IDThread2,kMessageCopyFile,8,9); } } return 0;}
参考
About Messages and Message Queues
Using Messages and Message Queues
0 0
- [ATL/WTL]_[初级]_[Windows消息循环初解]
- [ATL/WTL]_[初级]_[环境搭建]
- [ATL/WTL]_[初级]_[转发消息让CStatic支持点击消息操作]
- [ATL/WTL]_[初级]_[Win32窗口自定义消息处理过程]
- [ATL/WTL]_[初级]_[SDI程序关闭的注意事项]
- [ATL/WTL]_[初级]_[常用的界面对象操作]
- [ATL/WTL]_[初级]_[拖放文件到窗口]
- [ATL/WTL]_[初级]_[选择目录对话框]
- [ATL/WTL]_[初级]_[Win32实现Cocoa的dispatch_async到主线程的异步消息处理]
- [ATL/WTL]_[初级]_[CBitmap复制图片-截取图片-平铺图片]
- [ATL/WTL]_[初级]_[窗口如何实现WM_MOUSELEAVE和WM_MOUSEHOVER]
- [ATL/WTL]_[初级]_[关于CEdit不识别WM_KEYDOWN的问题]
- [ATL/WTL]_[初级]_[关于graphics.DrawImage绘图时显示不正常的问题]
- [ATL/WTL]_[初级]_[如何使用GetOpenFileName多选文件-根据文件名长度计算lpstrFile长度]
- Programming Windows (三)_ 消息循环
- [ATL/WTL]_[中级]_[保存CBitmap到文件-保存屏幕内容到文件]
- [ATL/WTL]_[中级]_[使用GDIPlus剪切和缩放图片]
- ATL/WTL消息响应函数原型
- Eclipse +Tomcat配置JNDI数据源
- Android 中门磁自动警报实例总结。。。。
- abap 知识点总结
- Acperience
- 【nyoj 1291 ABS 】
- [ATL/WTL]_[初级]_[Windows消息循环初解]
- osgearth学习之一 类库介绍
- oracle分区表详解
- 安装oracle11版本报错此先决条件将测试系统物理内存总量是否至少为 922MB
- idea15注册码
- JVM垃圾收集算法
- CSS:加边框内容收缩解决
- POJ-1019 Number Sequence
- 软件测试人员必备Linux命令(初、中、高级)