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

         

Приложение MultiMenu


Создайте новый проект под названием MultiMenu. В качестве типа приложения выберите из списка Type строку Application. Настройте проект MultiMenu, указав что приложение будет работать с библиотекой классов MFC.

Наберите в редакторе исходный текст приложения и сохраните его в файле MultiMenu.cpp (листинг 3.1). Включите готовый файл MultiMenu.cpp в проект.

Листинг 3.1. Файл MultiMenu.cpp

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

// Приложение MultiMenu

// (c) Frolov G.V., 1996

// E-mail: frolov@glas.apc.org

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

// Включаемые файлы для MFC

#include <afxwin.h>

#include <afxext.h>

#include <afxcmn.h>

// Включаемый файл для ресурсов приложения и идентификаторов

#include "resource.h"

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

// Класс CMultiMenuApp - главный класс приложения

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

class CMultiMenuApp : public CWinApp

{

public:

   // Мы будем переопределять метод InitInstance,

   // предназначенный для инициализации приложения

   virtual BOOL InitInstance();

};

 

// Создаем объект приложение класса CMultiMenuApp

CMultiMenuApp MultiMenuApp;

 

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

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

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

class CMultiMenuWindow : public CFrameWnd

{

protected: 

   // Панель состояния

   CStatusBar  m_wndStatusBar;  

  

   // Флаг управляет строкой Prosess меню Mission

   BOOL  bEnable;

   // Флаг управляет строкой Construction меню Mission

   BOOL  bRadio; 

   // Флаг управляет строкой Restrict меню Menu

   int   nCheck; 

      

protected:

   // Метод для создания окна приложения и панели состояния

   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

   // Методы для обработки командных сообщений


   // от меню приложения

   afx_msg void CMultiMenuWindow::OnDisable();

   afx_msg void CMultiMenuWindow::OnCommand();

   afx_msg void CMultiMenuWindow::OnExit();

   afx_msg void CMultiMenuWindow::OnConstruct();

   afx_msg void CMultiMenuWindow::OnRestrictMenu();

   afx_msg void CMultiMenuWindow::OnFullMenu();

   // Методы для обновления меню

   afx_msg void OnUpdateProcess(CCmdUI* pCmdUI);

   afx_msg void OnUpdateConstruct(CCmdUI* pCmdUI);

   afx_msg void OnUpdateDisable(CCmdUI* pCmdUI);

  

public:

   // Конструктор класса CMultiMenuWindow

   CMultiMenuWindow();

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

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

   DECLARE_MESSAGE_MAP()   

};

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

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

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

BEGIN_MESSAGE_MAP(CMultiMenuWindow, CFrameWnd)

  

   // Макрокоманда вызывает метод OnCreate

   ON_WM_CREATE()

   // Макрокоманда вызывает метод OnContextMenu

   ON_WM_CONTEXTMENU()

   // Макрокоманды для обработки командных сообщений

   ON_COMMAND(ID_MENU_DISABLE, OnDisable)

   ON_COMMAND(ID_MISSION_CONSTRUCT, OnConstruct)

   ON_COMMAND(ID_FILE_EXIT, OnExit)

   ON_COMMAND(ID_MISSION_PROCESS, OnCommand)

  

   ON_COMMAND(ID_MENU_RESTRICT, OnRestrictMenu)

   ON_COMMAND(ID_MENU_FULL, OnFullMenu)

   // Обработчики сообщений ON_UPDATE_COMMAND_UI

   ON_UPDATE_COMMAND_UI(ID_MISSION_PROCESS, OnUpdateProcess)

   ON_UPDATE_COMMAND_UI(ID_MISSION_CONSTRUCT,

                           OnUpdateConstruct)

   ON_UPDATE_COMMAND_UI(ID_MENU_DISABLE, OnUpdateDisable)

END_MESSAGE_MAP()

// Индикатор панели управления

UINT indicator = ID_SEPARATOR;

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

// Метод InitInstance класса CMultiMenuApp

// Создает главное окно приложения и отображает его на экране

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



BOOL CMultiMenuApp::InitInstance()

{

   m_pMainWnd = new CMultiMenuWindow();

   m_pMainWnd -> ShowWindow(m_nCmdShow);

   m_pMainWnd -> UpdateWindow();

   return TRUE;

}

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

// Конструктор класса CMultiMenuWindow

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

CMultiMenuWindow::CMultiMenuWindow()

{

   // Создаем окно приложения, соответствующее

   // данному объекту класса CMultiMenuWindow

   Create(NULL, "Multi Menu Sample", WS_OVERLAPPEDWINDOW,

      rectDefault, NULL, MAKEINTRESOURCE(IDR_FULL_MENU));

   // Загружаем таблицу клавиш акселерации

   LoadAccelTable(MAKEINTRESOURCE(IDR_ACCELERATOR));

   // Инициализируем флаги

   bEnable = TRUE;        

   bRadio = TRUE;        

   nCheck = 0;

}

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

// Метод OnCreate класса CMultiMenuWindow

// Вызывается во время создания окна приложения

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

int CMultiMenuWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

   // Вызываем метод OnCreate базового класса

   if(CFrameWnd::OnCreate(lpCreateStruct) == -1)

      return -1;

  

   // Создаем панель состояния

   if(!m_wndStatusBar.Create(this))

   {

      // Ошибка при создании панели состояния

      TRACE0("Failed to create status bar\n");

      return -1;  

   }

   // Отображаем индикаторы панели состояния

   if(!m_wndStatusBar.SetIndicators(&indicator,1))

   {

      // Ошибка при установке индикатора

      TRACE0("Failed to set indicators\n");

      return -1;  

   }

  

   return 0;

}

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

// Метод OnDisable класса CMultiMenuWindow

// Изменяем состояние флагов bEnable и nCheck

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

void CMultiMenuWindow::OnDisable()

{

   // Меняем значение bEnable с TRUE на FALSE и наоборот



   bEnable = !bEnable;

  

   // Меняем значение bEnable с 1 на 0 и наоборот

   nCheck = (nCheck == 1) ? 0 : 1;

}

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

// Метод OnRestrictMenu класса CMultiMenuWindow

// Изменяем меню приложения с IDR_FULL_MENU на

// IDR_RESTRICT_MENU

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

void CMultiMenuWindow::OnRestrictMenu()

{

   CMenu menuOld;       // текущее меню

   CMenu menuRestrict;  // новое меню

   CMenu* pMenu;

   // Получаем указатель на текущее меню

   pMenu = this->GetMenu();

  

   // Связываем меню с объектом menuOld

   menuOld.Attach(pMenu->m_hMenu);

   // Удаляем меню

   menuOld.DestroyMenu();

  

   // Загружаем меню IDR_RESTRICT_MENU

   menuRestrict.LoadMenu(IDR_RESTRICT_MENU);

   // Устанавливаем загруженное меню

   SetMenu(&menuRestrict);

   // Разрываем связь меню с объектом menuRestrict

   menuRestrict.Detach();

}

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

// Метод OnFullMenu класса CMultiMenuWindow

// Изменяем меню приложения с IDR_RESTRICT_MENU на

// IDR_FULL_MENU

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

void CMultiMenuWindow::OnFullMenu()

{

   CMenu menuOld;

   CMenu menuRestrict;

   CMenu* pMenu;

   pMenu = this->GetMenu();

   menuOld.Attach(pMenu->m_hMenu);

   menuOld.DestroyMenu();

   menuRestrict.LoadMenu(IDR_FULL_MENU);

   SetMenu(&menuRestrict);

   menuRestrict.Detach();

}

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

// Метод OnCommand класса CMultiMenuWindow

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

void CMultiMenuWindow::OnCommand()

{

   MessageBox("Command not implemented");

}

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

// Метод OnConstruct класса CMultiMenuWindow

// Изменяем состояние флага bRadio

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



void CMultiMenuWindow::OnConstruct()

{

   // Меняем значение bRadio с TRUE на FALSE и наоборот

   bRadio = !bRadio;

}

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

// Метод OnExit класса CMultiMenuWindow

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

void CMultiMenuWindow::OnExit()

{

   // Завершаем приложение

   DestroyWindow();

   return;

}

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

// Метод OnUpdateProcess класса CMultiMenuWindow

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

void CMultiMenuWindow::OnUpdateProcess(CCmdUI* pCmdUI)

{

   // Блокируем или разблокируем строку Process меню Mission

   pCmdUI->Enable(bEnable);

}

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

// Метод OnUpdateConstruct класса CMultiMenuWindow

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

void CMultiMenuWindow::OnUpdateConstruct(CCmdUI* pCmdUI)

{

   // Устанавливаем или снимаем пометку

   // строки Construction меню Mission

   pCmdUI->SetRadio(bRadio);

}

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

// Метод OnUpdateDisable класса CMultiMenuWindow

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

void CMultiMenuWindow::OnUpdateDisable(CCmdUI* pCmdUI)

{

   // Устанавливаем или удаляем пометку

   // у строки Disable меню Menu

   pCmdUI->SetCheck(nCheck);

}

Создайте новый файл ресурсов и включите его в проект под именем MultiMenu.rc. Включите в него два меню, присвоив им идентификаторы IDR_RESTRICT_MENU и IDR_FULL_MENU.

Введите строки этих меню в соответствии с представленным нами файлом ресурсов (листинг 3.2). Для всех строк меню введите их описания. Они будут записаны в файл ресурсов как строковые ресурсы, имеющие одинаковые идентификаторы со строками меню.

Добавьте в файл ресурсов строку Ready, выбрав для нее идентификатор AFX_IDS_IDLEMESSAGE. Эта строка будет отображаться в панели состояния во время “бездействия” приложения.



Включите в файл ресурсов таблицу акселераторов, состоящую из трех команд: ID_MENU_DISABLE, ID_MISSION_PROCESS и ID_FILE_EXIT. Присвойте им комбинации клавиш <Ctrl+D>, <Ctrl+P> и <Ctrl+E> соответственно.

Листинг 3.2. Файл MultiMenu.rc

//Microsoft Developer Studio generated resource script.

//

#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS

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

//

// Generated from the TEXTINCLUDE 2 resource.

//

#include "afxres.h"

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

#undef APSTUDIO_READONLY_SYMBOLS

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

// Russian resources

#if !defined(AFX_RESOURCE_DLL) defined(AFX_TARG_RUS)

#ifdef _WIN32

LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT

#pragma code_page(1251)

#endif //_WIN32

#ifdef APSTUDIO_INVOKED

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

//

// TEXTINCLUDE

//

1 TEXTINCLUDE DISCARDABLE

BEGIN

    "resource.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

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

//

// Menu

//

IDR_RESTRICT_MENU MENU DISCARDABLE

BEGIN

    POPUP "&File"

    BEGIN

        MENUITEM "P&rocess\tCtrl+P",  ID_MISSION_PROCESS

        MENUITEM SEPARATOR

        MENUITEM "E&xit\tCtrl+E",     ID_FILE_EXIT

    END

    POPUP "&Menu"

    BEGIN

        MENUITEM "Full",              ID_MENU_FULL

        MENUITEM "Disa&ble\tCtrl+D",  ID_MENU_DISABLE

    END

    POPUP "&Help", HELP

    BEGIN

        MENUITEM "Help index",        ID_HELP_HELPINDEX



        MENUITEM SEPARATOR

        MENUITEM "System info",       ID_HELP_SYSTEMINFO

    END

END

IDR_FULL_MENU MENU DISCARDABLE

BEGIN

    POPUP "&File"

    BEGIN

        MENUITEM SEPARATOR

        MENUITEM "E&xit\tCtrl+E",     ID_FILE_EXIT

    END

    POPUP "&Menu"

    BEGIN

        MENUITEM "Restrict",          ID_MENU_RESTRICT

        MENUITEM "Disa&ble\tCtrl+D",  ID_MENU_DISABLE

    END

    POPUP "M&ission"

    BEGIN

        MENUITEM "P&rocess\tCtrl+P",  ID_MISSION_PROCESS

        MENUITEM SEPARATOR

        MENUITEM "Construction",      ID_MISSION_CONSTRUCT

    END

    POPUP "&Help", HELP

    BEGIN

        MENUITEM "Help index",        ID_HELP_HELPINDEX

        MENUITEM "Context help",      ID_HELP_CONTEXTHELP

        MENUITEM SEPARATOR

        MENUITEM "System info",       ID_HELP_SYSTEMINFO

    END

END

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

//

// Accelerator

//

IDR_ACCELERATOR ACCELERATORS DISCARDABLE

BEGIN

    "D",   ID_MENU_DISABLE,    VIRTKEY, CONTROL, NOINVERT

    "E",   ID_FILE_EXIT,       VIRTKEY, CONTROL, NOINVERT

    "P",   ID_MISSION_PROCESS, VIRTKEY, CONTROL, NOINVERT

END

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

//

// String Table

//

STRINGTABLE DISCARDABLE

BEGIN

    AFX_IDS_IDLEMESSAGE     "Ready"

END

STRINGTABLE DISCARDABLE

BEGIN

    ID_FILE_EXIT            "Exit application"

    ID_MISSION_PROCESS      "Process"

    ID_HELP_HELPINDEX       "Open help index"

    ID_HELP_CONTEXTHELP     "Context help"

END

STRINGTABLE DISCARDABLE

BEGIN

    ID_HELP_SYSTEMINFO      "Display system info"

    ID_MISSION_CONSTRUCT    "Construct"

    ID_MENU_RESTRICT        "Restrict menu"



    ID_MENU_FULL            "Display full menu"

    ID_MENU_DISABLE         " Disable command Process from menu Mission"

END

#endif    // Russian resources

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

#ifndef APSTUDIO_INVOKED

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

//

// Generated from the TEXTINCLUDE 3 resource.

//

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

#endif    // not APSTUDIO_INVOKED

Идентификаторы ресурсов приложения MultiMenu определены в файле resource.h. Этот файл создается автоматически редактором ресурсов Microsoft Visual C++. Исходный текст этого файла представлен в листинге 3.3.

Листинг 3.3. Файл resource.h

//{{NO_DEPENDENCIES}}

// Microsoft Developer Studio generated include file.

// Used by MultiMenu.rc

//

#define IDR_RESTRICT_MENU               106

#define IDR_FULL_MENU                   107

#define IDR_ACCELERATOR                 108

#define ID_FILE_EXIT                    40009

#define ID_MISSION_PROCESS              40013

#define ID_HELP_HELPINDEX               40014

#define ID_HELP_CONTEXTHELP             40015

#define ID_HELP_SYSTEMINFO              40016

#define ID_MISSION_CONSTRUCT            40017

#define ID_MENU_RESTRICT                40019

#define ID_MENU_FULL                    40020

#define ID_MENU_DISABLE                 40025

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE        110

#define _APS_NEXT_COMMAND_VALUE         40027

#define _APS_NEXT_CONTROL_VALUE         1000

#define _APS_NEXT_SYMED_VALUE           101

#endif

#endif

Постройте приложение MultiMenu и запустите его. На экране появится окно приложения с главным меню и панелью состояния (рис. 3.4).

В панели состояния расположен один индикатор. В нем отображается подсказка о выбранной строке меню приложения или системного меню, а если приложение “бездействует” - строка Ready.





Рис. 3.4. Приложение MultiMenu

Сразу после запуска приложения MultiMenu используется меню с идентификатором IDR_FULL_MENU. Если вы выберите из меню Menu строку Restrict, то меню приложения будет заменено на меню IDR_RESTRICT_MENU. Это сокращенный вариант меню IDR_FULL_MENU, в котором отсутствуют некоторые строки, а строка Process перенесена из меню Mission в меню File.

Различные строки меню IDR_FULL_MENU и IDR_RESTRICT_MENU иллюстрируют режимы отображения строк меню. Так, при выборе из меню Menu строки Disable, блокируется строка Process в меню Mission. Около строки Disable при этом отображается символ Ö (рис. 3.3). Чтобы снять блокировку, выберите строку Disable из меню Menu еще раз. Символ Ö также исчезнет.

При выборе строки Process из меню Mission на экране появляется сообщение. Когда строка Process заблокирована, выбрать ее невозможно.

Если вы выберите из меню Mission строку Construction, то она будет выделена символом ·. Повторный выбор этой строки снимает с нее выделение.

Чтобы завершить работу приложения MultiMenu, можно выбрать из меню File строку Exit или выбрать из системного меню приложения строку Close. Все остальные строки меню приложения не работают и заблокированы.

Для ускорения выбора некоторых команд из меню приложения можно воспользоваться клавишами акселерации. В программе определены три такие комбинации.

Комбинация клавиш

Соответствующая строка меню

<Ctrl+D>

Строка Disable из меню Menu

<Ctrl+P>

Строка Process из меню Mission или из меню File (для сокращенного варианта меню)

<Ctrl+E>

Строка Exit из меню File


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