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处的代码而己。

 

为何这段语句中结算单号不需要用到wm_concat函数 select wm_concat(distinct to_char( t.就医方式)) 就医方式, wm_concat(distinct to_char( t.住院门诊号)) 住院门诊号, t.就诊号, t.结算单号, t.病历号, t.定点归属医保区划, t.统筹区编号, t.参保所属医保区划, t.退费标志, t.特殊人员类型名称, wm_concat(distinct to_char( t.目录类别名称)) 目录类别名称, wm_concat(distinct to_char( t.支付地点类别名称)) 支付地点类别名称, t.入院时间, t.出院时间, wm_concat(distinct to_char( t.住院天数)) 住院天数, t.医院编号, t.医院名称, t.个人编码, t.姓名, wm_concat(distinct to_char( t.年龄)) 年龄, t.性别, t.身份证, t.出生日期, wm_concat(distinct to_char( t.参保险种名称)) 参保险种名称, wm_concat(distinct to_char( t.主诊断编码)) 主诊断编码, wm_concat(distinct to_char( t.主诊断名称)) 主诊断名称, wm_concat(distinct to_char( t.副诊断编码)) 副诊断编码, wm_concat(distinct to_char( t.副诊断名称)) 副诊断名称, wm_concat(distinct to_char( t.住院主诊断代码)) 住院主诊断代码, wm_concat(distinct to_char( t.住院主诊断名称)) 住院主诊断名称, wm_concat(distinct to_char( t.主要病情描述)) 主要病情描述, wm_concat(distinct to_char( t.病种编码)) 病种编码, wm_concat(distinct to_char( t.病种名称)) 病种名称, wm_concat(distinct to_char( t.入院科室)) 入院科室, wm_concat(distinct to_char( t.出院科室)) 出院科室, wm_concat(distinct to_char( t.开单科室编码)) 开单科室编码, wm_concat(distinct to_char( t.开单科室名称)) 开单科室名称, wm_concat(distinct to_char( t.受单科室编码)) 受单科室编码, wm_concat(distinct to_char( t.受单科室名称)) 受单科室名称, wm_concat(distinct to_char( t.主诊医师代码)) 主诊医师代码, wm_concat(distinct to_char( t.主诊医师姓名)) 主诊医师姓名, wm_concat(distinct to_char( t.开单医师代码)) 开单医师代码, wm_concat(distinct to_char( t.开单医生姓名)) 开单医生姓名, wm_concat(distinct to_char( t.受单医师代码)) 受单医师代码, wm_concat(distinct to_char( t.受单医师姓名)) 受单医师姓名, wm_concat(distinct to_char( t.主手术操作代码)) 主手术操作代码, wm_concat(distinct to_char( t.主手术操作名称)) 主手术操作名称, wm_concat(distinct to_char( t.副手术操作代码)) 副手术操作代码, wm_concat(distinct to_char( t.副手术操作名称)) 副手术操作名称, wm_concat(distinct to_char( t.支付类别名称)) 支付类别名称, wm_concat(distinct to_char( t.医疗收费项目类别名称)) 医疗收费项目类别名称, t.结算时间, trunc (t.费用发生时间) 费用发生时间, t.医保项目编码, wm_concat(distinct to_char( t.医保项目名称)) 医保项目名称, wm_concat(distinct to_char( t.医院项目编码)) 医院项目编码, wm_concat(distinct to_char( t.医院项目名称)) 医院项目名称, wm_concat(distinct to_char( t.单价)) 单价, sum(t.数量) 数量, sum(t.金额) 总金额, wm_concat(distinct to_char( t.报销比例)) 报销比例, sum(t.符合医保范围金额) 符合医保范围金额, min(t.单价) 最低单价 from temp1 t --同一日超过1次 where t.scnt >1 group by t.就诊号, t.结算单号, t.病历号, t.定点归属医保区划, t.统筹区编号, t.参保所属医保区划, t.退费标志, t.特殊人员类型名称, t.入院时间, t.出院时间, t.结算时间, t.医院编号, t.医院名称, t.个人编码, t.医保项目编码, t.姓名, t.性别, t.身份证, t.出生日期, trunc (t.费用发生时间) )
最新发布
07-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值