• 离奇失踪的WM_HOTKEY消息--浅析WIN32消息队列


    故事的开端有些平淡,眼红于XXX小程序,认为写完该程序就有了和心仪的妹子多相处的机会,必须搞,必须酷,按钮不能有,界面得隐藏,这就想到了全局快捷键。

    注册调用RegisterHotKey(m_hWnd, 300, MOD_ALT, 'K');

    定义消息处理函数 afx_msg long OnHotKey(WPARAM wparam, LPARAM lparam);

    消息关联处理程序ON_MESSAGE(WM_HOTKEY, OnHotKey) 

    定义消息处理函数 ,switch(wparam)调用对应的函数处理。

    测试了一下,一切OK,开始搜索其他API,埋头苦整,一番恶战终于搞定其他功能,开始登记其他快捷键并调用处理过程。OH SHIT!快捷键没效果了?难道是登记的快捷键冲突了?检查了RegisterHotKey的返回值,是正确的,那么登记快捷键肯定没问题!该怎么办呢?去查WIN32消息处理机制来解决问题吧

    MFC总共有三种类型的消息:窗口、命令、控件通知,嗯,找找窗口消息是怎么处理的。

    登记全局快捷键的原理解释是:某键被按下时,系统在所有的热键列表中寻找匹配者,匹配成功将WM_HOTKEY消息发送给登记了该热键的线程的消息处理队列。挠了挠脑袋,我认定WM_HOTKEY已经发送给指定的消息队列。

    -----补充知识点,发送消息有两种形式:发送消息,即时到达并立马调用目标窗口的进程,目标窗口必须为调用函数返回一个结果才能继续;寄送消息,将消息加入目标进程的消息队列,应用程序有空闲时就会搜索消息队列,从消息队列中删除消息并将消息发送给指定窗口,通信可能延迟。鼠标和键盘消息由于其特殊性,采用寄送的方式处理,其他所有消息都是发送的方式。

      到这里就有点悟了,敢情我定义的全局快捷键处理函数OnHotKey并不会直接被调用,大胆猜测一下:窗口进程从消息队列中取出寄送来的WM_HOTKEY消息后首先交给了窗口,而窗口线程收到WM_HOTKEY消息并没有按照我的意愿调用OhHotKey。再找一下窗口处理消息的机制。

     寄送消息在被消息泵弹出之前会一直保留在消息队列中,直到应用程序调用GetMessage函数从消息队列中将之取出,取出后会调用PreTranslateMessage和TranslateMessage两个函数进行消息翻译,翻译后的消息通过DispatchMessage调用该消息预期的目标窗口进程。看到这里,不由得笑了,这可是大有玄机啊,GO ON!

     PreTranslateMessage有点眼熟,果然从代码里找到这个知其然、不知其所以然的预处理函数。埋头继续查:绝大多数本窗口的消息都要经过PreTranslateMessage处理,如果想在MFC之前处理某消息,可以重载该函数,重点来了,只有经过消息队列的消息才会经过PreTranslateMessage处理,即时发送的消息或其他不经过消息队列的消息不会理睬该函数,联系前面的寄送消息方式,各位小看官都应该懂了,快捷键消息到了这里被截下来没有发送给预期的窗口处理函数。挖,还得挖,这个坑有点苗头了。

    PretranslateMessage的定义和返回值仔细的看:是否调用TranslateMessage和DispatchMessage消息向指定窗口发送消息由PreTranslateMessage的返回值决定,当返回值为TRUE的时候,不回把消息发送给对应的窗口函数处理,这难道是真相?预处理消息的时候挖坑把WM_HOTKEY消息给埋起来了?修改代码,拦截到指定的消息后返回FALSE果然解决了问题。

    随着真相的浮出水面,我又一次期待着想象中的其乐融融,加油,我会做一个颇具高手风范的tool。 

  • 相关阅读:
    可变形参 Day07
    流程控制 Day06
    基本数据类型的值传递 和引用数据类型的引用传递 Day06
    一维数组的求平均成绩 Day06
    一维数组的初始化及遍历 Day06
    字符串分割+二维数组 Day15练习
    Java对数组和列表的排序1.8新特性
    Java Stream
    JPA学习(六、JPA_JPQL)
    JPA学习(五、JPA_二级缓存)
  • 原文地址:https://www.cnblogs.com/learn-my-life/p/3382703.html
Copyright © 2020-2023  润新知