Назад | Начало урока | Вперед
Содержание

День 7 (продолжение 1)

  • Библиотека MFC Класс CMenu
  • Библиотека MFC Сообщения о событиях связанных с меню
  • Создание контекстных меню
  • Создание меню с командными клавишами -акселераторами
  • Резюме
  • Вопросы и ответы.
  • Вопросы
  • Упражнения
    Библиотека MFC Класс CMenu

    В классе 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, которая возвращает указатель на текущее меню, используемое в окне.

    Вверх

    Библиотека MFC Сообщения о событиях связанных с меню
    Назначая обработчик события для пунктов меню, вы вероятно заметили два сообщения о событиях , для которых можно задать обработчики. Первое сообщение о событии COMMAND вполне очевидно передается классу окна, чтобы сообщить о том, что пользователь выбрал определенный пункт меню. Другое сообщение UPDATE_COMMAND_UI не столь понятно. UPDATE_COMMAND_UI посылается классу окна перед тем, как пункты меню будут отображены для пользователя. Это событие где вы должны добавить какую-то обработку , чтобы задать способ отображения меню. Если пункт меню, должен функционировать подобно флажку(и иметь возле себя флажок). здесь следует добавить флажок. Если пункт меню должен быть заблокирован, здесь нужно добавить специальный код. Это сообщение о событии будет рассматриватьься далее в главе 10.

    Вверх

    Создание контекстных меню
    В большинстве приложений Win используются всплывающие контекстные меню, которые вызываются с помощью правой кнопки мыши. Они "всплывают" посреди рабочей области приложения безотносительно к строке меню, рамке окна или еще чему-нибудь на экране (кроме указателя мыши). Они так же часто называются контекстными меню, потому что их содержание зависит от контекста в котором они вызваны. Доступные элементы меню зависят от выделенного в приложении объекта или от того, на что установлен указатель.

    Создать в приложении всплывающее меню можно двумя спосбами: Можно спроектировать меню именно для использования в качестве всплывающего меню, а можно использовать одно из раскрывающихся меню верхнего уровня, которое уже разработано ранее. Проектируя именно всплывающее меню нужно пропустить запись в строке верхнего уровня, поместив в заголовке пробел, или какой-то другой текст, так как он не будет показан(можно использовать надпись, которая отражает контекст меню).

    Каждая раскрывающаяся часть меню может так же быть использована как всплывающее меню. Чтобы использовать ее таким образом, следует получить дескриптор подменю (раскрывающаяся часть меню) и затем вызвать для него функцию TrackPopupMenu. Другие функциональные возможности высплывающих меню уже охвачены в предыдущем описании.

    Чтобы добавить всплывающее меню в приложение сделайте следующее:

    1. Используя режим Messages в области окна Properties , добавьте функцию для сообщения о событии WM_CONTEXTMENU в диалоговое окно.

      Примечание:

      Можно использовать два сообщения диалога о событии для вызова контекстного меню.
      Мы будем использовать сообщение - WM_RBUTTONDOWN - которое вызывается щелчком правой кнопки мыши.
      Другое событие, которое может и должно использоваться - WM_CONTEXTMENU - предназначенное для вызова контекстного меню. Это событие может вызываться двумя действиями пользователя:отпусканием правой кнопки мыши и нажатием кнопки контекстного меню, которая есть на новых клавиатурах для Windows.

    2. Добавьте функцию . Снимите знак комментария с параметров передаваемых функции

      Листинг 7.4 Функция OnContextMenu


      void CMenusDlg::OnContextMenu(CWnd* pWnd, CPoint point)
      {
      CMenu *pMenu;
      //получить указатель на меню
      pMenu = GetMenu();
      //получить указатель на подменю
      pMenu = pMenu->GetSubMenu(0);
      //открыть его как контекстное меню
      pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_LEFTBUTTON,
      point.x, point.y, pWnd, NULL);
      }

    Анализ:

    С помощью функции GetMenu сначала получается указатель на меню диалогового окна.

    CMenu *pMenu;
    //получить указатель на меню
    pMenu = GetMenu();

    Этот указатель должен всегда быть локальным в пределах функции, где он будет использоваться, потому что местоположение меню (в памяти) может измениться во время работы приложения.

    Затем с помощью функции GetSubMenu получается указатель на первое раскрывающееся меню (нумерация подменю начинается с нуля). Имея указатель на подменю, можно обрабатывать его как обычный экземпляр класса CMenu.

    //получить указатель на подменю
    pMenu = pMenu->GetSubMenu(0);

    Заключительная часть - вызов функции-члена CMenu, TrackPopupMenu.

    //открыть его как контекстное меню
    pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_LEFTBUTTON,
    point.x, point.y, pWnd, NULL);

    Эта функция использует пять параметров, чтобы определить где и как показывать всплывающее меню.

  • Первый параметр объединяет два флажка. Первый флажок TPM_CENTERALIGN , позиционирует центр всплывающего меню на указатель . Вместо него можно использовать TPM_LEFTALIGN или TPM_RIGHTALIGN. Каждый из этих флажков позиционирует один край (левый или правый) всплывающего меню на указатель мыши. Вторая часть этого комбинированного флажка - TPM_LEFTBUTTON -, задает, что темы меню будут выбираться левой кнопкой мыши. Но точно так же вместо него можно использовать TPM_RIGHTBUTTON , чтобы задать выбор с помощью правой кнопки.

  • Второй и третий параметры функции TrackPopupMenu определяют позицию всплывающего меню на экране. Это позиция абсолютная, а не относительно области окна.

  • Четвертый параметр - указатель на окно, которое получает сообщения меню команд.

  • Заключительный параметр - прямоугольник, в пределах которого пользователь может щелкать кнопкой не закрывая всплювающее меню. Передавая пустой указатель NULL, вы указываете, что если пользователь щелкнет кнопкой мыши вне поля всплывающего меню, оно закроется. Этот код дает возможность включать всплывающее меню в приложение.

    Новый термин:

    Абсолютная позиция и относительная позиция - методы определения местоположения на экране. Они определяются как горизонтальная позиция(x), и вертикальная позиция (y). Абсолютная позиция измеряется в пикселях от верхнего левого угла экрана. Комбинируя абсолютную и относительную позиции, можно определить в каком месте окна расположен указатель, и какой пункт под ним находится. Таким образом можно открыть контекстное меню для элемента на котором стоит указатель.

    Вверх

    Создание меню с командными клавишами -акселераторами
    Вверх
    Резюме
    Вверх
    Вопросы и ответы
  • Нужно ли называть пункты меню так же, как и все остальные?Например во многих приложениях используются пункты меню File и Help. Можно ли называть меню как то иначе?

    Вы можете называть ваше меню верхнего уровна как хотите. Однако существуют некоторые соглашения о названиях меню, в соответствии с которыми все файловые операции размещаются в меню File, а все связанные со справкой - в меню Help. Если ваше меню содержит пункты типа Брокколи, Зерно и Морковь, вы вероятно захотите назвать его овощи. Вообще названия пунктов меню должны легко запоминаться и не иметь неоднозначных толкований.

  • Почему нельзя задать одиночный символ в качестве ускоряющей клавиши?

    Одиночный символ вызвал бы сообщение WM_KEY, а не сообщения связанные с меню. Если бы разработчики Windows позволили бы использовать для этой цели односимвольные ускоряющие клавиши , Windows не смогла бы определить, что нужно сделать - напечатать символ или вызвать команду.

    Вверх

    Вопросы

    1. Какое сообщение о событии посылается в очередь сообщений окна при выборе пункта меню?
    2. Как связать меню с диалоговым окном?
    3. Какой существующий класс нужно указать для обработки сообщений о событии для меню?
    4. Каким сообщением о событии должно вызываться всплывающее меню?

  • Ответы

    Вверх

    Упражнения

    1. Добавьте кнопку в главное окно и сделайте так, чтобы по щелчку на ней вызывалась та же самая функция, что и при выборе пункта меню Hello.

    2. Измените контекстное меню приложения так, чтобы оно использовало раскрывающееся меню Help в качестве всплывающего меню.

  • Ответы

    Назад | Начало урока | Вверх | Вперед
    Содержание

    Hosted by uCoz