Как использовать клавиши акселераторов в
модальном диалоге, выступащем в качестве
главного окна
Пример TRACER, поставляемый с Microsoft Foundation Class Library,
использует модальный диалог в качестве
основного окна. Многие приложения, использующие
эту технологию так же включают главное меню в
диалоговом окне (пример TRACER не использует меню).
Как правило, один или более пунктов меню связаны
с клавиатурными акселераторами. Ниже описанны
шаги, которые необходимо предпринять для того,
чтобы добавить меню и акселераторы в пример TRACER.
Типичное приложение, разработанное под Windows с
использованием Си и Microsoft Windows Software Development Kit (SDK),
которое использует клавиатурные акселераторы,
вызывает функцию TranslateAccelerator() в основном цикле
сообщений. Однако, если использовать в качестве
главного окна модальный диалог, то приложение не
будет иметь основного цикла сообщений; вместо
этого чтобы транслировать и посылать сообщения,
приложение будет использовать диалоговый цикл
сообщений (встроенный в Windows). Естевственно, так
как такой цикл сообщений не предназначен для
обработки акселераторов, то он не будет вызывать
функцию TranslateAccelerator().
Чтобы обработать клавиши акселераторов в
модальном диалоговом окне, Вам прийдётся
переопределить функцию CWinApp::ProcessMessageFilter().
ProcessMessageFilter() вызывается до того как будет
обработано сообщение.
Следующие шаги показывают как изменить пример
TRACER для правильной обработки клавишей
акселераторов:
- Загрузите проект TRACER в Visual C++.
- Для всех 16-битных версий Visual C++, и 32-битных Visual C++
до версии 2.2, запустите App Studio.
Для Visual C++ 4.0 и выше, выберите Resource View в окне Project
Workspace.
- Отредактируйте ресурс диалогового окна и
укажите стиль бордюра "thin". Данный шаг
необходим для диалога, содержащего меню.
- Создайте новый ресурс меню, пунктом верхнего
уровня "&File" и пунктом "&Exit\tCTRL+E"(CTRL+X
обычно связан с вырезанием текста, поэтому будем
использовать CTRL+E).
- Свяжите меню с диалоговым окном путём ввода ID
меню в свойствах ресурса диалога.
- Выберите пункт меню "&Exit\tCTRL+E" и кликните
кнопку ClassWizard на панели инструментов.
- В диалоговом окне Add Class выберите Select Class.
Затем выберите CPromptDlg и нажмите OK. Visual C++ 4.0
распознает, что ресурс меню не связан ни с каким
объектом и попросит Вас связать его с классом
CPromptDlg.
- В диалоговом окне ClassWizard выберите ID меню
связанный с меню Exit ID_FILE_EXIT, и сообщение COMMAND.
Затем выберите Add Function.
- Диалоговое окно Add Member Function предложит имя
для функции, которое можно отредактировать по
желанию. Нажмите OK.
- Кликните Edit Code. Вставьте в функцию следующую
строчку:
PostMessage(WM_COMMAND, IDOK, 0L);
Это даст тот же эффект, что и нажатие OK когда
пользователь выберет Exit в меню File.
Нажатие OK закроет TRACER.
- Создайте новый ресурс акселератора и свяжите
комбинацию клавиш CTRL+E с ID_FILE_EXIT.
- Сохраните ресурсы и закройте App Studio.
- В файле TRACER.CPP после выражения #include объявите
следующие переменные:
HWND ghDlg; // Дескриптор главного диалогового окна
HACCEL ghAccelTable; // Дескриптор таблицы акселераторов
- В ClassWizard, выберите CPromptDlg с сообщением WM_INITDIALOG и
добавьте функцию. В Visual C++ 4.0 выберите класс CPromptDlg,
ID объекта CPromptDlg, сообщение WM_INITDIALOG, и добавьте
функцию (Add Function). Обратите внимание, что теперь
существует две функции OnInitDialog() - одна для Macintosh
внутри дерективы #ifdef _MAC/#endif, а вторая та, что была
добавлена.
- Добавьте следующую строчку в функцию, которая
была добавлена выше:
ghDlg = m_hWnd;
В Visual C++ 4.0, убедитесь, что отредактировали
добавленную функцию, а не макинтошевскую:
ghDlg = m_hWnd;
- В файле Tracer.cpp в функцию CTraceApp::InitInstance() добавьте
следующую строку сразу после вызова SetDialogBkColor()
либо как в Visual C++ 4.0, после объявления dlg объекта
CPromptDlg:
ghAccelTable = LoadAccelerators(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDR_ACCELERATOR1));
- Объявлении класса CTracerApp в секции public добавьте
следующую строку:
virtual BOOL ProcessMessageFilter(int code, LPMSG lpMsg);
- Добавьте следующую функцию после функции
InitInstance():
BOOL CTracerApp::ProcessMessageFilter(int code, LPMSG lpMsg)
{
if (code < 0)
CWinApp::ProcessMessageFilter(code, lpMsg);
if (ghDlg && ghAccelTable)
{
if (::TranslateAccelerator(ghDlg, ghAccelTable, lpMsg))
return(TRUE);
}
return CWinApp::ProcessMessageFilter(code, lpMsg);
}
- Откомпилируйте и запустите TRACER. В нём должно
появиться меню. Если выбрать Exit в меню File
или нажать CTRL+E, то приложение завершится как мы и
ожидали.
|