Как предотвратить закрытие диалога MFC на клавишах Enter и Escape? - программирование

Как предотвратить закрытие диалога MFC на клавишах Enter и Escape?

Я знаю один метод предотвращения закрытия диалога MFC при нажатии клавиш Enter или Esc, но я хотел бы узнать больше деталей процесса и всех распространенных альтернативных методов для этого.

Заранее благодарим за помощь.

4b9b3361

Ответ 1

Когда пользователь нажимает клавишу Enter в диалоговом окне, могут произойти две вещи:

  • Диалог имеет элемент управления по умолчанию (см. CDialog::SetDefID()). Затем в диалог отправляется WM_COMMAND с идентификатором этого элемента управления.
  • В диалоговом окне отсутствует элемент управления по умолчанию. Затем в диалог отправляется WM_COMMAND с ID = IDOK.

При первом варианте может оказаться, что элемент управления по умолчанию имеет ID, равный IDOK. Тогда результаты будут такими же, что и во втором варианте.

По умолчанию класс CDialog имеет обработчик для WM_COMMAND(IDOK), который должен вызвать CDialog::OnOk(), то есть виртуальную функцию, и по умолчанию он вызывает EndDialog(IDOK), который закрывает диалог.

Итак, если вы хотите избежать закрытия диалогового окна, выполните одно из следующих действий.

  • Установите для элемента управления по умолчанию значение, отличное от IDOK.
  • Установите обработчик WM_COMMAND(IDOK), который не вызывает EndDialog().
  • Переопределить CDialog::OnOk() и не вызывать базовую реализацию.

О IDCANCEL, это похоже, но нет эквивалента SetDefID(), а клавиша ESC жестко запрограммирована. Чтобы избежать закрытия диалогового окна:

  • Установите обработчик для WM_COMMAND(IDCANCEL), который не вызывает EndDialog().
  • Переопределить CDialog::OnCancel() и не вызывать базовую реализацию.

Ответ 2

Существует альтернатива предыдущему ответу, что полезно, если вы хотите иметь кнопку OK/Close. Если вы переопределите функцию PreTranslateMessage, вы можете поймать использование VK_ESCAPE/VK_RETURN следующим образом:

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);
}