MFC消息处理[转]

2023-05-16

PreTranslateMessage作用和使用方法

  PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用,当需要在MFC之前处理某些消息时,常常要在这里添加代码.  

        MFC消息控制流最具特色的地方是CWnd类的虚拟函数PreTranslateMessage(),通过重载这个函数,可以改变MFC的消息控制流程,甚至可以作一个全新的控制流出来。 只有穿过消息队列的消息才受PreTranslateMessage()影响,采用SendMessage()或其他类似的方式向窗口直接发送的而不经过消息队列的消息根本不会理睬PreTranslateMessage()的存在。 
 
       是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,如果该函数返回TRUE,则不会把该消息分发给窗口函数处理。
    传给PreTranslateMessage()的消息是未经翻译过的消息,它没有经过TranslateMessage()处理。可以在该函数中使用(pMsg->wParam==VK_RETURN)来拦截回车键。 wParam中存放的是键盘上字符的虚拟码。

PeekMessage和GetMessage的区别:

GetMessage在没有消息的时候等待消息,cpu当然低

PeekMessage没有消息的时候立刻返回,所以cpu占用率高。

因为游戏不能靠windows消息驱动,所以要用PeekMessage();

     PretranslateMessage的实现,不得不谈到MFC消息循环的实现。MFC通过CWinApp类中的Pumpmessage函数实现消息循环,但是实际的消息循环代码位于CWinThread中, CWinApp只是从CWinThread继承过来。其简化后的代码大概如下:
  BOOL CWinThread::PumpMessage()
  {
  _AFX_THREAD_STATE *pState = AfxGetThreadState();
  
  ::GetMessage(&(pState->m_msgCur), NULL, NULL, NULL))
  
  if (!AfxPreTranslateMessage(&(pState->m_msgCur)))
  {
  ::TranslateMessage(&(pState->m_msgCur));
  ::DispatchMessage(&(pState->m_msgCur));
  }
  return TRUE;
  }
  可以看到,PumpMessage在实际的TranslateMessage和DispatchMessage发生之前会调用AfxPreTranslateMessage,AfxPreTranslateMessage又会调用CWnd::WalkPreTranslateTree(虽然也会调用其他函数,但是这个最为关键),其代码如下:
  BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
  {
  ASSERT(hWndStop == NULL || ::IsWindow(hWndStop));
  ASSERT(pMsg != NULL);
  
  // walk from the target window up to the hWndStop window checking
  // if any window wants to translate this message
  
  for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
  {
  CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
  if (pWnd != NULL)
  {
  // target window is a C window
  if (pWnd->PreTranslateMessage(pMsg))
  return TRUE; // trapped by target window (eg: accelerators)
  }
  
  // got to hWndStop window without interest
  if (hWnd == hWndStop)
  break;
  }
  return FALSE; // no special processing
  }
  
  可以看到,代码还是很直接的。从接受到消息的窗口层层往上遍历,并调用PretranslateMessage看是否返回TRUE,是则结束,否则继续。
  这里有一个地方非常关键:CWnd *pWnd = CWnd::FromHandlePermanent(hWnd) 这一句代码从当前AfxModuleThreadState拿到Permanent句柄表,从而找到hWnd对应的CWnd


MFC中PreTranslateMessage是GetMessage(...)函数的下一级操作,即GetMessage(...)从消息队列中获取消息后,交由PreTranslateMessage()处理,若其返回FALSE则再交给TranslateMessage和DispatchMessage处理(进入WindowProc);  
如果用SendMessage,   则消息直接交到WindowProc处理,所以GetMessage不会取得SendMessage的消息,当然PreTranslateMessage也就不会被调用。   [Page]
如果用PostMessage,则消息进入消息队列,由GetMessage取得,PreTranslateMessage就有机会进行处理。
 
 
windows消息处理机制是这样的:  
      首先系统(也就是windows)把来自硬件(鼠标,键盘等消息)和来自应用程序的消息 放到一个系统消息队列中去. 而应用程序需要有自己的消息队列,也就是线程消息队列,每一个线程有自己的消息队列,对于多线程的应用程序就有和线程数目相等的线程消息队列.  
  windows 消息队列把得到的消息发送到线程消息队列, 线程消息队列每次取出一条消息发送到指定窗口,不断循环直到程序退出.这个循环就是靠消息环(while(GetMessage()) TranslateMessage();DispatchMessage();实现的.GetMessage()只是从线程消息中取出一条消息,TranslateMessage()把virtue key消息转化成character消息,如VK_F1会转化成WM_HELP,而DispatchMessage  则把取出的消息发送到目的窗口.如果收到WM_CLOSE消息则结束循环,发送postqiutmessage(0),处理WM_DESTROY销毁窗口!
 
 while (GetMessage(&msg, NULL, 0, 0))          //C++ code
 {  
        TranslateMessage(&msg);
        DispatchMessage(&msg);
 }
 
 

转载于:https://www.cnblogs.com/Dennis-mi/articles/3403402.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MFC消息处理[转] 的相关文章

  • 在 Visual Studio 2013 中显示带有偏移量的控件

    最近 我将源代码从 Visual Studio 2010 迁移到 Visual Studio 2013 在 Visual Studio 2013 中构建后 控件将显示有偏移 单击下面的链接查看图像 链接到图像 https i stack i
  • 如何从头开始启动 MFC 应用程序?

    换句话说 来自一个空白的 win32 项目 无向导 这就是我所在的地方 预处理器定义 WIN32 链接器 gt 系统 gt 子系统 控制台 int tmain int nRetCode 0 initialize MFC and print
  • VC++中如何判断链接是否存在?

    我有一个链接 我已通过正则表达式检查该链接是否是有效的 URL 现在 我想检查该链接是否是有效的 http 链接 即它不应该是不存在的链接 VC 6 0 MFC 有办法检查吗 一种选择是尝试使用以下方法从该 URL 获取数据URLOpenB
  • C++ Builder vs Delphi vs MFC

    我正在学习MFC 发现它不太好用 我听说过很多关于 Delphi 的事 对 Delphi 的研究让我接触到了 C Builder C Builder 是否提供了 C MFC 的严肃且良好的替代方案 C Builder 比 MFC 更好吗 C
  • DirectUI 的真相是什么? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在开发一个 Windows 桌面应用程序 它需要一个很棒的 UI 我现在使用Visual Studio和MFC 后来听说DirectU
  • Boost::序列化和 MFC Doc/View 架构

    我正在移植现有的 MFC C 应用程序以对 XML 文件使用 Boost Serialization 我的 CDocument 对象包含应用程序的所有数据 我已将序列化函数实现为 template
  • 如何将 unicode 字符变成小写字母

    我在 VC MFC 中将 unicode 字符转换为小写字母时遇到问题 我在 CString 变量中有 unicode 字符 所以 使用英语 MakeLower 工作正常 我得到小写字母 但它无法将 unicode 字符转换为小写 我确实尝
  • SetWindowPos() 函数不移动窗口?

    我有一个对话框 我想将其放置在另一个对话框中 并相对于主对话框上的其中一个控件进行定位 void CspAceDlg DrawResultsArea CWnd pTabCtl GetDlgItem IDC BUILDTABS CRect r
  • 如何向现有 Win32 C++ 项目添加 MFC 支持?

    我正在创建一个 C 应用程序 它使用 Qt 创建 GUI 但是 我需要使用依赖于 MFC 的第三方库 用于 CString 等 无论如何 是否可以将 MFC 添加到我的应用程序中以允许我使用这个库 或者我需要自己重写它 I saw 这个问题
  • 从不同操作系统检索到的故障转储指向消息循环。如何从那里到达故障位置? (TeamViewer 使我的进程崩溃。)

    我们软件的一位客户抱怨说 该软件在他的 Windows XP 计算机上崩溃了 我让他下载ProcDump https technet microsoft com en us sysinternals dd996900 aspx并按如下方式运
  • 如何将 std::variant 作为 VARIANT* 传递给 ExecWB?

    我看过这篇关于使用的文章std variant https en cppreference com w cpp utility variant 这是因为以下代码引发了代码分析警告 void CChristianLifeMinistryHtm
  • 如何找到激活时打开给定 HMENU 的菜单项(如果有)?

    我想用原型实现一个功能 Locates the menu item of the application which caused the given menu mnu to show up return true if the given
  • 想要将 ColeDateTime 转换为 CTime

    我正在从数据库中读取日期时间ColeDateTime格式 我想将其转换为CTime获取日期 月份 年份和时间 CString repDt this will hold the datetime which i read from Datab
  • 实现批量记录获取

    在程序开始时 我需要将数据从 MS Access 数据库 mdb 读取到下拉控件中 这样做是为了每当用户在该控件中键入内容时 应用程序都可以自动完成 不管怎样 从数据库中读取数据花了很长时间 所以我想我应该实现批量行获取 这是我的代码 CS
  • 错误 C2248: 'CObject::CObject' : 无法访问类 'CObject' afxwin.h 中声明的私有成员

    我试图让班级负责在灰色背景上放置一些文本 Score h pragma once class Score public Score Score void UpdateScore int points void UpdateLives int
  • 发送WM_SETTEXT时如何避免EN_CHANGE通知?

    我有一个 CEdit 派生控件 当基本数据为空时 该控件显示字符串 N A 我最近添加了代码 以在控件获得焦点时清空控件 SetWindowText 并在用户离开焦点时将其设置回 N A SetWindowText N A 控空 唯一的问题
  • 用于基于 MFC 的 GUI 应用程序的免费自动化测试工具

    我是 Windows 开发和测试平台的新手 我正在开发一个基于 MFC 的 GUI 应用程序 并正在寻找有助于 UI 自动化测试的工具 我搜索时出现了一大堆工具 但大多数似乎都不支持MFC 我考虑的选项是 A 编码 UI UI 自动化 看起
  • 更改 GLUT 调用以与 MFC/C++ 一起使用

    我有一个使用 GLUT 进行 OpenGL 渲染的程序 现在我需要它位于 MFC 项目内部 以便它可以与另一个程序组件一起使用 我已经按照这个教程进行操作 http www codeguru com cpp g m opengl openf
  • C++ 中的转换错误

    有人可以帮我解决这个错误吗 我是 C 新手 看来错误就发生在一堆宏中 我能做什么来解决它 或者我怎样才能追踪到它的源头 我真的不明白这个错误 这是否意味着编译器尝试转换该方法void ReadCPUparameter to a LRESUL
  • 如何在 VC++ CString 中验证有效的整数和浮点数

    有人可以告诉我一种有效的方法来验证 CString 对象中存在的数字是有效整数还是浮点数吗 Use tcstol http msdn microsoft com en us library w4z2wdyc aspx and tcstod

随机推荐