非模态对话框如何相应键盘消息?(ESC and Enter) 非模态对话框如何相应键盘消息?(ESC and Enter) 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 HOHO 分好多哦 不过这个问题应该挺简单的吧BOOL CYOURFROM::PreTranslateMessage(MSG* pMsg) { switch(pMsg->message) { case WM_KEYDOWN: switch (pMsg->wParam) { case VK_RETURN: { 响应按下回车后所执行的内容 } break; case VK_ESCAPE: { 响应按下esc后所执行的内容 } } } return CDialog::PreTranslateMessage(pMsg);} 有点乱 整理一下 HOHOBOOL CYOURFROM::PreTranslateMessage(MSG* pMsg) { switch(pMsg->message) { case WM_KEYDOWN: switch (pMsg->wParam) { case VK_RETURN: { 响应按下回车后所执行的内容 } break; case VK_ESCAPE: { 响应按下esc后所执行的内容 } break; } } return CDialog::PreTranslateMessage(pMsg); } 我们要想在第一时间对对话框的按键做出响应,需要重载PreTranslateMessage, 以下的代码实现了在对话框中显示虚拟键值(virtual-key code) BOOL CTestDlg::PreTranslateMessage(MSG* pMsg) { if(pMsg->message == WM_KEYDOWN) { ///或者直接调用OnKeyDown CString strwParam; strwParam.Format("%d ",pMsg->wParam); CDC* pDC = GetDC(); pDC->TextOut(10,10,strwParam); ReleaseDC(pDC); } return CDialog::PreTranslateMessage(pMsg); } 此方法也适用于FORMVIEW或其它控件中对键盘按键的响应,以下的代码来自MSDN, 实现了当按下上下左右方向键时调用OnKeyDown,我们可以在OnKeyDown中作相应处理。 BOOL CSampleControl::PreTranslateMessage(LPMSG lpmsg) { BOOL bHandleNow = FALSE; switch (lpmsg->message) { case WM_KEYDOWN: switch (lpmsg->wParam) { case VK_UP: case VK_DOWN: case VK_LEFT: case VK_RIGHT: bHandleNow = TRUE; break; } if (bHandleNow) OnKeyDown(lpmsg->wParam, LOWORD(lpmsg ->lParam), HIWORD(lpmsg->lParam)); break; } return bHandleNow; } 3楼所说///或者直接调用OnKeyDown 多数情况是不可行滴,如果窗口上没有控件还好,当然我们首先想到的是响应WM_KEYDOWN消息,但实际运行却发现没有任何效果。 原因是对话框里的控件需要首先对按键作出响应,比如多行编辑框必须首先 处理回车,不至于回车使对话框关闭。 我们要想在第一时间对对话框的按键做出响应,需要重载PreTranslateMessage, VsirSoft说的没问题啊,你的怎么了? 我的dialog是这个样子的class CxxxDlg : public CDialogImpl<CxxxDlg > 你的对话框是WTL模板的,仍然是这样处理,你用WTL的向导生成一个Modeless的对话框测试即可. WTL的Modeless对话框是直接调用ShowWindow。WTL本身的示例GuidGen也是一个Modeless对话框的示例class CMainDlg : public CDialogImpl<CMainDlg>, public CUpdateUI<CMainDlg>, public CMessageFilter, public CIdleHandler{public: enum { IDD = IDD_MAINDLG }; virtual BOOL PreTranslateMessage(MSG* pMsg) { switch(pMsg->message) { case WM_KEYDOWN: switch (pMsg->wParam) { case VK_RETURN: { ::MessageBox(NULL, L"Return", L"", MB_OK); } break; case VK_ESCAPE: { ::MessageBox(NULL, L"ESC", L"", MB_OK); return TRUE; } } break; } return CWindow::IsDialogMessage(pMsg); } virtual BOOL OnIdle() { return FALSE; } // .......}; 但是我的PreTranslateMessage call不进来 那估计是你直接搞什么破坏了,这是WTL的消息传递机制中的一步,只能你自己先尝试调试。下面是消息的基本过程:int CMessageLoop::Run(){...... if(!PreTranslateMessage(&m_msg)) { ::TranslateMessage(&m_msg); ::DispatchMessage(&m_msg); }......}virtual BOOL PreTranslateMessage(MSG* pMsg){ // loop backwards for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--) { CMessageFilter* pMessageFilter = m_aMsgFilter[i]; if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg)) return TRUE; } return FALSE; // not translated}通过CMessageFilter对象,它会把消息传递到PreTranslateMessage方法,因此,你可以尝试在前面的几个地方进行调试,或者看看你的CMessageFilter是否使用错误. 很抱歉,前面的回复也许全部都不能用,对应简单的Modeless对话框,可能这样是适合的,但是如果在DoModel的基础至少再显示Modeless对话框,这样估计就不能了,你不能直接取它的CMessageLoop链条。 这个时候只能使用HOOK,挂接GetMessage钩子。请参考微软知识库文章:http://support.microsoft.com/kb/q187988/ 和http://support.microsoft.com/kb/q216503/ 本帖最后由 laiyiling 于 2008-04-29 12:02:58 编辑 消息循环中调用IsDialogMessage,如果返回非0值则继续下次循环。 对于这个可能不行,你可以用ATL/WTL试试。若ATL/WTL是通过DoModel建立的消息讯息,微软的建议仍然是HOOK。 MFC datetime picker无法获取选择的时间 最近做一个用POP3协议收邮件的小东西,能CONNECT,但是SEND返回很慢,而且是验证失败 编辑框问题 动态文件名技术 如何通过线程ID取得窗口的HANDLE? 如何定位编辑框和移动编辑框? 按键消息是子窗口还是父窗口先收到? 在Dialog中显示Bmp图片 急切寻VISUAL ASSIANT 的注册码!!! 在哪可以下载到programming windows95(Petzold著)这本书的中文版? VC6下SDI使用GDI+处理GIF图片时,第一次可以打开显示.打开之后若触发VIEW重绘就会报错,何解? * 谁了解证券开户系统的 信息安全 设计方法? 我这样设计是安全的吗?
不过这个问题应该挺简单的吧BOOL CYOURFROM::PreTranslateMessage(MSG* pMsg)
{
switch(pMsg->message)
{
case WM_KEYDOWN:
switch (pMsg->wParam)
{
case VK_RETURN:
{
响应按下回车后所执行的内容
}
break;
case VK_ESCAPE:
{
响应按下esc后所执行的内容
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
BOOL CYOURFROM::PreTranslateMessage(MSG* pMsg)
{
switch(pMsg->message)
{
case WM_KEYDOWN:
switch (pMsg->wParam)
{
case VK_RETURN:
{
响应按下回车后所执行的内容
}
break;
case VK_ESCAPE:
{
响应按下esc后所执行的内容
}
break;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
以下的代码实现了在对话框中显示虚拟键值(virtual-key code)
BOOL CTestDlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_KEYDOWN)
{
///或者直接调用OnKeyDown
CString strwParam;
strwParam.Format("%d ",pMsg->wParam);
CDC* pDC = GetDC();
pDC->TextOut(10,10,strwParam);
ReleaseDC(pDC);
}
return CDialog::PreTranslateMessage(pMsg);
}
此方法也适用于FORMVIEW或其它控件中对键盘按键的响应,以下的代码来自MSDN,
实现了当按下上下左右方向键时调用OnKeyDown,我们可以在OnKeyDown中作相应处理。
BOOL CSampleControl::PreTranslateMessage(LPMSG lpmsg)
{
BOOL bHandleNow = FALSE;
switch (lpmsg->message)
{
case WM_KEYDOWN:
switch (lpmsg->wParam)
{
case VK_UP:
case VK_DOWN:
case VK_LEFT:
case VK_RIGHT:
bHandleNow = TRUE;
break;
}
if (bHandleNow)
OnKeyDown(lpmsg->wParam, LOWORD(lpmsg ->lParam), HIWORD(lpmsg->lParam));
break;
}
return bHandleNow;
}
我们首先想到的是响应WM_KEYDOWN消息,但实际运行却发现没有任何效果。
原因是对话框里的控件需要首先对按键作出响应,比如多行编辑框必须首先
处理回车,不至于回车使对话框关闭。
我们要想在第一时间对对话框的按键做出响应,需要重载PreTranslateMessage,
VsirSoft说的没问题啊,你的怎么了?
class CxxxDlg : public CDialogImpl<CxxxDlg >
class CMainDlg : public CDialogImpl<CMainDlg>, public CUpdateUI<CMainDlg>,
public CMessageFilter, public CIdleHandler
{
public:
enum { IDD = IDD_MAINDLG }; virtual BOOL PreTranslateMessage(MSG* pMsg)
{
switch(pMsg->message)
{
case WM_KEYDOWN:
switch (pMsg->wParam)
{
case VK_RETURN:
{
::MessageBox(NULL, L"Return", L"", MB_OK);
}
break;
case VK_ESCAPE:
{
::MessageBox(NULL, L"ESC", L"", MB_OK);
return TRUE;
}
}
break;
}
return CWindow::IsDialogMessage(pMsg);
} virtual BOOL OnIdle()
{
return FALSE;
}
// .......
};
{
......
if(!PreTranslateMessage(&m_msg))
{
::TranslateMessage(&m_msg);
::DispatchMessage(&m_msg);
}
......
}
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
// loop backwards
for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
{
CMessageFilter* pMessageFilter = m_aMsgFilter[i];
if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))
return TRUE;
}
return FALSE; // not translated
}通过CMessageFilter对象,它会把消息传递到PreTranslateMessage方法,因此,你可以尝试在前面的几个地方进行调试,或者看看你的CMessageFilter是否使用错误.
http://support.microsoft.com/kb/q187988/ 和
http://support.microsoft.com/kb/q216503/
对于这个可能不行,你可以用ATL/WTL试试。若ATL/WTL是通过DoModel建立的消息讯息,微软的建议仍然是HOOK。