Microsoft Visual C++ и MFC. Программирование для Win95 и WinNT

         

Создание меню для приложения MFMenu


Так как наше приложение будет содержать меню, мы приступим к созданию ресурсов приложения. Для этого создайте новый файл ресурсов. Выберите из меню File строку New, а затем из открывшейся диалоговой панели выберите строку Resource Script и нажмите кнопку OK.

Теперь надо создать меню. Выберите из меню Insert строку Resource. На экране появится диалоговая панель Insert Resource. Выберите из нее строку Menu и нажмите кнопку OK. Вы сможете в диалоговом режиме разработать меню. Чтобы быстрее перейти к редактированию меню, вы можете нажать кнопку New Menu (

) из панели управления Project или просто нажать комбинацию кнопок <Ctrl+2>.

Создайте меню, содержащее единственную строку Test, при выборе которой открывается меню, содержащее три строки - Beep и Exit. Внешний вид меню во время разработки представлен на рисунке 2.22.

Рис. 2.22. Разработка меню приложения

Когда вы создаете новое меню верхнего уровня или определяете строки, входящие в это меню, на экране появляется диалоговое окно Menu Item Properties (рис. 2.23). В нем полностью описывается выбранный элемент меню. В поле Caption задается название меню или строки меню. В названии вы можете вставить символ &. Он будет означать, что символ, следующий за ним, можно будет использовать для быстрого выбора данного элемента меню. Например, если перед названием строки меню Beep поставить символ &, то во время работы приложения символ B будет отображаться с подчеркиванием, и строку Beep можно будет выбрать, нажав комбинацию клавиш <Alt+B>.

Рис. 2.23. Диалоговая панель Menu Item Properties

Как вы знаете, каждый элемент меню должен иметь уникальный идентификатор, однозначно его определяющий. Вы можете задать идентификатор в поле ID или выбрать его из списка предопределенных идентификаторов.

Редактор ресурсов сам предлагает вам название идентификатора, создавая его из названия главного меню и строки меню. Так например строке Beep меню Test по умолчанию будет присвоен идентификатор ID_TEST_BEEP.

В поле Prompt можно в нескольких словах описать данный пункт меню. Введенная вами строка будет записана в строковый ресурс. Ей будет присвоен тот же самый идентификатор, что и пункту меню. Приложение может использовать строку описания, чтобы предоставить пользователю краткую справку о меню.


Если вы разрабатываете приложение с помощью средств MFC AppWizard, то при выборе пользователем строк меню их описание будет появляться в панели состояния StatusBar. Что интересно, для этого вам не потребуется написать ни одной строки текста программы. Это будет сделано автоматически благодаря возможностям библиотеки классов MFC и MFC AppWizard.



Остальные переключатели диалоговой панели Menu Item Properties описаны в следующей таблице.

Переключатель

Описание

Break

Этот переключатель может принимать три различных значения - None, Column и Bar. Он позволяет задать структуру меню.

По умолчанию выбрано значение None оно соответствует нормальному виду меню без деления на колонки.

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

Значение Bar соответствует Column, за исключением меню верхнего уровня. Если указать Bar для меню верхнего уровня, то новая колонка будет отделена от старой вертикальной линией

Checked

Если установить переключатель, то строка меню будет выделена символом
. Потом, обращаясь к специальным методам, вы сможете удалять или отображать этот символ

Grayed

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

Help

Если установить переключатель Help, тогда для него будет установлено выравнивание по правому краю. Обычно этот переключатель устанавливают для меню верхнего уровня, которое управляет справочной системной приложения

Inactive

Если включен переключатель Grayed, тогда переключатель недоступен. В противном случае вы можете установить переключатель Inactive. В этом случае пункт меню будет неактивен

Pop-up

Вы можете создавать многоуровневые меню. Если вы включите переключатель Pop-up, то данный пункт меню будет являться меню верхнего уровня, которое можно открыть. По умолчанию, все пункты главного меню имеют установленный переключатель Pop-up. Так как меню верхнего уровня служит только для объединения других пунктов меню, то оно не имеет идентификатора

Separator

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

<


Сохраните файл ресурсов в файле с именем MFMenu.rc. Редактор ресурсов создает кроме самого файла ресурсов еще включаемый файл, в котором определяются константы, используемые в файле ресурсов. В нашем случае в нем определяются идентификаторы меню приложения. По умолчанию этот файл сохраняется под именем resource.h. Вы можете изменить его, выбрав из меню View строку Resource Includes. Для нашего приложения мы изменили имя включаемого файла для ресурсов на MFMenuRes.h. Содержимое этого файла представлено листингом 2.8.

Листинг 2.8. Файл MFMenuRes.h

//{{NO_DEPENDENCIES}}

// Включаемый файл, созданный Microsoft Developer Studio

// Используется в файле ресурсов MFMenu.rc

//

#define IDR_MENU                        101

#define ID_TEST_BEEP                    40001

#define ID_TEST_EXIT                    40002

// Следующие значения идентификаторов используются по

// умолчанию для новых объектов

#ifdef APSTUDIO_INVOKED

      #ifndef APSTUDIO_READONLY_SYMBOLS

             #define _APS_NEXT_RESOURCE_VALUE        102

             #define _APS_NEXT_COMMAND_VALUE         40003

             #define _APS_NEXT_CONTROL_VALUE         1000

             #define _APS_NEXT_SYMED_VALUE           101

      #endif

#endif

В листинге 2.9 мы привели файл ресурсов MFMenuRes.rc приложения. Этот файл был подготовлен редактором ресурсов Visual C++. Одна из первых строк файла содержит директиву #include которой подключается файл MFMenuRes.h, содержащий описание идентификаторов ресурсов (листинг 2.8).

Среди прочих служебных строк, необходимых редактору ресурсов и компилятору Visual C++, вы можете обнаружить описание меню приложения IDR_MENU. Для первого приложения, использующего ресурсы мы привели файл ресурсов полностью. Впоследствии мы ограничимся словесным описанием ресурсов и будем приводить только выдержки из файла ресурсов.

Листинг 2.9. Файл MFMenuRes.rc

// Файл описания ресурсов приложения, созданный

// Microsoft Developer Studio

#include "MFMenuRes.h"



#define APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

// Включаем файл afxres.h, содержащий определения стандартных

// идентификаторов

#include "afxres.h"

//////////////////////////////////////////////////////////////

#undef APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

// Руссификацированные ресурсы

#if !defined(AFX_RESOURCE_DLL) defined(AFX_TARG_RUS)

      #ifdef _WIN32

             LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT

             #pragma code_page(1251)

      #endif //_WIN32

      ////////////////////////////////////////////////////////////              // Меню

      //

      IDR_MENU MENU DISCARDABLE

      BEGIN

             POPUP "Test"

             BEGIN

                   MENUITEM "Beep",                        ID_TEST_BEEP

                   MENUITEM SEPARATOR

                   MENUITEM "Exit",                        ID_TEST_EXIT

             END

      END

      #ifdef APSTUDIO_INVOKED

            

             ////////////////////////////////////////////////////////

             // Ресурсы TEXTINCLUDE

             //

             1 TEXTINCLUDE DISCARDABLE

             BEGIN

                   "MFMenuRes.h\0"

             END

             2 TEXTINCLUDE DISCARDABLE

             BEGIN

                   "#include ""afxres.h""\r\n"

                   "\0"

             END

             3 TEXTINCLUDE DISCARDABLE

             BEGIN

                   "\r\n"

                   "\0"

             END

      #endif         // APSTUDIO_INVOKED

#endif                // Руссификацированные ресурсы

//////////////////////////////////////////////////////////////

#ifndef APSTUDIO_INVOKED

#endif

Когда вы создадите ресурсы приложения и включите файл ресурсов в проект обратите внимание на окно Project Workspace. В нем появится еще одна, четвертая страница ResourceView (рис. 2.24). Эта страница показывает все ресурсы, входящие в проект. В приложении MFMenu определен только один ресурс - меню, имеющее идентификатор IDR_MENU.



Вы можете быстро перейти к редактированию меню, если выберите его идентификатор и щелкните два раза левой кнопкой мыши.



Рис. 2.24. Страница ResourceView окна Project Workspace

Теперь проект готов. Вы можете построить его и запустить полученное приложение MFMenu. Внешний вид приложения представлен на рисунке 2.25. Как видите окно приложения имеет меню Test, состоящее из двух строк - Beep и Exit.

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

Когда вы завершите работу с приложением, его можно закрыть. Для этого воспользуйтесь системным меню приложения или выберите из меню Test строку Exit.



Рис. 2.25. Приложение MFMenu

Чтобы объекты класса могли обрабатывать сообщения, в определении этого класса необходимо поместить макрокоманду DECLARE_MESSAGE_MAP. По принятым соглашениям эта макрокоманда должна записываться в конце определения класса в секции public.

//=====================================================

// Класс CMFMenuWindow - представляет главное окно

//=====================================================

class CMFMenuWindow : public CFrameWnd

{

public:

      // Объявляем конструктор класса CMFMenuWindow

      CMFMenuWindow();

      // Объявляем методы для обработки команд меню

      afx_msg void MenuCommand();

      afx_msg void ExitApp();

      // Макрокоманда необходима, так как класс

      // CMFMenuWindow обрабатывает сообщения

      DECLARE_MESSAGE_MAP()   

};

Однако это еще не все. Необходимо также определить таблицу сообщений. Таблица начинается макрокомандой BEGIN_MESSAGE_MAP и заканчивается макрокомандой END_MESSAGE_MAP. Между этими макрокомандами расположены строки таблицы сообщений, определяющие сообщения, подлежащие обработке данным классом и методы, которые выполняют такую обработку.



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

Приложение MFMenu обрабатывает только две команды от меню приложения. Первая команда имеет идентификатор ID_TEST_BEEP и передается, когда пользователь выбирает из меню Test строку Beep. Для обработки этой команды вызывается метод MenuCommand. Вторая команда с идентификатором ID_TEST_EXIT передается приложению, когда пользователь выбирает из меню Test строку Exit. Обработка этого сообщения выполняется методом ExitApp.

//=====================================================

// Таблица сообщений класса CMFMenuWindow

//=====================================================

BEGIN_MESSAGE_MAP(CMFMenuWindow, CFrameWnd)

      ON_COMMAND(ID_TEST_BEEP, MenuCommand)

      ON_COMMAND(ID_TEST_EXIT, ExitApp)

END_MESSAGE_MAP()

Конечно, приложению MFMenu может поступать гораздо больше сообщений и команд, чем указано в таблице сообщений класса CMFMenuWindow. Необработанные сообщения передаются для обработки базовому классу CMFMenuWindow - классу CFrameWnd. Класс, который будет обрабатывать сообщения, не указанные в таблице сообщений, указывается во втором параметре макрокоманды BEGIN_MESSAGE_MAP.


Содержание раздела