http://blog.csdn.net/linlingzhao/article/details/7517951

由 arain 于 星期二, 11/02/2010 - 10:44 发表

MSG message ;

if (::PeekMessage(&message ,NULL , 0, 0 ,PM_REMOVE))

{

::TranslateMessage(&message);  //把键盘消息翻译成字符消息

::DispatchMessage(&message);  //通过窗口类把控制交给MFC消息处理器

}

PeekMessage (&msg, NULL, 0, 0, PM_REMOVE) ;

前面的四个参数(一个指向MSG结构的指针、一个窗口句柄、两个值指示消息范围)与GetMessage的参数相同。将第二、三、四个参数设定为NULL或0时,表明我们想让PeekMessage传回程序中所有窗口的所有消息。如果要将消息从消息队列中删除,则将PeekMessage的最后一个参数设定为PM_REMOVE。如果您不希望删除消息,那么您可以将这个参数设定为PM_NOREMOVE。它使得程序可以检查程序的队列中的下一个消息,而不实际删除它。

GetMessage不将控制传回给程序,直到从程序的消息队列中取得消息,但是PeekMessage总是立刻传回,而不论一个消息是否出现。当消息队列中有一个消息时,PeekMessage的传回值为TRUE(非0),并且将按通常方式处理消息。当队列中没有消息时,PeekMessage传回FALSE(0)。

这使得我们可以改写普通的消息循环。我们可以将如下所示的循环:

while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

return msg.wParam ;

替换为下面的循环:

while (TRUE)

{

if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))

{

if (msg.message == WM_QUIT)

break ;

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

else

{

// 完成某些工作的其它行程序

}

}

return msg.wParam ;

注意,WM_QUIT消息被另外挑出来检查。在普通的消息循环中您不必这么作,因为如果GetMessage接收到一个WM_QUIT消息,它将传回0,但是PeekMessage用它的传回值来指示是否得到一个消息,所以需要对WM_QUIT进行检查。

如果PeekMessage的传回值为TRUE,则消息按通常方式进行处理。如果传回值为FALSE,则在将控制传回给Windows之前,还可以作一点工作(如显示另一个随机矩形)。

(尽管Windows文件上说,您不能用PeekMessage从消息队列中删除WM_PAINT消息,但是这并不是什么大不了的问题。毕竟,GetMessage并不从消息队列中删除WM_PAINT消息。从队列中删除WM_PAINT消息的唯一方法是令窗口显示区域的失效区域变得有效,这可以用ValidateRect和ValidateRgn或者BeginPaint和EndPaint对来完成。如果您在使用PeekMessage从队列中取出WM_PAINT消息后,同平常一样处理它,那么就不会有问题了。所不能作的是使用如下所示的程序代码来清除消息队列中的所有消息:

while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) ;

这行叙述从消息队列中删除WM_PAINT之外的所有消息。如果队列中有一个WM_PAINT消息,程序就会永远地陷在while循环中。)

另外补充:

peekMessage:

函数功能:该函数为一个消息检查线程消息队列,并将该消息(如果存在)放于指定的结构。
  
函数原型:BOOL PeekMessage(LPMSG IpMsg,HWND hWnd,UINT wMSGfilterMin,UINT wMsgFilterMax,UINT wRemoveMsg);

参数:

lpMsg:接收消息信息的MSG结构指针。
  
  hWnd:其消息被检查的窗口的句柄。
  
  wMsgFilterMin:指定被检查的消息范围里的第一个消息。
  
  wMsgFilterMax:指定被检查的消息范围里的最后一个消息。
  
  wRemoveMsg:确定消息如何被处理。此参数可取下列值之一:
  
  PM_NOREMOVE:PeekMessage处理后,消息不从队列里除掉。
  
  PM_REMOVE:PeekMessage处理后,消息从队列里除掉。
  
  可将PM_NOYIELD随意组合到PM_NOREMOVE或PM_REMOVE。此标志使系统不释放等待调用程序空闲的线程。
  
  缺省地,处理所有类型的消息。若只处理某些消息,指定一个或多个下列值:
  
  PM_QS_INPUT:Windows NT5.0和Windows 98:处理鼠标和键盘消息。
  
  PM_QS_PAINT:Windows NT 5.0和Windows 98:处理画图消息。
  
  PM_QS_POSTMESSAGE:Windows NT 5.0和Windows 98:处理所有被寄送的消息,包括计时器和热键。
  
  PM_QS_SENDMESSAGE:Windows NT 5.0和Windows 98:处理所有发送消息。
  
  返回值:如果消息可得到,返回非零值;如果没有消息可得到,返回值是零。
  
  备注:和函数GetMessage不一样的是,函数PeekMesssge在返回前不等待消息被放到队列里。
PeekMesssge只得到那些与参数hWnd标识的窗口相联系的消息或被lsChild确定为其子窗口相联系的消息,并且该消息要在由参数wMsgFiterMin和wMsgFiherMax确定的范围内。如果hWnd为NULL,则PeekMessage接收属于当前调用线程的窗口的消息(PeekMessage不接收属于其他线程的窗口的消息)。如果hWnd为C1,PeekMessage只返回hWnd值为NULL的消息,该消息由函数PostThreadMessage寄送。如果wMsgFilterMin和wMsgFilterMax都为零,GetMessage返回所有可得的消息(即,无范围过滤)。
  
  常数WM_KEYFIRST和WMKEYLAST可作为过滤值取得所有键盘消息;常数WM_MOUSEFIRST和WM_MOUSELAST可用来接收所有的鼠标消息。
  
  PeekMessage通常不从队列里清除WM_PANT消息。该消息将保留在队列里直到处理完毕。但如果WM_PAINT消息有一个空更新区,PeekMessage将从队列里清除WM_PAINT消息。
  
  Windows CE:有一个NULL更新区的WM_PAINT消息不从队列里清除。

TranslateMessage函数

TranslateMessage是用来把虚拟键消息转换为字符消息。由于Windows对所有键盘编码都是采用虚拟键的定义,这样当按键按下时,并不得字符消息,需要键盘映射转换为字符的消息。
TranslateMessage函数用于将虚拟键消息转换为字符消息。字符消息被投递到调用线程的消息队列中,当下一次调用GetMessage函数时被取出。当我们敲击键盘上的某个字符键时,系统将产生WM_KEYDOWN和WM_KEYUP消息。这两个消息的附加参数(wParam和lParam)包含的是虚拟键代码和扫描码等信息,而我们在程序中往往需要得到某个字符的ASCII码,TranslateMessage这个函数就可以将WM_KEYDOWN和WM_ KEYUP消息的组合转换为一条WM_CHAR消息(该消息的wParam附加参数包含了字符的ASCII码),并将转换后的新消息投递到调用线程的消息队列中。注意,TranslateMessage函数并不会修改原有的消息,它只是产生新的消息并投递到消息队列中。
也就是说TranslateMessage会发现消息里是否有字符键的消息,如果有字符键的消息,就会产生WM_CHAR消息,如果没有就会产生什么消息。

函数TranslateMessage声明如下:
WINUSERAPI
BOOL
WINAPI
TranslateMessage(
__in CONST MSG *lpMsg);
lpMsg是检查需要转换的消息。

DispatchMessage函数

前面已经介绍从系统队列里获取一条消息,然后经过快捷键的函数检查,又通过字符消息函数的转换,最后要做的事情就是调用DispatchMessage函数,它的意思就是说要把这条消息发送到窗口里的消息处理函数WindowProc。

函数DispatchMessage声明如下:
WINUSERAPI
LRESULT
WINAPI
DispatchMessageA(
__in CONST MSG *lpMsg);
WINUSERAPI
LRESULT
WINAPI
DispatchMessageW(
__in CONST MSG *lpMsg);
#ifdef UNICODE
#define DispatchMessage DispatchMessageW
#else
#define DispatchMessage DispatchMessageA
#endif // !UNICODE

lpMsg是指向想向消息处理函数WindowProc发送的消息。

调用这个函数的例子如下:

//主程序入口
//
// 蔡军生 2007/07/19
// QQ: 9073204
//
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

//
MSG msg;
HACCEL hAccelTable;

// 加载全局字符串。
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TESTWIN, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// 应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTWIN));

// 消息循环:
BOOL bRet;
while ( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
//处理出错。

}
else if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

return (int) msg.wParam;
}

MFC 消息处理 PeekMessage TranslateMessage DispatchMessage相关推荐

  1. PostMessage,SendMessage,GetMessage,PeekMessage,TranslateMessage,DispatchMessage的用法集合

    SendMessage函数功能描述:将指定的消息发送到一个或多个窗口.此函数为指定的窗口调用窗口过程,直到窗口过程处理完消息后才返回. Postmessage函数则是将消息放入消息队列里,并立即返回. ...

  2. MFC消息处理时,双击鼠标左键响应单击左键消息的处理

    今天做老师留下来的作业题,莫名其妙出现Bug,然后发现是MFC消息处理机制的问题,在响应鼠标双击前,会先产生一个单击鼠标消息,这里是我的解决方法. 单击响应: void CMouseView::OnL ...

  3. Windows API一日一练(10-12)GetMessage TranslateMessage DispatchMessage函数

    主目录传送门 https://blog.csdn.net/zb774095236/article/details/108291755 本次学习的源码模板下载: 1.https://pan.baidu. ...

  4. GetMessage TranslateMessage DispatchMessage 和PeekMessage

    文章目录 GetMessage 函数功能 函数声明 第一个参数 第二个参数 第三个参数 第四个参数 返回值 补充: TranslateMessage 函数功能 函数声明 第一个参数: 返回值 补充 D ...

  5. MFC中的TranslateMessage和DispatchMessage

    TranslateMessage(msg):是将虚拟键消息(比如键盘消息)转化为字符消息,如果没有虚拟键消息则不做处理. DispatchMessage(msg):msg中存的有窗口句柄,该函数会把消 ...

  6. MFC消息处理学习总结

    Windows消息机制概述 http://www.cppblog.com/suiaiguo/archive/2009/07/18/90412.html 消息是指什么?      消息系统对于一个win ...

  7. win32——消息循环 原理 函数 GetMessage PeekMessage TranslateMessage SendMessage PostMessage...

    //消息循环 MSG 结构体 typedef struct tagMSG {HWND hwnd;UINT message; //消息ID WPARAM wParam;LPARAM lParam;DWO ...

  8. C++-Windows消息循环GetMessage/TranslateMessage/DispatchMessage

    1.windows消息循环 if (GetMessage(&msg, NULL, 0, 0)) {TranslateMessage(&msg); //消息转化DispatchMessa ...

  9. 【MFC】PeekMessage() 与GetMessage() 消息函数

    01.目录 目录 01.目录 02.简言 03.PeekMessage() Function 3.1 语法(Syntax) 3.2 参数(Parameters) 3.3 返回值(Return valu ...

最新文章

  1. CentOS7(64位)安装Jupyter Notebook
  2. spring之旅第四篇-注解配置详解
  3. 仓鼠体重年龄对照表_一文带你走进仓鼠世界:仓鼠种类之叙利亚仓鼠(上)
  4. dnf用虚拟机会被制裁吗_DNF: 神豪奶妈扬言, 战斗力没有超过他的, 都不配被加buff!...
  5. jsp获得文件的绝对路径
  6. linux下软件发布,Linux Kernel 5.12发布下载,附新特性及新功能介绍
  7. 年薪35W+ 的程序员看过来!百万架构师第3期招生
  8. linux-vim编辑器简览
  9. 【项目调研+论文阅读】基于BERT的中文命名实体识别方法[J] | day6
  10. Deep Learning基础--Softmax求导过程
  11. springboot项目实例_Springboot项目的接口防刷的实例
  12. C#自定义控件七水波纹
  13. linux进入vi永久显示行数,mac/linux中vim永久显示行号、开启语法高亮
  14. 安装pkgconfig_一个R包怎么也安装不上,憋着急!
  15. ASP.NET自定义控件组件开发
  16. [算法模板]高斯消元
  17. 【创建型】Prototype模式
  18. gets函数没有输入会怎样_如果没有“227事件”,肖战的未来会是怎样的?
  19. Qt实现简单的密码加密
  20. 21世纪将淘汰的八种人

热门文章

  1. python 去重去除重复数组
  2. 跑酷类游戏实现背景无限循环
  3. Laravel Mix 4升级说明与“排坑儿”指南
  4. canvas画边框不一样的矩形
  5. 51单片机LED 1秒闪烁
  6. 企业工厂使用MES系统有哪些先进性的体现和表现在哪些方面?
  7. 微信小程序使用wx.redirectTo跳转页面时出现小房子图标解决方法
  8. navicat 怎么调试存储过程_mysql如何调试存储过程
  9. 【信号与系统homework】信号与系统学习与实践指导1
  10. 超详细的周杰伦演唱会观看攻略,拿走不谢!