CFindReplaceDialog 是 Windows 唯一的非模態通用對話框,不像 CFileDialog 等以 DoModal() 阻塞呼叫執行緒,它必須以 new 配置記憶體、Create() 初始化、ShowWindow() 顯示,並透過視窗訊息回報使用者操作。
在接收訊息的視圖類 (如 CEditTestView) 中:
// 標頭檔
class CEditTestView : public CFormView {
// ...
afx_msg LONG OnFindReplace(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
};
// 實作檔
static UINT WM_FINDREPLACE = ::RegisterWindowMessage(FINDMSGSTRING);
BEGIN_MESSAGE_MAP(CEditTestView, CFormView)
ON_REGISTERED_MESSAGE(WM_FINDREPLACE, OnFindReplace)
END_MESSAGE_MAP()
RegisterWindowMessage(FINDMSGSTRING) 取得唯一訊息 ID,ON_REGISTERED_MESSAGE 將其導向 OnFindReplace。註冊後,ClassWizard 會出現 ID_EDIT_FIND、ID_EDIT_REPLACE 供選單綁定。
void CEditTestView::OnEditFind() {
CFindReplaceDialog* pDlg = new CFindReplaceDialog();
pDlg->Create(TRUE, NULL, NULL, FR_DOWN, this); // TRUE=純尋找對話框
pDlg->ShowWindow(SW_SHOW);
}
Create 原型:
BOOL Create(BOOL bFindDialogOnly, LPCTSTR lpszFindWhat, LPCTSTR lpszReplaceWhat=NULL, DWORD dwFlags=FR_DOWN, CWnd* pParentWnd=NULL);
OnFindReplaceLONG CEditTestView::OnFindReplace(WPARAM wParam, LPARAM lParam) {
CFindReplaceDialog* pDlg = CFindReplaceDialog::GetNotifier(lParam);
if (pDlg->IsTerminating()) {
// 使用者關閉對話框,刪除物件
delete pDlg; // 或由建立者負責刪除
return 0;
}
if (pDlg->FindNext()) {
CString strFind = pDlg->GetFindString();
BOOL bMatchCase = pDlg->MatchCase();
BOOL bWholeWord = pDlg->MatchWholeWord();
BOOL bDirectionDown = pDlg->SearchDown();
// 執行實際尋找邏輯...
}
if (pDlg->ReplaceCurrent() || pDlg->ReplaceAll()) {
CString strFind = pDlg->GetFindString();
CString strReplace = pDlg->GetReplaceString();
// 執行取代邏輯...
}
return 0;
}
GetNotifier(lParam) 從 lParam 取得對話框指標,IsTerminating() 偵測關閉事件,FindNext()/ReplaceCurrent()/ReplaceAll() 判斷使用者動作。
dwFlags 對照表| 旗標 | 效果 |
|---|---|
| FR_DOWN | 預設「向下尋找」 |
| FR_HIDEUPDOWN | 隱藏方向單選鈕 |
| FR_HIDEMATCHCASE | 隱藏「大小寫」核取方塊 |
| FR_HIDEWHOLEWORD | 隱藏「全字比對」核取方塊 |
| FR_MATCHCASE | 預設勾選「大小寫」 |
| FR_WHOLEWORD | 預設勾選「全字比對」 |
| FR_NOUPDOWN | 停用方向選擇 |
| FR_SHOWHELP | 顯示說明按鈕 |
非模態對話框 不由框架自動刪除,必須在 IsTerminating() 時 delete pDlg,或由建立視窗在 OnDestroy 統一清理,否則會造成記憶體洩漏。