概要
Windows ベースのアプリケーションでは、多くの場合、ユーザーからの情報を要求するためのデータ入力ダイアログボックスが表示できます。 これらのダイアログボックスには、複数の編集コントロールと、[OK] と [キャンセル] というラベルの2つのコマンドボタンが含まれている場合があります。 データ入力ダイアログボックスの例としては、社会保障番号、住所、識別 (ID) 番号、日付/時刻など、ユーザーからの個人情報を要求するものがあります。 各項目が編集コントロールに入力されます。既定では、ダイアログボックスで TAB キーを使って、編集コントロール間でフォーカスを移動します。 ただし、一般的なユーザーインターフェイスでは、ENTER (RETURN) キーを使って編集コントロール間を移動することもできます (たとえば、ユーザーが情報の一部を入力した後、ENTER キーを押すと、フォーカスが次のフィールドに移動します)。ENTER キーを使用して編集コントロール間を移動するには、いくつかの方法があります。 1つの方法は、編集コントロールやボタンのダイアログボックスで、WM_COMMAND とそれに付属する通知メッセージを使うことです。 他の方法では、編集コントロールのサブクラス化が必要になります。 3番目に、アプリ Studio とクラスウィザードを使用し、新しいダイアログボックスメンバー関数を作成します。
詳細情報
方法 I: (WM_COMMAND)
この方法は、ダイアログボックス (ダイアログマネージャー) の次の動作と、Windows でのフォーカス処理に基づいています。ダイアログボックスまたはそのコントロールの1つにフォーカスがある場合は、ENTER キーを押すと、idItem (wParam) パラメーターが既定のコマンドボタンの ID に設定された WM_COMMAND メッセージが送信されます。 ダイアログボックスに既定のコマンドボタンがない場合は、既定で idItem パラメーターが IDOK に設定されます。IdItem が既定のコマンドボタンの ID に設定されたメッセージを WM_COMMAND 受信すると、ENTER キーを押した前にフォーカスが置かれていたコントロールでフォーカスが移動します。 この時点で GetFocus () を呼び出すと、ENTER キーが押される前にフォーカスが設定されていたコントロールのハンドルが返されます。 このコントロールハンドルをチェックして、ダイアログボックスのいずれかの編集コントロールに属しているかどうかを確認できます。 その場合は、ユーザーがいずれかの編集コントロールにデータを入力した後、ENTER キーを押します。 この時点で、アプリケーションは、次のコントロールにフォーカスを移動するためのダイアログボックスに WM_NEXTDLGCTL メッセージを送ることができます。ただし、フォーカスがコマンドボタンのいずれか (キャンセルまたは OK) であった場合は、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 ;
方法 II
この方法では、ダイアログボックスの [編集] コントロールのサブクラス化/superclassing を行います。 編集コントロールがサブクラス化または superclassed されると、すべてのキーボード入力には、ダイアログボックスに既定のコマンドボタンがあるかどうかに関係なく、現在入力フォーカスがある編集コントロールのサブクラス/スーパークラスのプロシージャが送信されます。 アプリケーションでは、キーの下 (または文字) のメッセージをトラップし、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
この方法では、アプリ Studio と ClassWizard を使って、新しいダイアログボックスのメンバー関数を作成します。このメソッドを使うと、ユーザーは ENTER キーを押して次の編集コントロールにフォーカスを移動することができます。 現在フォーカスがダイアログボックスの最後の編集コントロールにある場合、フォーカスは最初の編集コントロールに進みます。最初に、アプリ Studio を使って、ダイアログボックスの [OK] ボタンの ID を変更します。 App Studio の既定の動作では、[OK] ボタンに ID IDOK を指定します。 [OK] ボタンの ID は、IDC_OK などの別の値に変更する必要があります。 また、既定のプッシュボタンではなく、[OK] ボタンのプロパティを変更します。次に、ClassWizard を使用して、新しいダイアログボックスのメンバー funciton を作成します。 新しいメンバー関数に「OnClickedOK」のような名前を付けることができます。 この関数は、IDC_OK コントロールからの BN_CLICKED メッセージに関連付けられている必要があります。これが完了したら、OnClickedOK 関数の本文を記述します。 通常、OnOK 関数に挿入するコードは、クラスの OnOK 関数を含む新しい OnClickedOK 関数に配置する必要があります。ダイアログボックスのヘッダーファイルに次のプロトタイプを追加します。
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(); }