




已阅读5页,还剩2页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
从SetTimer看Windows消息处理机制 2010-02-09 22:07 909人阅读 评论(0) 收藏 举报 本文说明两个问题:1.windows的消息处理机制;2.怎么往SetTimer的回调函数传递参数。首先看第一个问题,我们都知道 windows是消 息驱动的,windows呈现给用户的任何可以看到听到的东西几乎都是消息驱动的,在底层windows为每个线程准备了一个消息队列,如果用户线程注册 了某个消息,那么在适当的时候windows就会将消息投递到该线程的消息队列中,然后由该线程取出队列中的消息,然后处理之,这个过程有两个参与者,一 个是windows系统,它主要负责投递消息,收不收是用户线程的事,另一个就是用户线程,它主要负责取出消息并处理消息,即使用户线程因为睡眠或者根本 就没有设定消息循环,系统还是会投递的,系统和用户线程的消息接口就是消息队列,这就在用户和系统之间关于消息解除了耦合,在用户线程处理消息的时候,其 实还有一个消息队列,因为一个线程不一定只接收一种消息而且不一定马上就能处理完并返回,这个消息队列我们把它叫做消息分发队列或者简称分发队列用来与系 统的消息队列区分,注意分发队列里面的消息都是已经格式化后的消息,分发给谁呢?当然是分发给消息的回调函数了,对于有窗口的就是先分发给窗口过程,然后 由窗口过程分发给具体的处理函数。下面我们来通过一个例子说明一下,用vs2005或VC建立一个Win32工程,然后看自动生成的代码: int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) . / 主消息循环: while (GetMessage(&msg, NULL, 0, 0) if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg) TranslateMessage(&msg); DispatchMessage(&msg);/msg中按照消息号识别 return (int) msg.wParam;以上就是消息循环,该线程循环接收消息,然后DispatchMessage消息,Dispatch到窗口过程:LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message)/message就是消息号 case WM_COMMAND:. default: return DefWindowProc(hWnd, message, wParam, lParam); return 0;以上实际上就是windows消息机制的全景,对于windows的timer当然也要套用上面的模式了,在SetTimer调用后,实际上就注册了WM_TIMER消息,以下是函数定义:UINT_PTR SetTimer( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);lpTimerFunc就是回调函数,其形式为:VOID CALLBACK TimerProc( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);SetTimer的参数uElapse就是时间间隔,比如设置为1000即1秒,现在有了一个问题,请看下列代码: VOID CALLBACK TimerFunc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime) Sleep(5000);DWORD CALLBACK AutoBakup( PVOID lpParam ) MSG msg; UINT id=SetTimer(NULL,1,1000,TimerFunc); BOOL bRet; while( (bRet = GetMessage(&msg,NULL,0,0)!= 0) ) if(bRet=-1) break; else TranslateMessage(&msg); DispatchMessage(&msg); KillTimer(NULL,id); return 0;竟 然在timer的处理函数中睡眠了,那么SetTimer时的1000毫秒触发一次timer回调还会进行吗?其实不会进行了,本质上那个1000毫秒就 不是说触发回调函数的间隔,而是产生WM_TIMER消息的间隔,因为回调函数中睡眠了,所以也就阻塞了本线程,这个线程就不再往前走了,但是底层的 WM_TIMER消息也会因此而不再投递吗?不会,消息的投递其实不是本线程进行的,而是系统进行的,本线程已经睡眠了,但是系统却没有睡眠,它会继续往 该线程的消息队列投递WM_TIMER消息,只不过这些消息不再由该线程的GetMessage取出了,因为它睡眠了(如果对回调函数是否和 GetMessage是否为统一线程有疑义,那么用GetCurrentThreadId()检测一下就好),消息全部堆积在队列里面,然后等待睡眠结束 后再一个一个处理。好吧,这个问题解决了,下一个问题又来了,试着将回调函数改为下面的: VOID CALLBACK TimerFunc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime) MessageBoxA(NULL,zhaoya,msg,MB_OK); Sleep(5000);发 现完全按照SetTimer时设置的那样,1秒弹出一个消息框,一个一个出来,Sleep好像根本就没有执行,线程根本没有睡眠阻塞,我把 MessageBoxA(NULL,MB_OK)换成printf就不行了,线程立即执行Sleep,这是为何?关键就在 MessageBoxA上,它实际上是一个模态对话框,既然是对话框它就有消息循环,它并没有开独立的线程,因此可以肯定还是原来的线程,原来 MessageBoxA的内部实现了GetMessage-TranslateMessage-DispatchMessage的循 环,由于还是原来的线程,所以它GetMessage将还包括WM_TIMER,另外还有消息框自己的一些关于界面的消息,比如WM_PAINT,消息框 的出现只是在系统中又注册了一些需要的消息,就是消息框的关于界面事件的消息。WM_TIMER回调函数在那,于是调用之,于是又是一个消息框出来了,但 是一旦你点击最上面的OK键,那么程序立即向下进行,进入Sleep,开始睡眠,所有的消息框好像死掉一般,因为就一个线程,它睡眠了,消息循环不再进 行,当然所有消息框的消息循环也不再进行,什么WM_PANIT之类的消息都将阻塞,于是消息框们都和死了一样。通过以上论述,我想关于windows消息大致已经说清了,下面解决第二个问题,如何向SetTimer的回调函数传递自定义参数。再看TimerProc:VOID CALLBACK TimerPro(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime);看 看MSDN关于第三个参数idEvent的解释,就是Timer的id,我们可以用SetTimer的返回值来作为自定义参数的指针,然后在 TimerProc回调函数中通过idEvent取出,强制转换为自己定义的类型,可是SetTimer的返回值并不是我们所能左右的啊,那么还是要从 MSG结构下手了: typedef struct tagMSG / msg HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; MSG;看 看wParam和lParam,MSDN上说是额外参数,我们只需要重新设置值就可以了,于是我们要取wParam和lParam这两个参数与 TimerProc形参的交集,这个交集就是我们可以自定义的参数,经过测试,发现wParam其实就是SetTimer返回的id,也就是 TimerProc的形参idEvent,于是例子如下:VOID CALLBACK TimerFunc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime) char * buf = (char*)idEvent; printf( %s/n, buf );/这里打印的就是abcdeDWORD CALLBACK AutoBakup( PVOID lpParam ) char * buf = abcde; MSG msg; UINT id=SetTimer(NULL,1,1000,TimerFunc); BOOL bRet; while( (bRet = GetMessage(&msg,NULL,0,0)!= 0) ) if(bRet=-1) break; else TranslateMessage(&msg); msg.wParam = (
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 那曲市中储粮2025秋招写作案例分析万能模板直接套用
- 中国联通黄冈市2025秋招网申填写模板含开放题范文
- 萍乡市中石油2025秋招笔试模拟题含答案法律与合规岗
- 三明市中储粮2025秋招面试专业追问题库购销统计岗
- 2025年警犬寻人考试题及答案
- 中国移动阳江市2025秋招笔试行测题库及答案行业解决方案经理岗
- 新疆地区中石化2025秋招面试半结构化模拟题及答案油气储运与管道岗
- 铜仁市中石化2025秋招笔试模拟题含答案炼油工艺技术岗
- 中国移动钦州市2025秋招写作案例分析万能模板直接套用
- 国家能源杭州市2025秋招笔试题库含答案
- 机加工安全生产培训考核试题及答案(班组级)(精)
- 电梯从业证考试试题及答案解析
- 2024年武汉商学院公开招聘辅导员笔试题含答案
- DB32-T 5156-2025 零碳园区建设指南
- 人教版三年级数学上册第一单元分层作业设计
- 2024年国庆中秋安全教育主题班会《欢度双节 安全护航》主题安全教育【课件】
- 浙教版(2024)科学八年级上册 2.1力(第2课时)课件
- 中国外卖大战报告(中英)-高盛-202507
- 咖啡对身体健康的影响研究
- DB32∕T 4569-2023 发泡陶瓷保温板 保温系统应用技术规程
- 2025-2030中国地坪研磨机行业市场发展趋势与前景展望战略研究报告
评论
0/150
提交评论