摘要
以 Windows 為基礎的應用程式通常會顯示資料輸入對話方塊,以向使用者要求資訊。 這些對話方塊可能包含數個編輯控制項,以及兩個命令(推入)按鈕,標示為 [確定] 和 [取消]。 [資料輸入] 對話方塊的範例就是要求使用者輸入個人資訊,例如社會保險號碼、位址、身分識別(ID)號碼、日期/時間等。 這些專案中的每一個都是在編輯控制項中輸入。根據預設,會在對話方塊中使用 TAB 鍵,以將焦點移到 [編輯] 控制項之間。 但作為常見的使用者介面,您也可以使用 ENTER (RETURN)鍵在編輯控制項之間移動(例如,使用者輸入一條資訊之後,按下 ENTER 就會將焦點移到下一個欄位)。有幾種方式可讓您使用 ENTER 鍵在 [編輯] 控制項之間移動。 其中一個方法是在編輯控制項和按鈕的對話方塊中使用 WM_COMMAND 及隨附的通知訊息。 另一種方法是針對編輯控制項進行子類分類。 第三個涉及使用 App Studio 和課程嚮導,並建立新的對話方塊成員函數。
其他相關資訊
方法 I:(WM_COMMAND)
這個方法是以對話方塊的下列行為為基礎(對話方塊管理員),以及 Windows 中的焦點處理。如果對話方塊或其中一個控制項目前有輸入焦點,則按 ENTER 鍵會導致 Windows 傳送 WM_COMMAND 訊息,並將 idItem (wParam)參數設定為預設命令按鈕的識別碼。 如果對話方塊沒有預設的命令按鈕,則 idItem 參數預設會設定為 IDOK。當應用程式收到 idItem 設定為預設命令按鈕識別碼的 WM_COMMAND 訊息時,焦點會保持在按下 ENTER 鍵前擁有焦點的控制項。 在此點呼叫 GetFocus ()會傳回在按下 ENTER 鍵前,擁有焦點的控制項控制碼。 應用程式可以檢查這個控制控制碼,並判斷它是否屬於對話方塊中的任何編輯控制項。 如果有的話,使用者是在其中一個編輯控制項中輸入資料,然後在執行此動作之後,按下 ENTER。 此時,應用程式可以將 WM_NEXTDLGCTL 的訊息傳送到對話方塊,以將焦點移至下一個控制項。不過,如果焦點是使用其中一個命令按鈕([取消] 或 [確定]),則 GetFocus ()會傳回一個按鈕控制項控點,這時,點即可關閉對話方塊。 此邏輯的偽程式碼類似下列在應用程式的對話方塊程式中:
case WM_COMMAND: if(wParam=IDOFDEFBUTTON || IDOK) { // User has hit the ENTER key. hwndTest = GetFocus() ; retVal = TesthWnd(hWndTest) ; //Where retVal is a boolean variable that indicates whether //the hwndTest is the handle of one of the edit controls. if(hwndTest) { //Focus is with an edit control, so do not close the dialog. //Move focus to the next control in the dialog. PostMessage(hDlg, WM_NEXTDLGCTL, 0, 0L) ; return TRUE ; } else { //Focus is with the default button, so close the dialog. EndDialog(hDlg, TRUE) ; return FALSE ; } } break ;
Method II
這個方法涉及在對話方塊中將 [編輯] 控制項為子類/superclassing。 只要編輯控制項是 [細分] 或 [superclassed],無論對話方塊是否有預設的命令按鈕,所有的鍵盤輸入都會傳送到目前擁有輸入焦點的編輯控制項的子類/超類程式。 應用程式可以將鑰匙鍵(或 char)訊息補漏白,尋找 ENTER 鍵,並據此進行處理。 下列是尋找 ENTER 鍵的範例子類程式:
//*------------------------------------------------------------------- //| Title: //| SubClassProc //| //| Parameters: //| hWnd - Handle to the message's destination window //| wMessage - Message number of the current message //| wParam - Additional info associated with the message //| lParam - Additional info associated with the message //| //| Purpose: //| This is the window procedure used to subclass the edit control. //*--------------------------------------------------------------------- long FAR PASCAL SubProc(HWND hWnd, WORD wMessage,WORD wParam,LONG lParam) { switch (wMessage) { case WM_GETDLGCODE: return (DLGC_WANTALLKEYS | CallWindowProc(lpOldProc, hWnd, wMessage, wParam, lParam)); case WM_CHAR: //Process this message to avoid message beeps. if ((wParam == VK_RETURN) || (wParam == VK_TAB)) return 0; else return (CallWindowProc(lpOldProc, hWnd, wMessage, wParam, lParam)); case WM_KEYDOWN: if ((wParam == VK_RETURN) || (wParam == VK_TAB)) { PostMessage (ghDlg, WM_NEXTDLGCTL, 0, 0L); return FALSE; } return (CallWindowProc(lpOldProc, hWnd, wMessage, wParam, lParam)); break ; default: break; } /* end switch */
方法 3
這個方法涉及使用 App Studio 及 ClassWizard 並建立新的對話方塊成員函數。這個方法可讓使用者按 ENTER 鍵,並將焦點移到下一個編輯控制項。 如果焦點目前在對話方塊中的最後一個編輯控制項上,則焦點會移至第一個編輯控制項。首先,使用 App Studio 變更對話方塊 [確定] 按鈕的識別碼。 App Studio 的預設行為是將 [確定] 按鈕設為 [識別碼 IDOK]。 [確定] 按鈕的識別碼應該變更為其他值,例如 [IDC_OK]。 此外,您也可以變更 [確定] 按鈕的屬性,使其不是預設的按鍵。接著,使用 ClassWizard 建立新的對話方塊成員 funciton。 將新的成員函數命名為 OnClickedOK。 此函數應與來自 IDC_OK 控制項的 BN_CLICKED 訊息相關聯。完成這項操作後,請撰寫 OnClickedOK 函數的主體。 您應該將您通常會放入 OnOK 函數中的程式碼放入新的 OnClickedOK 函數中,包括類別的 OnOK 函數。在對話方塊的標頭檔中新增下列原型:
protected: virtual void OnOK();
在對話方塊中新增 OnOK 函數,程式碼如下所示:
void CMyDialog::OnOK() { CWnd* pwndCtrl = GetFocus(); CWnd* pwndCtrlNext = pwndCtrl; int ctrl_ID = pwndCtrl->GetDlgCtrlID(); switch (ctrl_ID) { case IDC_EDIT1: pwndCtrlNext = GetDlgItem(IDC_EDIT2); break; case IDC_EDIT2: pwndCtrlNext = GetDlgItem(IDC_EDIT3); break; case IDC_EDIT3: pwndCtrlNext = GetDlgItem(IDC_EDIT4); break; case IDC_EDIT4: pwndCtrlNext = GetDlgItem(IDC_EDIT1); break; case IDOK: CDialog::OnOK(); break; default: break; } pwndCtrlNext->SetFocus(); }