故事的开端有些平淡,眼红于XXX小程序,认为写完该程序就有了和心仪的妹子多相处的机会,必须搞,必须酷,按钮不能有,界面得隐藏,这就想到了全局快捷键。小程序
注册调用RegisterHotKey(m_hWnd, 300, MOD_ALT, 'K');函数
定义消息处理函数 afx_msg long OnHotKey(WPARAM wparam, LPARAM lparam);测试
消息关联处理程序ON_MESSAGE(WM_HOTKEY, OnHotKey) spa
定义消息处理函数 ,switch(wparam)调用对应的函数处理。线程
测试了一下,一切OK,开始搜索其余API,埋头苦整,一番恶战终于搞定其余功能,开始登记其余快捷键并调用处理过程。OH SHIT!快捷键没效果了?难道是登记的快捷键冲突了?检查了RegisterHotKey的返回值,是正确的,那么登记快捷键确定没问题!该怎么办呢?去查WIN32消息处理机制来解决问题吧翻译
MFC总共有三种类型的消息:窗口、命令、控件通知,嗯,找找窗口消息是怎么处理的。队列
登记全局快捷键的原理解释是:某键被按下时,系统在全部的热键列表中寻找匹配者,匹配成功将WM_HOTKEY消息发送给登记了该热键的线程的消息处理队列。挠了挠脑壳,我认定WM_HOTKEY已经发送给指定的消息队列。进程
-----补充知识点,发送消息有两种形式:发送消息,即时到达并立马调用目标窗口的进程,目标窗口必须为调用函数返回一个结果才能继续;寄送消息,将消息加入目标进程的消息队列,应用程序有空闲时就会搜索消息队列,从消息队列中删除消息并将消息发送给指定窗口,通讯可能延迟。鼠标和键盘消息因为其特殊性,采用寄送的方式处理,其余全部消息都是发送的方式。消息队列
到这里就有点悟了,敢情我定义的全局快捷键处理函数OnHotKey并不会直接被调用,大胆猜想一下:窗口进程从消息队列中取出寄送来的WM_HOTKEY消息后首先交给了窗口,而窗口线程收到WM_HOTKEY消息并无按照个人意愿调用OhHotKey。再找一下窗口处理消息的机制。it
寄送消息在被消息泵弹出以前会一直保留在消息队列中,直到应用程序调用GetMessage函数从消息队列中将之取出,取出后会调用PreTranslateMessage和TranslateMessage两个函数进行消息翻译,翻译后的消息经过DispatchMessage调用该消息预期的目标窗口进程。看到这里,不禁得笑了,这但是大有玄机啊,GO ON!
PreTranslateMessage有点眼熟,果真从代码里找到这个知其然、不知其因此然的预处理函数。埋头继续查:绝大多数本窗口的消息都要通过PreTranslateMessage处理,若是想在MFC以前处理某消息,能够重载该函数,重点来了,只有通过消息队列的消息才会通过PreTranslateMessage处理,即时发送的消息或其余不通过消息队列的消息不会理睬该函数,联系前面的寄送消息方式,各位小看官都应该懂了,快捷键消息到了这里被截下来没有发送给预期的窗口处理函数。挖,还得挖,这个坑有点苗头了。
PretranslateMessage的定义和返回值仔细的看:是否调用TranslateMessage和DispatchMessage消息向指定窗口发送消息由PreTranslateMessage的返回值决定,当返回值为TRUE的时候,不回把消息发送给对应的窗口函数处理,这难道是真相?预处理消息的时候挖坑把WM_HOTKEY消息给埋起来了?修改代码,拦截到指定的消息后返回FALSE果真解决了问题。
随着真相的浮出水面,我又一次期待着想象中的其乐融融,加油,我会作一个颇具高手风范的tool。