C++ 如何防止 MFC 对话框在 Enter 和 Escape 键上关闭?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17828258/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to prevent MFC dialog closing on Enter and Escape keys?
提问by Laxman Sahni
I know one method of preventing an MFC dialog from closing when the Enteror Esckeys are pressed, but I'd like to know more details of the process and all the common alternative methods for doing so.
我知道一种防止 MFC 对话框在按下Enter或Esc键时关闭的方法,但我想了解该过程的更多详细信息以及所有常见的替代方法。
Thanks in advance for any help.
在此先感谢您的帮助。
回答by rodrigo
When the user presses Enter key in a dialog two things can happen:
当用户在对话框中按下 Enter 键时,会发生两种情况:
- The dialog has a default control (see
CDialog::SetDefID()
). Then a WM_COMMAND with the ID of this control is sent to the dialog. - The dialog does not have a default control. Then WM_COMMAND with ID = IDOK is sent to the dialog.
- 该对话框有一个默认控件(请参阅
CDialog::SetDefID()
)。然后将带有此控件 ID 的 WM_COMMAND 发送到对话框。 - 该对话框没有默认控件。然后将 ID = IDOK 的 WM_COMMAND 发送到对话框。
With the first option, it may happen that the default control has a ID equal to IDOK. Then the results will be the same that in the second option.
对于第一个选项,可能会发生默认控件的 ID 等于 IDOK。那么结果将与第二个选项中的结果相同。
By default, class CDialog
has a handler for the WM_COMMAND(IDOK)
that is to call to CDialog::OnOk()
, that is a virtual function, and by default it calls EndDialog(IDOK)
that closes the dialog.
默认情况下,类CDialog
有一个处理程序,用于WM_COMMAND(IDOK)
调用CDialog::OnOk()
,这是一个虚函数,默认情况下它调用EndDialog(IDOK)
关闭对话框。
So, if you want to avoid the dialog being closed, do one of the following.
因此,如果您想避免关闭对话框,请执行以下操作之一。
- Set the default control to other than
IDOK
. - Set a handler to the
WM_COMMAND(IDOK)
that does not callEndDialog()
. - Override
CDialog::OnOk()
and do not call the base implementation.
- 将默认控件设置为
IDOK
. - 将处理程序设置为
WM_COMMAND(IDOK)
不调用EndDialog()
. - 覆盖
CDialog::OnOk()
并且不调用基本实现。
About IDCANCEL, it is similar but there is not equivalent SetDefID()
and the ESC key is hardcoded. So to avoid the dialog being closed:
关于IDCANCEL,它是相似的,但没有等价物SetDefID()
,ESC 键是硬编码的。所以为了避免对话框被关闭:
- Set a handler to the
WM_COMMAND(IDCANCEL)
that does not callEndDialog()
. - Override
CDialog::OnCancel()
and do not call the base implementation.
- 将处理程序设置为
WM_COMMAND(IDCANCEL)
不调用EndDialog()
. - 覆盖
CDialog::OnCancel()
并且不调用基本实现。
回答by The Forest And The Trees
There is an alternative to the previous answer, which is useful if you wish to still have an OK / Close button. If you override the PreTranslateMessage function, you can catch the use of VK_ESCAPE / VK_RETURN like so:
上一个答案有一个替代方案,如果您希望仍然有一个确定/关闭按钮,这将很有用。如果你覆盖 PreTranslateMessage 函数,你可以像这样捕捉 VK_ESCAPE / VK_RETURN 的使用:
BOOL MyCtrl::PreTranslateMessage(MSG* pMsg)
{
if( pMsg->message == WM_KEYDOWN )
{
if(pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
{
return TRUE; // Do not process further
}
}
return CWnd::PreTranslateMessage(pMsg);
}
回答by Laxman Sahni
I simply override the OnOk event and instead of passing the message to the parent dialog, do nothing.
So it's basically simple as doing so:
我只是覆盖 OnOk 事件,而不是将消息传递给父对话框,什么都不做。
所以这样做基本上很简单:
void OnOk() override { /*CDialog::OnOK();*/ }
This should prevent the dialog from closing when pressing the return/enter key.
这应该可以防止对话框在按下回车/回车键时关闭。
回答by Kazem Sami
Make sure you don't #define CUSTOM_ID 2
because 2
is already defined for escape and I think 1
is defined for enter? Correct me if i'm wrong.
确保你没有#define CUSTOM_ID 2
因为2
已经定义为转义而我认为1
是为输入定义的?如果我错了纠正我。
回答by user12425014
The answer of @the-forest-and-the-trees is quite good. Except one situation which was addressed by @oneworld. You need to filter messages which are not for dialog window:
@the-forest-and-the-trees 的回答很好。除了@oneworld 解决的一种情况。您需要过滤不是对话窗口的消息:
BOOL CDialogDemoDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->hwnd == this->m_hWnd && pMsg->message == WM_KEYDOWN)
{
if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
{
return TRUE; // Do not process further
}
}
return CWnd::PreTranslateMessage(pMsg);
}
Remember to add virtual
in the header file.
记得virtual
在头文件中添加。