c++ MFC筆記010 CEdit控件的輸入焦點傳遞
阿新 • • 發佈:2019-03-03
保存 col 開始 long lpar 有關 設置 rep 三種
一 引入
當一個對話框有多個CEdit時,當在一個編輯框裏輸入文本按Enter時,對話框將關閉。原因是對話框有一個IDOK按鈕,它的Default Button屬性被設置為True了。當按下該鍵時,基類調用了CDialogEx::OnOK();它把對話框關閉了。雙擊IDOK,將CDialogEx::OnOK()刪除,再按下IDOK時,對話框沒有關閉。分析:所有消息都要通過窗口過程來調用,Enter也是一個字符消息,因此可以通過處理字符消息,來判斷是否按下Enter,如果按下,則將焦點設置到下一個編輯框。但是由於窗口過程函數完成於窗口類設計時,在窗口類創建完後如何修改窗口過程?
二 修改窗口過程
使用LONG::SetWindowLong(),何時修改?VS2015 消息列表中找不到WM_INITDIALOG(該消息產生於對話框及其子控件創建完成後,對話框顯示之前發出來的消息)。因此需要添加虛函數:OnInitDialog()。如果在OnCreate中創建,將得到一個無效指針。
//缺省的IDOK消息響應函數 void CFstDlg::OnBnClickedOk() { GetNextDlgTabItem(GetFocus())->SetFocus(); } WNDPROC preProc; //用於保存類設計時的窗口過程函數 //新的過程處理函數HRESULT CALLBACK newProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) //註意 該過程是為IDC_EDIT1服務的,因此hwnd是指IDC_EDIT1 { if (uMsg == WM_CHAR && 0xD==wParam) //對於一個WM_CHAR消息,wParam保存了字符的ASCII碼 { /*方法1*/ ////如果是Enter按下,就在這裏改變焦點 //::SetFocus(GetNextWindow(hwnd,GW_HWNDNEXT));////至此 編譯無錯誤,但在編輯框1按下按鈕並沒有把光標設置在下一個編輯框。原因是沒有將IDC_EDIT1屬性Multiline設置為Ture,它就不能接受回車 ////在資源視圖中,將三個CEdit的屬性都設置為多行,讓它們都能接受Enter鍵 結果:IDC_EDIT1成功切換到IDC_EDIT2,但是IDC_EDIT2無法繼續切換到IDC_EDIT3 ////如果用上面GetNextWindow函數去順次切換焦點,則顯得麻煩,因此用如下辦法: /*方法2*/ //參數1:開始查找時的窗口句柄,參數2:它跟要查找的句柄的關系:GW_CHILD GW_HWNDNEXT GW_HWNDPREV等 具體看MSDN //::SetFocus(GetWindow(hwnd, GW_HWNDNEXT)); //但是從第二個開始還是沒有跳轉到第三個編輯框 /*方法3: GetNextDlgTabItem*/ //::SetFocus(::GetNextDlgTabItem(GetParent(hwnd),hwnd,FALSE)); //同樣從第二個開始不能正確切換到第三個編輯框,而是跳轉到IDOK按鈕上去了 //以上三種方式都顯得麻煩 /*方法4 利用缺省按鈕來實現*/ //1. 重新設置所有Edit的Multiline為False //2. 中完成把 GetDlgItem(IDC_EDIT1)->GetNextWindow()->SetFocus(); 這句代碼放在OnBnClickedOk()中,但是情況同前,原因是ID寫死了 //3. 動態修改ID GetFocus()->->GetNextWindow()->SetFocus(); 把上面的代碼換成這句就可以正確傳遞了 //4. 當一只按回車時,出現非法訪問的錯誤。原因是最後一個窗口它沒有下一個窗口了,此時它返回一個空指針 //5. 換成這個 GetFocus()->->GetWindow(GW_HWNDNEXT)->SetFocus(); 還是一樣的錯誤 //6. 在把上面這句切換成:GetNextDlgTabItem(GetFocus())->SetFocus(); 此時不再報錯,按Enter會循環切換焦點到TabStop=True的控件上 //7. 如果需要改變Tab鍵順序,切換到資源視圖->雙擊某個對話框資源打開->此時菜單欄多了個[格式]->Tab鍵順序 或者直接Ctrl+D 打開或關閉Tab鍵順序 return 1L; } else { return preProc(hwnd,uMsg,wParam,lParam); //交給先前的消息處理 } } BOOL CFstDlg::OnInitDialog() { CDialogEx::OnInitDialog(); preProc = (WNDPROC)SetWindowLong(GetDlgItem(IDC_EDIT1)->m_hWnd,GWL_WNDPROC,(LONG)newProc); return TRUE; // return TRUE unless you set the focus to a control // 異常: OCX 屬性頁應返回 FALSE }
註意:IDOK是系統的,它是缺省的,IDC_OK是自定義的
c++ MFC筆記010 CEdit控件的輸入焦點傳遞