Cómo usar la tecla entrar en los controles de edición de un cuadro de diálogo


Resumen


Las aplicaciones basadas en Windows suelen mostrar cuadros de diálogo de entrada de datos para solicitar información a los usuarios. Estos cuadros de diálogo pueden contener varios controles de edición y dos botones de comando (inserción), denominados aceptar y cancelar. Un ejemplo de un cuadro de diálogo de entrada de datos es aquél que solicita información personal, como el número de seguridad social, la dirección, el número de identificación (ID.), la fecha y la hora, etc., de los usuarios. Cada uno de estos elementos se escribe en un control de edición. De forma predeterminada, se usa la tecla TAB en un cuadro de diálogo para desplazar el foco entre controles de edición. Sin embargo, como una interfaz de usuario común, también puede usar la tecla entrar (retorno) para desplazarse entre los controles de edición (por ejemplo, después de que el usuario escribe un fragmento de información, al presionar entrar el foco se mueve al siguiente campo). Hay varias maneras de habilitar el uso de la tecla entrar para desplazarse entre los controles de edición. Un método es usar WM_COMMAND y los mensajes de notificación que vienen con él en el cuadro de diálogo para editar controles y botones. Otro método implica subclases de los controles de edición. Un tercero implica el uso de App Studio y asistente de clases y la creación de una nueva función miembro de cuadro de diálogo.

Más información


Método I: (WM_COMMAND)

Este método se basa en el siguiente comportamiento de los cuadros de diálogo (Administrador de cuadros de diálogo) y en Windows. Si un cuadro de diálogo o uno de sus controles tiene actualmente el foco de entrada, presionar la tecla entrar hace que Windows envíe un mensaje WM_COMMAND con el parámetro idItem (wParam) establecido en el identificador del botón de comando predeterminado. Si el cuadro de diálogo no tiene un botón de comando predeterminado, el parámetro idItem se establece en IDOK de forma predeterminada. Cuando una aplicación recibe el WM_COMMAND mensaje con idItem establecido en el identificador del botón de comando predeterminado, el foco permanece con el control que tenía el foco antes de que se presionara la tecla entrar. Al llamar a GetFocus () en este punto, se devuelve el controlador del control que tenía el foco antes de que se presionara la tecla entrar. La aplicación puede comprobar este controlador y determinar si pertenece a cualquiera de los controles de edición en el cuadro de diálogo. Si es así, significa que el usuario ha introducido datos en uno de los controles de edición y, después de hacerlo, presionó entrar. En este punto, la aplicación puede enviar el WM_NEXTDLGCTL mensaje al cuadro de diálogo para mover el foco al siguiente control. Sin embargo, si el foco era con uno de los botones de comando (cancelar o aceptar), entonces GetFocus () devuelve un controlador de botón, en el que se puede descartar uno de los cuadros de diálogo. El pseudo-código de esta lógica se asemeja a lo siguiente en el procedimiento de cuadro de diálogo de la aplicación:
     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 ;

Método II

Este método implica la subclase o la superclase del control de edición en el cuadro de diálogo. Una vez que los controles de edición son de subclase o superclase, todas las entradas de teclado se envían al procedimiento de subclase o superclase del control de edición que tiene el foco de entrada actualmente, independientemente de si el cuadro de diálogo tiene un botón de comando predeterminado o no. La aplicación puede reventar los mensajes clave abajo (o Char), buscar la tecla entrar y realizar el procesamiento según corresponda. A continuación se muestra un procedimiento de subclase que busca la tecla entrar:
   //*-------------------------------------------------------------------   //| 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 */ 

Método 3

Este método implica el uso de App Studio y ClassWizard y la creación de una nueva función miembro de cuadro de diálogo. Este método permitirá al usuario presionar la tecla entrar y centrar el foco en el siguiente control de edición. Si el foco está actualmente en el último control de edición del cuadro de diálogo, el foco se desplazará al primer control de edición. En primer lugar, use App Studio para cambiar el identificador del botón Aceptar del cuadro de diálogo. El comportamiento predeterminado de App Studio es dar al botón aceptar el identificador IDOK. El identificador del botón Aceptar debe cambiarse a otro valor, como IDC_OK. Además, cambie las propiedades del botón Aceptar para que no sea un botón de opción predeterminado. A continuación, use ClassWizard para crear un nuevo miembro de cuadro de diálogo funciton. Asigne un nombre a la nueva función miembro como OnClickedOK. Esta función se debe vincular al BN_CLICKED mensaje del control de IDC_OK. Una vez hecho esto, escribe el cuerpo de la función OnClickedOK. Debe colocar el código que normalmente pondría en la función OnOK en la nueva función OnClickedOK, incluida la función OnOK de clase. Agregue el siguiente prototipo al archivo de encabezado para el cuadro de diálogo:
   protected:      virtual void OnOK();
Agregue una función OnOK al cuadro de diálogo y el código es como se muestra a continuación:
   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();   }