- •Глава 10 Меню и быстрые клавиши
- •Структура меню
- •Шаблон меню
- •Ссылки на меню в вашей программе
- •Меню и сообщения
- •Образец программы
- •Этикет при организации меню
- •Сложный способ определения меню
- •Третий подход к определению меню
- •Независимые всплывающие меню
- •Использование системного меню
- •Изменение меню
- •Другие команды меню
- •Нестандартный подход к меню
- •Использование в меню битовых образов
- •Два способа создания битовых образов для меню
- •Контекст памяти
- •Создание битового образа, содержащего текст
- •Масштабирование битовых образов
- •Соберем все вместе
- •Добавление интерфейса клавиатуры
- •Быстрые клавиши
- •Зачем нужны быстрые клавиши?
- •Некоторые правила назначения быстрых клавиш
- •Загрузка таблицы быстрых клавиш
- •Преобразование нажатий клавиш клавиатуры
- •Получение сообщений быстрых клавиш
- •Программа poppad, имеющая меню и быстрые клавиши
- •Разрешение пунктов меню
- •Обработка опций меню
Разрешение пунктов меню
Основная работа оконной процедуры состоит теперь в разрешении и запрещении пунктов меню Edit, что осуществляется при обработке сообщения WM_INITMENUPOPUP. Сначала программа проверяет, отображается ли всплывающее меню Edit. Поскольку индекс положения пункта Edit в меню (начинающегося с пункта File, чей индекс положения равен 0) равен 1, то lParam равен 1 в том случае, если отображается всплывающее меню Edit.
Для того чтобы определить, может ли быть разрешена опция Undo, программа POPPAD2 посылает сообщение EM_CANUNDO дочернему окну редактирования. Возвращаемое значение функции SendMessage не равно нулю, если дочернее окно редактирования может выполнить операцию Undo, в этом случае опция Undo делается разрешенной; в противном случае опция делается недоступной:
EnableMenuItem ((HMENU) wParam, IDM_UNDO,
SendMessage (hwndEdit, EM_CANUNDO, 0, 0) ?
MF_ENABLED : MF_GRAYED) ;
Опцию Paste следует делать разрешенной только в том случае, если в данный момент в папке обмена имеется текст. Определить это можно с помощью функции IsClipboardFormatAvailable с идентификатором CF_TEXT:
EnableMenuItem ((HMENU) wParam, IDM_PASTE,
IsClipboardFormatAvailable (CF_TEXT) ?
MF_ENABLED : MF_GRAYED) ;
Опции Cut, Copy и Delete следует делать разрешенными только в том случае, если в окне редактирования был выделен текст. При посылке окну управления сообщения EM_GETSEL возвращаемым значением функции SendMessage является целое, в котором содержится эта информация:
iSelect = SendMessage (hwndEdit, EM_GETSEL, 0, 0) ;
Младшим словом iSelect является положение первого выбранного символа; старшим словом iSelect является положение первого символа после выделения. Если два этих слова равны, то в окне редактирования нет выбранного текста:
if (HIWORD(iSelect) == LOWORD(iSelect))
iEnable = MF_GRAYED ;
else
iEnable = MF_ENABLED ;
Затем значение iEnable используется для опций Cut, Copy и Delete:
EnableMenuItem ((HMENU) wParam, IDM_CUT, iEnable) ;
EnableMenuItem ((HMENU) wParam, IDM_COPY, iEnable) ;
EnableMenuItem ((HMENU) wParam, IDM_DEL, iEnable) ;
Обработка опций меню
Конечно, если бы мы в программе POPPAD2 не использовали элемент управления — дочернее окно редактирования, то теперь нам пришлось бы заняться проблемами, связанными с фактической реализацией опций Undo, Cut, Copy, Paste, Delete и Select All из меню Edit. Но окно редактирования делает этот процесс элементарным: мы просто посылаем окну редактирования сообщение для каждой из этих опций:
case IDM_UNDO :
SendMessage (hwndEdit, WM_UNDO, 0, 0) ;
return 0 ;
case IDM_CUT :
SendMessage (hwndEdit, WM_CUT, 0, 0) ;
return 0 ;
case IDM_COPY :
SendMessage (hwndEdit, WM_COPY, 0, 0) ;
return 0 ;
case IDM_PASTE :
SendMessage (hwndEdit, WM_PASTE, 0, 0) ;
return 0 ;
case IDM_DEL :
SendMessage (hwndEdit, WM_CLEAR, 0, 0) ;
return 0 ;
case IDM_SELALL :
SendMessage (hwndEdit, WM_SETSEL, 0, -1) ;
return 0 ;
Обратите внимание, что мы могли бы еще больше все упростить, приравняв значения IDM_UNDO, IDM_CUT и другие — значениям соответствующих сообщений окна WM_UNDO, WM_CUT и т. д.
Опция About всплывающего меню File вызывает простое окно сообщения:
case IDM_ABOUT :
MessageBox (hwnd,
"POPPAD2 (c) Charles Petzold, 1996",
szAppName, MB_OK | MB_ICONINFORMATION) ;
return 0 ;
В главе 11 мы создадим здесь окно диалога. Окно сообщения появляется также при выборе опции Help этого меню или при нажатии быстрой клавиши <F1>.
Опция Exit посылает оконной процедуре сообщение WM_CLOSE:
case IDM_EXIT :
SendMessage (hwndEdit, WM_CLOSE, 0, 0) ;
return 0 ;
Это именно то, что делает функция DefWindowProc при получении сообщения WM_SYSCOMMAND с параметром wParam, равным SC_CLOSE.
В предыдущих программах мы не обрабатывали сообщение WM_CLOSE в оконной процедуре, а просто передавали его в DefWindowProc. DefWindowProc поступает с сообщениями WM_CLOSE очень просто: она вызывает функцию DestroyWindow. Однако в программе POPPAD2 сообщение WM_CLOSE обрабатывается, а не пересылается в DefWindowProc. В данном случае это не имеет большого значения, но обработка сообщения WM_CLOSE станет важна, когда, как будет показано в главе 11, программа POPPAD будет фактически редактировать файлы:
case WM_CLOSE :
if (IDYES == AskConfirmation (hwnd))
DestroyWindow (hwnd) ;
return 0 ;
В программе POPPAD2 функция AskConfirmation выводит на экран окно сообщения, запрашивая подтверждение на завершение программы:
AskConfirmation (HWND hwnd)
{
return MessageBox (hwnd, "Do you really want to close Poppad2?",
szAppName, MB_YESNO | MB_ICONQUESTION) ;
}
Окно сообщения (как и функция AskConfirmation) возвращает IDYES, если нажата кнопка Yes. Только после этого программа POPPAD2 вызывает функцию DestroyWindow. В противном случае программа не завершается.
Если перед завершением программы требуется подтверждение, то необходимо также обрабатывать сообщение WM_QUERYENDSESSION. Windows посылает каждой оконной процедуре сообщение WM_QUERYENDSESSION, когда пользователь заканчивает сеанс работы с Windows. Если какая-либо оконная процедура возвращает 0 в ответ на это сообщение, то сеанс работы с Windows не завершается. Мы обрабатываем сообщение WM_QUERYENDSESSION следующим образом:
case WM_QUERYENDSESSION :
if ( IDYES == AskConfirmation (hwnd))
return 1 ;
else
return 0 ;
Сообщения WM_CLOSE и WM_QUERYENDSESSION — это два сообщения, которые требуют обработки, если необходимо запрашивать пользователя о подтверждении завершения программы. По этой причине в программе POPPAD2 опция Exit отправляет оконной процедуре сообщение WM_CLOSE. Это сделано во избежание еще и третьего запроса на подтверждение завершения.
Если вы обрабатываете сообщение WM_QUERYENDSESSION, вас заинтересует и сообщение WM_ENDSESSION. Windows посылает это сообщение каждой оконной процедуре, которая ранее получила сообщение WM_QUERYENDSESSION. Параметр wParam этого сообщения равен 0, если сеанс работы не может завершиться из-за того, что другая программа возвратила 0 в ответ на сообщение WM_QUERYENDSESSION. Практически сообщение WM_ENDSESSION отвечает на вопрос: "Я сообщил Windows, что могу закончить свою работу, но завершена ли она на самом деле?"
Хотя в меню File программы POPPAD2 включены обычные опции New, Open, Save и Save As, в этой программе они не работают. Для обработки этих опций необходимо использовать окна диалога. Сейчас мы готовы перейти к их изучению.
