C++-Windows消息循环GetMessage/TranslateMessage/DispatchMessage[通俗易懂]

C++-Windows消息循环GetMessage/TranslateMessage/DispatchMessage[通俗易懂]1.windows消息循环if(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);//消息转化DispatchMessage(&msg);//消息派遣.把TranslateMessage转换的消息发送到窗口的消息处理函数,此函数在窗口注册时已经指定}执行过程:消息循环调用G…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

1.windows消息循环

if (GetMessage(&msg, NULL, 0, 0)) {
   TranslateMessage(&msg); //消息转化
   DispatchMessage(&msg);  //消息派遣.  把TranslateMessage转换的消息发送到窗口的消息处理函数,此函数在窗口注册时已经指定
  }

执行过程:

  1. 消息循环调用GetMessage()从消息队列中查找消息进行处理,如果消息队列为空,程序将停止执行并等待(程序阻塞)。
  2. 事件发生时导致一个消息加入到消息队列(例如系统注册了一个鼠标点击事件),GetMessage()将返回一个正值,这表明有消息需要被处理,并且消息已经填充到传入的MSG参数中;当传入WM_QUIT消息时返回0;如果返回值为负表明发生了错误。
  3. 取出消息(在Msg变量中)并将其传递给TranslateMessage()函数,这个函数做一些额外的处理:将虚拟键值信息转换为字符信息。这一步实际上是可选的,但有些地方需要用到这一步。
  4. DispatchMessage()函数将消息分发到消息的目标窗口,并且查找目标窗口过程函数,给窗口过程函数传递窗口句柄、消息、wParam、lParam等参数然后调用该函数。
  5. 在窗口过程函数中,检查消息和其他参数,你可以用它来实现你想要的操作。如果不想处理某些特殊的消息,你应该总是调用DefWindowProc()函数,系统将按按默认的方式处理这些消息(通常认为是不做任何操作)。
  6. 一旦一个消息处理完成,窗口过程函数返回,DispatchMessage()函数返回,继续循环处理下一个消息。

2. 函数定义

2.1GetMessage

BOOL WINAPI GetMessage(
 _Out_     LPMSG lpMsg,
 _In_opt_  HWND hWnd,
 _In_      UINT wMsgFilterMin,
 _In_      UINT wMsgFilterMax
);
  • GetMessage 函数的作用是从当前线程的消息队列里获取一个消息并填入 MSG 结构 中。
  • 该函数只能获取调用线程的消息,不能获得其他线程的消息。成功获取消息后,线程将从消息队列中删除该消息。
  • 使用 GetMessage 函数,如果消息队列为空,函数会一直等待直到有消息到来才有返回值。

2.2 TranslateMessage

//BOOL TranslateMessage(CONST MSG *lpMsg);
  • 参数:lpMsg
    指向一个含有用GetMessage或PeekMessage函数从调用线程的消息队列中取得消息信息的MSG结构的指针
  • 函数功能描述:
    将虚拟键消息转换为字符消息。字符消息被送到调用线程的消息队列中,在下一次线程调用函数GetMessage或PeekMessage时被读出。
    TranslateMessage函数不修改由参数lpMsg指向的消息。

2.3 DispatchMessage

函数原型:LONG DispatchMessage(CONST MSG*lpmsg);
  • 参数:
    lpmsg:指向含有消息的MSG结构的指针。

  • 返回值:
    返回值是窗口程序返回的值。尽管返回值的含义依赖于被调度的消息,但返回值通常被忽略。

  • 备注:
    MSG结构必须包含有效的消息值。如果参数lpmsg指向一个WM_TIMER消息,并且WM_TIMER消息的参数IParam不为NULL,则调用IPa1ram指向的函数,而不是调用窗口程序。

3. 程序实例

  • 如果处理时间大于定时器时间,按照处理时间循环。
  • 如果处理时间小于定时器时间,按照定时器时间。
#pragma comment(lib,"user32")
#include <stdio.h>
#include <time.h>
#include <sys/timeb.h>
#include <windows.h>
char datestr[16];
char timestr[16];
char mss[4];
void log(char *s) { 
   
 struct tm *now;
 struct timeb tb;
 ftime(&tb);
 now = localtime(&tb.time);
 sprintf(datestr, "%04d-%02d-%02d", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday);
 sprintf(timestr, "%02d:%02d:%02d", now->tm_hour, now->tm_min, now->tm_sec);
 sprintf(mss, "%03d", tb.millitm);
 printf("%s %s.%s %s", datestr, timestr, mss, s);
}
VOID CALLBACK myTimerProc1(
 HWND hwnd, // handle of window for timer messages
 UINT uMsg, // WM_TIMER message ************
 UINT idEvent, // timer identifier
 DWORD dwTime // current system time)
 { 
   
 log("In myTimerProc1\n");
}
VOID CALLBACK myTimerProc2(
 HWND hwnd, // handle of window for timer messages
 UINT uMsg, // WM_TIMER message
 UINT idEvent, // timer identifier
 DWORD dwTime // current system time) 
 { 
   
 log("In myTimerProc2\n");
}

int main() 
{ 
   
 MSG msg;
 SetTimer(NULL, 0, 4000, myTimerProc1);
 SetTimer(NULL, 1, 2000, myTimerProc2);
 for (int i = 0; i<20; i++) 
 { 
   
  Sleep(1000);
  log("In main\n");
  if (GetMessage(&msg, NULL, 0, 0)) 
  { 
   
   TranslateMessage(&msg); //消息处理
   DispatchMessage(&msg);  //消息派遣. 把TranslateMessage转换的消息发送到窗口的消息处理函数,此函数在窗口注册时已经指定
 }
 }
  return 0;
}
2019-12-06 21:10:24.633 In main
2019-12-06 21:10:25.618 In myTimerProc2
2019-12-06 21:10:26.619 In main
2019-12-06 21:10:27.620 In myTimerProc1
2019-12-06 21:10:28.621 In main
2019-12-06 21:10:28.621 In myTimerProc2
2019-12-06 21:10:29.623 In main
2019-12-06 21:10:29.624 In myTimerProc2
2019-12-06 21:10:30.625 In main
2019-12-06 21:10:31.623 In myTimerProc1
2019-12-06 21:10:32.624 In main
2019-12-06 21:10:32.624 In myTimerProc2
2019-12-06 21:10:33.626 In main
2019-12-06 21:10:33.626 In myTimerProc2
2019-12-06 21:10:34.628 In main
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/194513.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 7种方法求解八数码问题

    【八数码问题】//https://vijos.org/p/1360在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。【分析】题目读完第一感

    2022年4月5日
    164
  • android之如何在两个activity之间传递handler_利用broadcast广播机制「建议收藏」

    这算是如何在两个activity之间传递handler的解决方案二了,解决方案一见http://blog.csdn.net/jason0539/article/details/18055259再重复一遍我遇到的问题,就是在MainActivity里面打开AnotherActivity去执行一些操作,相应的改变MainActivity里的一些布局或者执行一些动作,最开始想到的就是把MainAct

    2022年3月11日
    53
  • Facebook时序预测工具Prophet实战分析

    Facebook时序预测工具Prophet实战分析引言去年Facebook开源了一套时序预测工具叫做Prophet。Prophet是一个预测时间序列数据的模型。它基于一个自加性模型,用来拟合年、周、季节以及假期等非线性趋势。它在至少有一年历史数据的日常周期性数据,效果最好。Prophet对缺失值,趋势的转变和大量的异常值是有极强的鲁棒性。Prophet中文翻译是:“先知”。名字还是挺贴切的。在看完本篇文章后,你将会知道:

    2022年6月29日
    29
  • 哈希表、哈希冲突

    哈希表、哈希冲突哈希表1.哈希表是一种以键值key存储数据value的结构,以key作为标识值存储value值;只要输入待查找的key,即可获取其对应的value值。当按照键值查询元素时,使用相同的hash函数将key转换为数组下标,从数组中按照下标对应的位置获取数据。它实际上是数组的一种扩展,数组+链表+红黑树。2.哈希表的设计哈希函数的设计首先不能过于复杂,复杂的哈希函数会间接的影响hash表的性能;其次要求哈希值应该尽可能随机且均匀分布,避免或者减少哈希冲突的数量,使每个桶中存储的数据比较平均。常规的设计方法

    2022年6月21日
    31
  • idea构建springboot_钉钉的使用方法和技巧

    idea构建springboot_钉钉的使用方法和技巧随着技术框架的不断更新,一些公司摒弃了原先的技术框架模式。而springboot慢慢取代了原有的ssm框架开发。为什么选择springboot呢?配置简单不需要编写太多的xml; 基于spring构建,容易上手; 独立运行不依赖于容器; 内置服务器tomcat不需要打war包; 提供maven极简配置; 对于各种框架有很好的集成; 为SpringCloud微服务奠定基础,使微服务构建变得简单;下面让我们使用idea一起搭建完整版的SpringBoot项目:一.创建SpringBoot项

    2025年8月29日
    8
  • 移动端开发之Web App开发

    移动端开发之Web App开发写在前面:本人刚刚接触移动端开发,希望自己的见解能够帮助到他人,不足之处还望提醒。1移动端开发分类1.1NativeApp原生App开发优点:(1)用户体验好(2)性能稳定(3)操作速度快(4)能够访问本地资源(通讯录,相册)(5)能够设计出色的动效,转场(6)拥有系统级别的贴心通知或提醒(7)用户留存率高缺点:(1)开发成本高(2)维护成本高(3)更新缓慢,根据不同平台,提交–审核–上线…

    2022年6月17日
    31

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号