TO: mtsh(清风华仔(*****)) 在MFC中,当然通过消息映射或类的继承,WM_KEYDOWN消息会送往其他地方,这正是MFC和Win SDK的差别,你可以在CDialog::PreTranslateMessage中看到CDialog截获CEdit的WM_KEYDOWN消息(当wParam为VK_ESCAPE时),转而发送IDCANCEL命令消息,引发OnCancel()。 我现在想要得就是当在对话框的一个编辑控件中按下ESC和ENTER时,由编辑控件来处理,而不是直接关闭对话框。
To cygroup():原来这样,原来我疏忽了!不过既然这样,你可以重写CDialog类重载PreTranslateMessage函数,改变对ESC和ENTRY键的默认处理方式,并把对基类的调用注释掉,实现起来应该没问题。
To mtsh(清风华仔(*****)) 通过参考MFC源代码,初步知道了解决办法,你说对了一半,是要重载CDialog子类的PreTranslateMessage函数,但不能屏蔽基类CDialog的PreTranslateMessage函数调用,因为那样会屏蔽掉所有针对对话框的其他输入,对话框会毫无反应。应该在对基类PreTranslateMessage函数的调用前,将ESC和ENTER的消息筛选出来重发向当前具有焦点的窗口。至于CDialog在什么地方如何截取ENTER的,我实在没时间、精力查下去了,都是MFC,把事情搞得那么复杂,要是用SDK就简单多了,键盘消息都是直接发向当前唯一具有输入焦点的窗口的。
补充:屏蔽基类CDialog的PreTranslateMessage函数调用也行,但一定返回FALSE,按MSDN的说法: Nonzero if the message was translated and should not be dispatched; 0 if the message was not translated and should be dispatched. 非零的返回值会导致消息不再分发。
窗口拦截了enter,esc,控件就得不到消息。这个是拦截enter转换为tab的例子:
BOOL CXxDialog::PreTranslateMessage(MSG* pMsg)
if(pMsg->message == WM_KEYDOWN )
{
CWnd * pWnd = CWnd::GetFocus();
int nID = pWnd->GetDlgCtrlID();
switch (pMsg->wParam)
{
case VK_RETURN:
if(!pWnd->IsKindOf(RUNTIME_CLASS(CButton)))
pMsg->wParam = VK_TAB;
else
{
pWnd->PostMessage(WM_LBUTTONDOWN,WM_COMMAND,0);
pWnd->PostMessage(WM_LBUTTONUP,WM_COMMAND,0);
return TRUE;
}
break; }
}
return CDialog::PreTranslateMessage(pMsg);
}
我现在想要得就是当在对话框的一个编辑控件中按下ESC和ENTER时,由编辑控件来处理,而不是直接关闭对话框。
通过参考MFC源代码,初步知道了解决办法,你说对了一半,是要重载CDialog子类的PreTranslateMessage函数,但不能屏蔽基类CDialog的PreTranslateMessage函数调用,因为那样会屏蔽掉所有针对对话框的其他输入,对话框会毫无反应。应该在对基类PreTranslateMessage函数的调用前,将ESC和ENTER的消息筛选出来重发向当前具有焦点的窗口。至于CDialog在什么地方如何截取ENTER的,我实在没时间、精力查下去了,都是MFC,把事情搞得那么复杂,要是用SDK就简单多了,键盘消息都是直接发向当前唯一具有输入焦点的窗口的。
Nonzero if the message was translated and should not be dispatched; 0 if the message was not translated and should be dispatched.
非零的返回值会导致消息不再分发。