В классе CMenu инкапсулировано большинство функциональных возможностей меню. При этом построение меню в основном осуществляется посредством вашего кода, а не с помощью Мастера. Однако некоторые методы позволяют работать с предварительно подготовленными меню
Очевидно основное меню, используемое в приложении будет связано с главным окном и не потребует никакой дальнейшей обработки. Если надо изменить меню во время работы приложения, придется добавить некоторый код вручную. Первы метод для выполнения этой задачи - LoadMenu. Этот метод получает единственный параметр - идентификатор ID ресурса того меню, которое должно быть загружено. После загрузки меню можно использовать метод SetMenu класса CWnd для окна, в котором вы хотите изменить меню. Метод SetMenu принимает единственный параметр, представляющий собой указатель на новое меню.
Выполнение этой задачи выглядит примерно так :
//Переменная m_MyNewMenu является экземпляром класса CMenu. Она относится
//к классу окна, для которого вы хотите установить новое меню.
//Это - НЕ локальная переменная функции , выполняющей переключение.
m_MyNewMenu.LoadMenu(IDR_NEW_MENU);
//удалить старое меню, передав ПУСТОЙ УКАЗАТЕЛЬ NULL, вместо указателя CMenu
SetMenu(NULL);
//уничтожить старое меню используя дескриптор
//переменная m_hMenuHandle так же является дескриптором уровня класса в
//классе окна.
//Получить указатель на старое меню
CMenu *pMenu = CMenu::FromHandle(m_hMenuHandle);
if(pMenu)
//уничтожить меню освобождая все ресурсы, которые оно использует
pMenu->DestroyMenu();
//Добавить новое меню передав адрес переменной типа CMenu
SetMenu(&m_MyNewMenu);
//Присвоить новый декриптор меню переменной, в которой хранится дескриптор
m_hMenuHandle = m_MyNewMenu.m_hMenu;
В приведенном коде, после того как старое меню уже не привязано к окну, указатель на меню извлекается из его дескриптора и затем используется для уничтожения окна. Сделано это с помощью метода FromHandle, котороая принимает дескриптор CMenu как единственный параметр и возвращает указатель на меню. После того , как указатель на меню возвращен, вызывается метод DestroyMenu. Старое меню удаляется из памяти, освобождая всю используемую память и все другие ресурсы, используемые им. Этого так же можно достичь, вызвав функцию интерфейса Windows для прикладных программ (WindowsAPI) DestroyMenu, которая принимает дескриптор меню как параметр.
::DestroyMenu(m_hMenuHandle);
Чуть дальше вы узнаете как использовать два других метода-члена класса CMenu. Они полезны для создания контекстных меню. К функциям CMenu относятся так же GetSubMenu, которая может использоваться для получения указателя на раскрывающуюся часть меню, и TrackPopupMenu , - она отображает меню как контекстное. Мы используем эти методы с функцией GetMenu класса CWnd, которая возвращает указатель на текущее меню, используемое в окне.
Вверх
Вверх
Создать в приложении всплывающее меню можно двумя спосбами:
Можно спроектировать меню именно для использования в качестве всплывающего меню, а можно использовать одно из раскрывающихся меню верхнего уровня, которое уже разработано ранее. Проектируя именно всплывающее меню нужно пропустить запись в строке верхнего уровня, поместив в заголовке пробел, или какой-то другой текст, так как он не будет показан(можно
использовать надпись, которая отражает контекст меню).
Каждая раскрывающаяся часть меню может так же быть использована как
всплывающее меню. Чтобы использовать ее таким образом, следует получить дескриптор подменю (раскрывающаяся часть меню) и затем вызвать для него
функцию TrackPopupMenu. Другие функциональные возможности высплывающих
меню уже охвачены в предыдущем описании.
Чтобы добавить всплывающее меню в приложение сделайте следующее:
Можно использовать два сообщения диалога о событии для вызова контекстного меню.
Листинг 7.4 Функция OnContextMenu
Анализ:
С помощью функции GetMenu сначала получается указатель на меню
диалогового окна.
Этот указатель должен всегда быть локальным в пределах
функции, где он будет использоваться, потому что местоположение меню
(в памяти) может измениться во время работы приложения.
Затем с помощью функции GetSubMenu получается указатель на первое раскрывающееся меню (нумерация подменю начинается с нуля). Имея указатель на подменю, можно обрабатывать его как обычный экземпляр класса CMenu.
Заключительная часть - вызов функции-члена CMenu, TrackPopupMenu.
Эта функция использует пять параметров, чтобы определить где и как показывать
всплывающее меню.
Новый термин:
Абсолютная позиция и относительная позиция - методы определения местоположения на экране. Они определяются как горизонтальная позиция(x),
и вертикальная позиция (y). Абсолютная позиция измеряется в пикселях
от верхнего левого угла экрана. Комбинируя абсолютную и относительную позиции, можно определить в каком месте окна расположен указатель,
и какой пункт под ним находится. Таким образом можно открыть контекстное меню для элемента на котором стоит указатель.
Вверх
Вы можете называть ваше меню верхнего уровна как хотите. Однако существуют
некоторые соглашения о названиях меню, в соответствии с которыми все файловые
операции размещаются в меню File, а все связанные со справкой - в меню Help.
Если ваше меню содержит пункты типа Брокколи, Зерно и Морковь, вы вероятно захотите назвать его овощи. Вообще названия пунктов меню должны легко запоминаться и не иметь неоднозначных толкований.
Одиночный символ вызвал бы сообщение WM_KEY, а не сообщения связанные с меню. Если бы разработчики Windows позволили бы использовать для этой цели односимвольные ускоряющие клавиши , Windows не смогла бы определить,
что нужно сделать - напечатать символ или вызвать команду.
Вверх
Вверх
Назад |
Начало урока |
Вверх |
Вперед
Библиотека MFC Сообщения о событиях связанных с меню
Назначая обработчик события для пунктов меню, вы вероятно заметили два сообщения о событиях , для которых можно задать обработчики. Первое сообщение о событии COMMAND вполне очевидно передается классу окна, чтобы сообщить о том, что пользователь выбрал определенный пункт меню. Другое сообщение UPDATE_COMMAND_UI не столь понятно. UPDATE_COMMAND_UI посылается классу окна перед тем, как пункты меню будут отображены для пользователя. Это событие где вы должны добавить какую-то обработку , чтобы задать способ отображения меню. Если пункт меню, должен функционировать подобно флажку(и иметь возле себя флажок). здесь следует добавить флажок.
Если пункт меню должен быть заблокирован, здесь нужно добавить специальный код.
Это сообщение о событии будет рассматриватьься далее в главе 10.
Создание контекстных меню
В большинстве приложений Win используются всплывающие контекстные меню,
которые вызываются с помощью правой кнопки мыши. Они "всплывают"
посреди рабочей области приложения безотносительно к строке меню, рамке окна или еще чему-нибудь на экране (кроме указателя мыши). Они так же часто называются контекстными меню, потому что их содержание зависит от
контекста в котором они вызваны. Доступные элементы меню зависят
от выделенного в приложении объекта или от того, на что установлен
указатель.
Мы будем использовать сообщение - WM_RBUTTONDOWN - которое вызывается щелчком правой кнопки мыши.
Другое событие, которое может и должно
использоваться - WM_CONTEXTMENU - предназначенное для вызова контекстного меню. Это событие может вызываться двумя действиями пользователя:отпусканием
правой кнопки мыши и нажатием кнопки контекстного меню, которая есть
на новых клавиатурах для Windows.
void CMenusDlg::OnContextMenu(CWnd* pWnd, CPoint point)
{
//получить указатель на меню
pMenu = GetMenu();
//получить указатель на подменю
pMenu = pMenu->GetSubMenu(0);
//открыть его как контекстное меню
pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_LEFTBUTTON,
point.x, point.y, pWnd, NULL);
CMenu *pMenu;
//получить указатель на меню
pMenu = GetMenu();
//получить указатель на подменю
pMenu = pMenu->GetSubMenu(0);
//открыть его как контекстное меню
pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_LEFTBUTTON,
point.x, point.y, pWnd, NULL);
Создание меню с командными клавишами -акселераторами
Вверх
Резюме
Вверх
Вопросы и ответы
Вопросы
Упражнения
Содержание