[英]How to prevent MFC dialog closing on Enter and Escape keys?
我知道一種防止 MFC 對話框在按下Enter或Esc鍵時關閉的方法,但我想了解該過程的更多詳細信息以及執行此操作的所有常用替代方法。
在此先感謝您的幫助。
當用戶在對話框中按下 Enter 鍵時,會發生兩種情況:
CDialog::SetDefID()
)。 然后將帶有此控件 ID 的 WM_COMMAND 發送到對話框。對於第一個選項,可能會發生默認控件的 ID 等於 IDOK。 那么結果將與第二個選項中的結果相同。
默認情況下,類CDialog
有一個用於調用CDialog::OnOk()
的WM_COMMAND(IDOK)
處理程序,這是一個虛函數,默認情況下它調用EndDialog(IDOK)
來關閉對話框。
因此,如果您想避免關閉對話框,請執行以下操作之一。
IDOK
以外的其他控件。EndDialog()
的WM_COMMAND(IDOK)
EndDialog()
。CDialog::OnOk()
並且不調用基本實現。 關於 IDCANCEL,它是類似的,但沒有等效的SetDefID()
並且 ESC 鍵是硬編碼的。 所以為了避免對話框被關閉:
EndDialog()
的WM_COMMAND(IDCANCEL)
EndDialog()
。CDialog::OnCancel()
並且不調用基本實現。上一個答案有一個替代方案,如果您希望仍然有一個確定/關閉按鈕,這將很有用。 如果您覆蓋 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);
}
@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);
}
記得在頭文件中添加virtual
。
在處理 Dialog 樣式的 MFC 應用程序時,框架會自動硬編碼一些必須覆蓋的項目,以防止應用程序在按下 ESC 或 Enter 鍵時退出。 但是有一種非常簡單的方法不需要任何特殊的東西,例如實現非常不推薦的 PreTranslateMessage()。
有三個功能需要到位:
在標題中,添加三個函數原型。 如果您想添加 WM_CLOSE 事件處理程序,您可以使用類向導,但只需輸入它就非常簡單。
// DefaultDialogAppDlg.h
//
class CDefaultDialogAppDlg : public CDialogEx
{
// ... other code
protected:
virtual void OnCancel(){} // inline empty function
virtual void OnOK(){} // inline empty function
public:
afx_msg void OnClose(); // message handler for WM_CLOSE
// ...other code
};
在 .cpp 文件中,將 ON_WM_CLOSE() 條目添加到消息映射和三個函數的定義中。 由於 OnCancel() 和 OnOK() 通常為空,如果需要,您可以將它們內聯到標頭中(看看我在第 1 步中做了什么?)。
.cpp 文件將包含以下內容:
// DefaultDialogAppDlg.cpp
// ... other code
BEGIN_MESSAGE_MAP(CDefaultDialogAppDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_CLOSE() // WM_CLOSE messages are handled here.
END_MESSAGE_MAP()
// ... other code
void CDefaultDialogAppDlg::OnClose()
{
// TODO: Add exit handling code here
// NOTE: to actually allow the program to end, call the base class
// version of either the OnOK() or OnCancel() function.
//CDialogEx::OnOK(); // returns 1 to theApp object
CDialogEx::OnCancel(); // returns 2 to theApp object
}
我只是覆蓋 OnOk 事件,而不是將消息傳遞給父對話框,什么都不做。
所以這樣做基本上很簡單:
void OnOk() override { /*CDialog::OnOK();*/ }
這應該可以防止對話框在按下回車/回車鍵時關閉。
確保你沒有#define CUSTOM_ID 2
因為2
已經定義為轉義而我認為1
是為輸入定義的? 如果我錯了,請糾正我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.