1.问题描述
基于MFC窗口嵌套IE内核的3D游戏,在游戏聊天界面,如果用户输入了VK_BACK按键,那么此时在输入其他字符或者按键都无法响应,导致用户输入无效(仅仅VK_BACK有效)。
2.问题分析
1.3D游戏放在IE浏览器运行=》正常
2.3D游戏通过MFC窗口运行之后,将游戏脱离窗口设置为独立的窗口,运行正常
3.建立一个空的MFC工程,将游戏嵌套进去,现象复现
所以综上分析我们得出是MFC在传输VK_BACK消息导致的,并非嵌套框架导致的,那么到底是系统按键出发的bug还是字符显示出发的bug呢。
3.问题解决
通过上述分析我们初步解决方案就是PreTranslateMessage拦截VK_BACK消息。
错误实现:
if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_BACK)) {
return TRUE;
}
这样虽然可以拦截VK_BACK,但是导致VK_BACK没办法删除字符。
因为我们使用键盘VK_BACK的功能是删除字符,而不是显示字符VK_BACK。所以我们可以换种实现方式
正确实现:
if ((pMsg->message == WM_CHAR) && (pMsg->wParam == VK_BACK)) {
return TRUE;
}
此时只是界面功能正常。
4.问题结论
是由于3D游戏处理键盘WM_CHAR为VK_BACK消息触发而导致的。但是由于是第三方的游戏,所以我们只做消息拦截处理。
5.修改后的源码
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)) {
return FALSE;
}
if ((pMsg->message == WM_CHAR) && (pMsg->wParam == VK_BACK)) {
return FALSE;
}
BOOL has_process = FALSE;
if (m_spPlaceActiveObject != NULL) {
HRESULT hr = m_spPlaceActiveObject->TranslateAcceleratorW(pMsg);
if (S_OK == hr) {
has_process = TRUE;
}
}
if (has_process) {
return TRUE;
}
return CWindow::IsDialogMessage(pMsg);
}