Resumo
Os aplicativos baseados no Windows geralmente exibem caixas de diálogo de entrada de dados para solicitar informações de usuários. Essas caixas de diálogo podem conter vários controles de edição e dois botões de comando (push), rotulados como OK e cancelar. Um exemplo de uma caixa de diálogo de entrada de dados é uma que solicita informações pessoais, como um número de CPF, endereço, identificação (ID) número, data/hora e assim por diante, de usuários. Cada um desses itens é inserido em um controle de edição. Por padrão, a tecla TAB é usada em uma caixa de diálogo para alternar o foco entre controles de edição. No entanto, como uma interface do usuário comum, uma delas também pode usar a tecla ENTER (RETURN) para mover-se entre os controles de edição (por exemplo, depois que o usuário insere uma informação, pressionar ENTER move o foco para o próximo campo). Há algumas maneiras de habilitar o uso da tecla ENTER para mover-se entre os controles de edição. Um método é usar o WM_COMMAND e as mensagens de notificação que vêm com ele na caixa de diálogo para controles de edição e botões. Outro método envolve a Subclassificação dos controles de edição. Um terceiro envolve o uso do App Studio e do assistente de classe e a criação de uma nova função de membro de caixa de diálogo.
Informações adicionais
Método I: (WM_COMMAND)
Esse método é baseado no seguinte comportamento de caixas de diálogo (Gerenciador de caixa de diálogo) e manuseio de foco no Windows. se uma caixa de diálogo ou um de seus controles atualmente tem o foco de entrada, pressionar a tecla ENTER faz com que o Windows envie uma mensagem WM_COMMAND com o parâmetro idItem (wParam) definido como a ID do botão de comando padrão. Se a caixa de diálogo não tiver um botão de comando padrão, o parâmetro idItem será definido como IDOK por padrão. Quando um aplicativo recebe a mensagem WM_COMMAND com idItem definido como a ID do botão de comando padrão, o foco permanece com o controle que tinha o foco antes da tecla ENTER ser pressionado. Chamar GetFocus () neste ponto retorna a alça do controle que tinha o foco antes da tecla ENTER ser pressionada. O aplicativo pode verificar essa alça de controle e determinar se ela pertence a qualquer um dos controles de edição na caixa de diálogo. Em caso afirmativo, o usuário estava inserindo dados em um dos controles de edição e depois disso, pressionado ENTER. Nesse ponto, o aplicativo pode enviar a mensagem WM_NEXTDLGCTL para a caixa de diálogo para mover o foco para o próximo controle. No entanto, se o foco era com um dos botões de comando (CANCEL ou OK), GetFocus () retorna uma alça de controle de botão, no qual o ponto um pode descartar a caixa de diálogo. O pseudo código para essa lógica é semelhante ao seguinte no procedimento de caixa de diálogo do aplicativo:
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
Esse método envolve a subclassificação/superclasse do controle de edição na caixa de diálogo. Depois que os controles de edição são emclasses ou superclassedos, todas as entradas do teclado são enviadas para o procedimento de superclasse/superclasse do controle de edição que tem o foco de entrada no momento, independentemente de a caixa de diálogo ter ou não um botão de comando padrão. O aplicativo pode interceptar as mensagens de tecla (ou carac), procurar a tecla ENTER e fazer o processamento de acordo. Veja a seguir um exemplo de procedimento de subclasse que procura a tecla 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 */
Método 3
Esse método envolve o uso do App Studio e do ClassWizard e a criação de uma nova função de membro de caixa de diálogo. Esse método permitirá que um usuário pressione a tecla ENTER e tenha o foco avançar para o próximo controle de edição. Se o foco estiver no momento no último controle de edição na caixa de diálogo, o foco será adiantado para o primeiro controle de edição. Primeiro, use o app Studio para alterar a ID do botão OK da caixa de diálogo. O comportamento padrão do App Studio é para dar ao botão OK o ID IDOK. A ID do botão OK deve ser alterada para outro valor, como IDC_OK. Além disso, altere as propriedades do botão OK para que ele não seja um botão padrão. Em seguida, use ClassWizard para criar um novo membro de caixa de diálogo funciton. Nomeie a nova função membro como algo como OnClickedOK. Essa função deve ser vinculada à mensagem BN_CLICKED do controle IDC_OK. Depois disso, escreva o corpo da função OnClickedOK. Você deve colocar o código que normalmente colocaria na função OnOK na nova função OnClickedOK, incluindo a função OnOK da classe. Adicione o seguinte protótipo ao arquivo de cabeçalho para a caixa de diálogo:
protected: virtual void OnOK();
Adicionar uma função OnOK à caixa de diálogo e o código é como demonstrado abaixo:
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(); }