采用基于默认 MFC 的单对话框应用程序,我试图防止 Escape 或 Enter 键将导致对话框关闭的默认行为。
然而,虽然我能够实现这一点,但我发现应用程序退出代码现在总是返回 20,无论我传递给 EndDialog 的值如何。
在下面的测试中我阻止了 Escape 键:
BEGIN_MESSAGE_MAP(CMFCApplication10Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDCANCEL, &CMFCApplication10Dlg::OnBnClickedCancel) // Triggers when Escape key pressed
ON_WM_CLOSE() // Added WM_CLOSE to handle the close
END_MESSAGE_MAP()
OnBnClickedCancel 在按 Escape 时发生,因此为了防止应用程序关闭,我不调用 OnCancel
void CMFCApplication10Dlg::OnBnClickedCancel()
{
//CDialogEx::OnCancel(); // Not calling OnCancel
}
我添加了 OnClose 以允许使用右上角的“关闭”按钮仍然可以关闭对话框
void CMFCApplication10Dlg::OnClose()
{
CDialogEx::EndDialog(0); // Call the EndDialog with 0
}
如何禁用退出键并返回退出代码 0
预期: 退出代码 0
实际: 获得退出代码 20
当您创建 MFC“对话框应用程序”时,您通常希望禁用 Enter 和 [sc] 键处理,因为这是主应用程序窗口,同时仍然能够从系统菜单或标题栏上的关闭按钮。
对于 [Enter] 键,您可以覆盖对话框的
OnOK()
成员(默认实现关闭对话框):
void CMyDlg::OnOK()
{
// CDialogEx::OnOK(); Don't Close
}
对于 [Esc] 键有多种技巧。一种是覆盖
OnCancel()
成员:
void CMyDlg::OnCancel()
{
// Disable Closing on Esc press
if ((GetKeyState(VK_ESCAPE) & 0x8000) == 0)
CDialogEx::OnCancel(); // Close only if NOT caused by [Esc]
}
或者覆盖
OnCancel()
并向向导生成的 OnSysCommand()
成员添加几行:
void CMyDlg::OnCancel()
{
//CDialogEx::OnCancel(); Don't Close
}
void CMyDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else if (nID == SC_CLOSE) // Add these 2 lines
CDialogEx::OnCancel();
else CDialogEx::OnSysCommand(nID, lParam);
}
其他开发人员会覆盖
PreTranslateMessage()
成员。
至于退出代码,我认为它根本没有意义,正如我在评论中指出的那样。如果单击 [X] 按钮,应用程序将返回 0,但它还应该返回什么?在什么条件下?
无论如何,
CWinApp
派生自CWinThread
,您可以尝试覆盖Run()
,并在实现中调用父类(CWinApp::Run()
或CWinAppEx::Run()
)丢弃其返回值并始终返回0。向导-对于对话框应用程序,生成的 InitInstance()
覆盖返回 FALSE
,这意味着初始化失败,这就是为什么您可能会得到非零退出代码。
旁注,如果您的项目是新的,并且您想要的只是一个显示“主窗体”的 MFC 应用程序,例如 VB 或 C#,您可以尝试不使用“对话框应用程序”,而是使用没有文档/的 SDI 应用程序查看支持(取消选中该选项)。但它仍然包含一个视图对象。视图类型可以是
CFormView
,这是基于对话框资源的视图,应用程序表现更好,避免了应用程序中的问题,支持 ON_UPDATE_COMMAND_UI
处理程序和键盘加速器等功能,并提供了诸如工具栏、状态栏和可停靠窗格,全部由向导生成。也就是说,它是一个正确的应用程序,而不是一个重新用作应用程序窗口的对话框。