web-dev-qa-db-fra.com

Comment empêcher la fermeture du dialogue MFC sur les touches Entrée et Échap?

Je connais une méthode pour empêcher la fermeture d’un dialogue MFC lorsque le Enter ou Esc Les touches sont enfoncées, mais j'aimerais connaître plus de détails sur le processus et toutes les méthodes alternatives alternatives pour le faire.

Merci d'avance pour votre aide.

17
Laxman Sahni

Lorsque l'utilisateur appuie sur la touche Entrée dans une boîte de dialogue, deux choses peuvent se produire:

  1. La boîte de dialogue a un contrôle par défaut (voir CDialog::SetDefID()). Ensuite, un WM_COMMAND avec l'ID de ce contrôle est envoyé à la boîte de dialogue.
  2. La boîte de dialogue n'a pas de contrôle par défaut. Ensuite, WM_COMMAND avec ID = IDOK est envoyé à la boîte de dialogue.

Avec la première option, il peut arriver que le contrôle par défaut ait un ID égal à IDOK. Ensuite, les résultats seront les mêmes que dans la deuxième option.

Par défaut, la classe CDialog a un gestionnaire pour la WM_COMMAND(IDOK) qui doit appeler CDialog::OnOk(), c'est une fonction virtuelle et, par défaut, elle appelle EndDialog(IDOK) qui ferme la boîte de dialogue.

Par conséquent, si vous souhaitez éviter de fermer la boîte de dialogue, effectuez l’une des opérations suivantes.

  1. Définissez le contrôle par défaut sur autre que IDOK.
  2. Définissez un gestionnaire sur WM_COMMAND(IDOK) qui n'appelle pas EndDialog().
  3. Remplacez CDialog::OnOk() et n'appelez pas l'implémentation de base.

A propos d'IDCANCEL, il est similaire mais il n'y a pas d'équivalent SetDefID() et la touche ESC est codée en dur. Donc, pour éviter que le dialogue ne soit fermé:

  1. Définissez un gestionnaire sur WM_COMMAND(IDCANCEL) qui n'appelle pas EndDialog().
  2. Remplacez CDialog::OnCancel() et n'appelez pas l'implémentation de base.
30
rodrigo

Il existe une alternative à la réponse précédente, ce qui est utile si vous souhaitez toujours avoir un bouton OK/Fermer. Si vous remplacez la fonction PreTranslateMessage, vous pouvez utiliser VK_ESCAPE/VK_RETURN comme suit:

BOOL MyCtrl::PreTranslateMessage(MSG* pMsg)
{
    if( pMsg->message == WM_KEYDOWN )
    {
        if(pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
        {
            return TRUE;                // Do not process further
        }
    }

    return CWnd::PreTranslateMessage(pMsg);
}
29

Je remplace simplement l'événement OnOk et au lieu de transmettre le message à la boîte de dialogue parent, je ne fais rien. 
C'est donc aussi simple que ça:

void OnOk() override { /*CDialog::OnOK();*/ }

Cela devrait empêcher la boîte de dialogue de se fermer lorsque vous appuyez sur la touche Entrée/Retour.

0
Gilad Reich