Опубликован: 17.08.2010 | Доступ: свободный | Студентов: 999 / 59 | Оценка: 4.11 / 3.89 | Длительность: 29:38:00
Самостоятельная работа 7:

Меню в приложениях MFC

Привязка к меню функциональных возможностей

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

  • Откройте через панель Resource View для нашего меню проектировщик Menu Designer
  • Выберите элемент меню с названием Hello
  • Щелкните на нем правой кнопкой мыши и из контекстного меню выберите пункт Add Event Handler (Добавить обработчик события)

Появится диалоговое окно, которое нужно настроить как показано на рисунке


Мастер добавит следующие коды

Добавление прототипа в объявление класса CMenuDlg
// CMenuDlg dialog
class CMenuDlg : public CDialog
{
....................................
public:
	afx_msg void OnBnClickedExit();
	afx_msg void OnFileHello();
};
Регистрация обработчика в таблице сообщений класса CMenuDlg
BEGIN_MESSAGE_MAP(CMenuDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_EXIT, OnBnClickedExit)
	ON_COMMAND(ID_FILE_HELLO, OnFileHello)
END_MESSAGE_MAP()
Обработчик команды-сообщения, поступившей от 
идентификатора ID_FILE_HELLO ресурса пункта меню, включенного в класс CMenuDlg
void CMenuDlg::OnFileHello()
{
	// Здесь компилятор автоматически соединяет
	// строковые константы в одну строку !!!
	MessageBox("Это поле текста!\n"	
			  "Выбрана пиктограмма MB_ICONEXCLAMATION\n"
			  "Для переноса строк используется\n"
			  "управляющий символ \\n - экранирует его \\\n\n"
			  "Привет студентам от Снеткова В.М.!!!"
			, "Это заголовок окна"
			, MB_OK | MB_ICONEXCLAMATION 
			// запятая спереди элементов списка позволяет
			// удалить строку без синтаксических нарушений
			);
}
  • Постройте приложение и выполните пункт меню Hello

    Получится результат


  • Таким же образом создайте обработчик для опции About категории Help, настроив мастер так


    При настройке мастера приложения мы отказались от создания окна About, поэтому остались без автоматически сгенерированного меню About, диалогового ресурса IDD_ABOUTBOX и поддерживающего класса CAboutDlg. Восполним этот пробел позже, а сейчас создадим заготовку кода обработчика.

  • Создайте обработчик и заполните его следующим кодом
    Заготовка кода обработчика команды-сообщения, 
    Запоступившей от идентификатора ID_HELP_ABOUT ресурса пункта меню, включенного в класс CMenuDlg
    void CMenuDlg::OnHelpAbout()
    {
    	//CAboutBox dlgAbout; // Создаем на стеке локальный объект About с
    					// отредактированными заранее настройками ресурса
    	//dlgAbout.DoModal(); // Отображаем локальный About
    }
  • Свяжите ранее созданный обработчик завершения приложения с пунктом меню E&xit. Для этого вызовите и настройте мастер, который создаст заготовку обработчика

  • Заполните обработчик, включив в него вызов обработчика кнопки E&xit
    Обработчик команды-сообщения, поступившей от идентификатора ID_FILE_EXIT ресурса пункта меню, 
    включенного в класс CMenuDlg
    void CMenuDlg::OnFileExit()
    {
    	OnBnClickedExit(); // Вызов обработчика кнопки
    }

Такой прием вызова одного обработчика через другой не всегда хорош, поскольку сильно связывает код. Если программист захочет избавиться от вызывающего обработчика, ему понадобятся дополнительные действия.

Создание диалога AboutBox

Восполним пробел того, что мы не указали создание диалогового окна AboutBox в настройках мастера. Для этого используем материал, рассмотренный в лабораторной работе " Lab7 - Dialogs ".

Создание макета диалогового окна About
  • Выберите вкладку Resource View, выделите узел Dialogs и через контекстное меню или главное меню оболочки выполните опцию Add Resourcе

    Появится окно Add Resource


  • Выделите в нем пиктограмму Dialog и щелкните на кнопке New. Оболочка создаст заготовку диалогового окна
  • Присвойте идентификатору ресурса окна имя IDD_ABOUTBOX
  • Удалите из заготовки кнопку Cancel. Измените сгенерированный заголовок окна " Dialog " на "Сведения об авторах"
  • Добавьте ресурс Icon через окно Add Resource, но только иконку загрузите внешнюю, нажав клавишу Import

    Откроется окно

    в котором настройте фильтр на *.ico и загрузите нужную иконку. Измените идентификатор ресурса иконки на IDI_ICONABOUT в панели свойств, предварительно выделив ресурс. Удостоверьтесь, что файл с иконкой оболочка скопировала к себе в каталог res приложения

  • Добавьте элемент управления Picture Control. Измените значение его свойства Type на Icon, а в свойстве Image выберите IDI_ICONABOUT. Другая же иконка имеет стандартное имя IDR_MAINFRAME, которое закреплено за иконкой приложения
  • Наполните заготовку краткими сведениями о приложении (лаб. работа №8 и т.д.) и его разработчиках, используя элементы управления Static Text. При редактировании диалогового ресурса периодически проверяйте дизайн кнопкой Test Dialog панели инструментов Dialog Editor. Размеры элементов управления контролируйте через панель состояния дизайнера. Для выравнивания элементов пользуйтесь инструментами на панели инструментов или опциями меню Format оболочки

Ресурс должен выглядеть примерно так


Создание управляющего класса
  • Выберите только что сконструированное окно в режиме дизайна и через контекстное меню (или главное меню Project ) выполните опцию Add Class. Запустится мастер добавления класса, который нужно настроить в соответствии с рисунком

  • Подключите вначале файла MenuDlg.h заголовочный файл AboutBox.h
    Подключение сведений о классе CAboutBox в файл описания класса CMenuDlg
    // MenuDlg.h : header file
    //
    	
    #pragma once
    	
    #include "AboutBox.h"
    // CMenuDlg dialog
    class CMenuDlg : public CDialog
    {
    .....................................
    };
  • Раскомментируйте обработчик About главного меню приложения
    Обработчик команды-сообщения, поступившей от идентификатора mID_HELP_ABOUT ресурса пункта меню, 
    включенного в класс CMenuDlg
    void CMenuDlg::OnHelpAbout()
    {
    	CAboutBox dlgAbout; // Создаем на стеке локальный объект About с
    					// отредактированными заранее настройками ресурса
    	dlgAbout.DoModal(); // Отображаем локальный About
    }
  • Запустите приложение и убедитесь в правильности выполненной работы
  • Обратите внимание, что объект dlgAbout создан локально на стеке внутри обработчика и не будет виден из других функций приложения. Измените, код обработчика так, чтобы объект диалогового окна About создавался на куче всякий раз при входе в обработчик и уничтожался при выходе из него
    Создание объекта About динамически на куче
    void CMenuDlg::OnHelpAbout()
    {
    	
    	// CAboutBox dlgAbout; // Создаем на стеке локальный объект About с
    					// отредактированными заранее настройками ресурса
    	// dlgAbout.DoModal(); // Отображаем локальный About
    	
    	CAboutBox *dlgAbout; // Создаем на стеке локальный указатель на объект About
    	dlgAbout = new CAboutBox; // Создаем на куче объект
    	dlgAbout->DoModal(); // Отображаем объект About
    	delete dlgAbout; // Уничтожаем объект
    }
  • Постройте приложение и убедитесь, что все работает

Динамические меню

Для создания меню динамическим способом, или управлением уже существующим меню, предназначен MFC -класс CMenu. Если в каком-то из окон приложения меню уже существует, то получить указатель на этот объект можно с помощью унаследованного этим окном от класса CWnd метода CWnd::GetMenu() с помощью кода

CMenu *ptrMenu = GetMenu();

Этот указатель ptrMenu на созданное приложением меню должен быть всегда локальным в пределах функции, чтобы дать возможность системе самой освободить ею же созданный объект меню. После того, как указатель на существующее меню окна получен, можно получить указатели на отдельные подменю (категории) этого меню уже с помощью метода класса CMenu, например

CMenu *ptrSubMenu = ptrMenu->GetSubMenu(nPos);
				где nPos (int nPos) - индекс категории всего мен

Единственным параметром этой функции является целое nPos, которое означает индекс подменю первого уровня. Нумерация индексов начинается с нуля.

Приведем список наиболее часто используемый функций класса CMenu

Наиболее часто используемые функции класса Cmenu
Функция Описание
AppendMenu() Добавляет новый пункт в конец уже существующего или нового всплывающего меню. В передаваемых аргументах указывается, создавать новый пункт в категориях или добавлять новый пункт в раскрывающийся список опций
CheckMenuItem() Устанавливает или сбрасывает флажок пункта меню (используется редко). Обычно вместо этой функции используют обработчик сообщений UPDATE_COMMAND_UI.
GetSubMenu() Возвращает указатель на подменю по индексу категории (индексируется с нуля)
GetMenuItemID() Запрашивает идентификатор команды пункта меню.
GetMenuString() Запрашивает текст метки пункта меню (внешнее наименование пункта)
EnableMenuItem() Блокирует и разблокирует пункты меню. Обычно вместо этой функции используется обработчик сообщения UPDATE_COMMAND_UI.
InsertMenu() Вставляет новый пункт в определенную позицию уже существующего меню.
RemoveMenu() Удаляет определенный пункт меню.
DestroyMenu() Удаляет из памяти динамически созданный на куче объект меню.
TrackPopupMenu() Выводит соответствующий раскрывающийся список опций как контекстное меню.
Александр Даниленко
Александр Даниленко
Стоит Windows 8 Pro, Visual Studio 2010 Express Edition .