WM_CHAR消息分析

博客转移:http://vivianke.blog.163.com/blog/static/297152712007529113537994/

 

WM_CHAR消息分析

应用程序中键盘消息从WM_KEYFIRSTWM_KEYLAST那么多,但我们知道最原始的键盘消息只有两个那就是WM_KEYDOWN, WM_KEYUP,在键盘钩子中我们能截获的也就这两个消息,那其它消息是从何产生的,如何动作的呢?下面我们就WM_CHAR消息来分析一下。

 

一个键按下后,便会有一个或多个WM_KEYDOWN消息产生,这些消息会从系统消息队列发送到目标窗口的线程的消息队列中,这样在对应线程处理消息时便会对此消息处理,并在处理的过程中产生一系列的其它键盘消息,其中便有WM_CHAR

 

以下是向对话框中的编辑框输入‘a‘的部分处理过程(以所附源码调试、整理而得)

CGetInputDlg::DoModal()     //对话框创建,往编辑框按下一键‘a

001 CGetInputDlg::RunModalLoop //消息循环,在这里peekWM_KEYDOWN

002 CGetInputDlg::PumpMessage //消息泵,取消息、翻译、处理这些消息

003 CGetInputDlg::PreTranslateMessage //线程开始消息预处理

004 CGetInputDlg::WalkPreTranslateTree //从目标窗口到主窗口历遍

005 CMyEdit::PreTranslateMessage    //目标窗口,没有处理(返回FALSE)。

006 CGetInputDlg::PreTranslateMessage //子窗口没有处理,所以流到父窗口

007 CDialogDlg::PreTranslateMessage //由基类处理

   ...

008 CMyEdit::WindowProc

009 CMyEdit::OnWndMsg

010 CMyEdit::OnKeyDown

011 CMyEdit::DefWindowProc

012 CGetInputDlg::RunModalLoop //在这里peekWM_CHAR,不过一般情况下之间会有几个WM_KICKIDLE

    ...

 

由上有人就会说,这并不能说明WM_CHARWM_KEYDOWN消息处理过程中产生的,这仅仅说明WM_CHARWM_KEYDOWN之后。i嗯,大家再看看下面。

 

这些是所附源码中的调试输出信息,无~~代表对应函数的进入,有~~代表一个函数的返回点,msg后的值为消息的16进制值(WM_KEYDOWN= 0X100, WM_KEYUP=0X101, WM_CHAR=0X102)haveCharMsg为消息队列中是否有WM_CHAR消息(通过peekmessage来实现)

 

英文输入‘a‘,对应调试信息整理如下:

对应005

101 CMyEdit::PreTranslateMessage msg=100, haveCharMsg=0

102 ~~CMyEdit::PreTranslateMessage msg=100, haveCharMsg=0, Ret=0

对应006

103 CGetInputDlg::PreTranslateMessage msg=100, haveCharMsg=0

105  CMyEdit::OnKeyDown haveCharMsg=1

106  CMyEdit::DefWindowProc msg=100, haveCharMsg=1

107  ~~CMyEdit::DefWindowProc msg=100, haveCharMsg=1, Ret=1

108  ~~CMyEdit::OnKeyDown haveCharMsg=1

109 ~~CGetInputDlg::PreTranslateMessage msg=100, haveCharMsg=1, Ret=1

 

110 CMyEdit::PreTranslateMessage msg=102, haveCharMsg=0

111 ~~CMyEdit::PreTranslateMessage msg=102, haveCharMsg=0, Ret=0

 

112 CGetInputDlg::PreTranslateMessage msg=102, haveCharMsg=0

113  CMyEdit::OnChar 61

114  CMyEdit::DefWindowProc msg=102, haveCharMsg=0

115  ~~CMyEdit::DefWindowProc msg=102, haveCharMsg=0, Ret=1

116  ~~CMyEdit::OnChar 61

117 ~~CGetInputDlg::PreTranslateMessage msg=102, haveCharMsg=0, Ret=1

 

118 CMyEdit::PreTranslateMessage msg=101, haveCharMsg=0

119 ~~CMyEdit::PreTranslateMessage msg=101, haveCharMsg=0, Ret=0

 

120 CGetInputDlg::PreTranslateMessage msg=101, haveCharMsg=0

121  CMyEdit::OnKeyUp

122  CMyEdit::DefWindowProc msg=101, haveCharMsg=0

123  ~~CMyEdit::DefWindowProc msg=101, haveCharMsg=0, Ret=0

124  ~~CMyEdit::OnKeyUp

125 ~~CGetInputDlg::PreTranslateMessage msg=101, haveCharMsg=0, Ret=1

 

看到了吗?在103处(对应处理过程006处)的CGetInputDlg::PreTranslateMessage里产生了WM_CHAR消息,并放入了消息队列中。由此可见消息确实是WM_KEYDOWN处理过程中产生的。在WM_KEYDOWN处理完成后,消息循环便检测到它,并在 PumpMessageGet它,并进入110相应的处理。也就在此时队列中已无WM_CHAR消息了。

 

耶,不对啊,很多地方不是说TranslateMessage产生WM_CHAR消息?他们的意思也就是PumpMessage中的

m_msgCur),我将PumpMessage简化如下:

200 BOOL CWinThread::PumpMessage() (CGetInputDlg::PumpMessage)

201 {

202 ASSERT_VALID(this);

m_msgCur, NULL, NULL, NULL))

204 return FALSE;

205 // process this message

206 if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))

m_msgCur);

m_msgCur);

210 }

211 return TRUE;

212 }

这里可见,只有当PreTranslateMessageCGetInputDlg::)返回FALSE时才会执行208处对应的函数,而事实上从 103处可以看到CGetInputDlg::PreTranslateMessage还没有返回,就有了WM_CHAR消息,而且从 ~~CGetInputDlg::PreTranslateMessage可以看出PreTranslateMessage返回为1,不会执行208 209。那是不是那些说法错了呢?也不一定,如果他指的是对话框程序,那我想他就确实错了,但对于非对话框程序是对的,我建了一SDI工程,PreTranslateMessage中对于非加速键返加是FALS,即会执行208209::TranslateMessage(&m_msgCur)来翻译键盘消息。当然,如果我想 PreTranslateMessage中的默认处最终还是调TranslateMessage来完成翻译的,只是不对应208处的代码而己。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值