Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
UP04_Menyu.doc
Скачиваний:
16
Добавлен:
01.03.2025
Размер:
555 Кб
Скачать
☆

4.2. Создание меню

Алгоритм создания меню в общем случае содержит следующие шаги:

  1. Создание пустого меню hMenu.

  2. Вставка элемента в меню hMenu.

  3. Шаг 2 повторяем столько раз, сколько элементов содержит меню hMenu.

Этот алгоритм позволяет создавать многоуровневое меню. Например, вставляемый на 2-м шаге элемент может указывать на уже созданное временное меню. Причем любой элемент последнего также может указывать на временное меню.

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

Функция CreateMenu создает пустое главное меню окна:

HMENU CreateMenu(VOID);

В случае успешного выполнения функция CreateMenu возвращает дескриптор созданного главного меню, иначе – NULL.

Функция CreatePopupMenu создает пустое временное меню:

HMENU CreatePopupMenu(VOID);

В случае успешного выполнения функция CreatePopupMenu возвращает дескриптор созданного временного меню, иначе – NULL.

Функция SetMenu подключает главное меню hMenu к окну hwnd:

BOOL SetMenu(HWND hwnd, HMENU hMenu );

Она удаляет предыдущее меню, но не разрушает его. Если же hMenu = NULL, то только удаляется главное меню. В случае успешного подключения функция возвращает ненулевое значение.

После изменений в меню, независимо от состояния окна hwnd, для перерисовки полосы меню нужно вызвать функцию DrawMenuBar:

void WINAPI DrawMenuBar(HWND hwnd);

Она перерисовывает полосу меню окна hwnd.

Таким образом, алгоритм подключения главного меню к окну и отображения полосы меню содержит следующие шаги:

  1. Создание главного меню. Этот шаг полностью совпадает с алгоритмом создания меню.

  2. Подключение главного меню к окну.

  3. Перерисовка полосы меню окна.

После этого работу с меню обеспечивает операционная система.

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

4.2.1. Вставка элементов в меню

Функция InsertMenuItem вставляет элемент в меню hMenu:

BOOL InsertMenuItem(HMENU hMenu, UINT uItem,

BOOL fByPosition, LPMENUITEMINFO lpmii);

Значение аргумента uItem зависит от значения fByPosition. При fByPosition = FALSE значение uItem равно идентификатору команды вставляемого элемента, иначе – позиции того элемента в меню, перед которым нужно вставить новый элемент. Если меню содержит n элементов и нужно вставить новый элемент последним, то номер позиции приравнивают n (n = 0, 1, 2, ...).

Параметр lpmii указывает на структуру типа MENUITEMINFO, которая уже содержит информацию о вставляемом элементе.

В случае успешной вставки элемента функция возвращает ненулевое значение.

Задача. Описать функцию для вставки элемента в меню.

Нижеследующий фрагмент может служить примером решения данной задачи.

BOOL CreateMenuItem(HMENU hMenu, char *str, UINT uIns, UINT uCom, HMENU hSubMenu, BOOL flag, UINT fType)

{

MENUITEMINFO mii;

mii.cbSize = sizeof(MENUITEMINFO);

mii.fMask = MIIM_STATE | MIIM_TYPE | MIIM_SUBMENU | MIIM_ID;

mii.fType = fType;

mii.fState = MFS_ENABLED;

mii.dwTypeData = str;

mii.cch = sizeof(str);

mii.wID = uCom;

mii.hSubMenu = hSubMenu;

return InsertMenuItem(hMenu, uIns, flag, &mii);

}

Рассмотрим список формальных параметров этой функции.

  1. hMenu – дескриптор меню, в который вставляется элемент.

  2. str указывает на текст отображения строки меню.

  3. uIns равноценен параметру uItem функции InsertMenuItem.

  4. uCom, когда он ненулевой, исполняет роль параметра wID функции InsertMenuItem.

  5. hSubMenu – дескриптор временного меню, которое должно появиться при выборе строки str в меню hMenu.

  6. flag совпадает с параметром fByPosition в InsertMenuItem.

  7. fType принимает те же значения, что и поле fType структуры MENUITEMINFO.

Задача. Главное меню содержит разделы "Файлы" и "Правка". При выборе строки "Файлы" отображается временное меню со строками "Открыть", "Сохранить" и "Выход". При выборе строки "Правка" отображается временное меню со строками "Найти" и "Заменить".

Листинг 4.1. Пример приложения со статическим меню.

#include <windows.h>

#define CM_FILE_OPEN 1001

#define CM_FILE_SAVE 1002

#define CM_FILE_QUIT 1003

#define CM_EDIT_FIND 2001

#define CM_EDIT_REPLC 2002

BOOL RegClass(WNDPROC, LPCTSTR, UINT);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE hInstance;

TCHAR szClass[] = TEXT("MenuWindow");

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)

{

MSG msg;

HWND hwnd;

hInstance = hInst;

if (!RegClass(WndProc, szClass, COLOR_WINDOW)) return FALSE;

hwnd = CreateWindow(szClass, TEXT("Приложение со статическим меню"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,

CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, NULL);

if (!hwnd) return FALSE;

while(GetMessage(&msg, 0, 0, 0))

{ TranslateMessage(&msg); DispatchMessage(&msg); }

return msg.wParam;

}

BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)

{

WNDCLASS wc;

wc.style = wc.cbClsExtra = wc.cbWndExtra = 0;

wc.lpfnWndProc = Proc;

wc.hInstance = hInstance;

wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

wc.hCursor = LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground = (HBRUSH)(brBackground +1);

wc.lpszMenuName = NULL;

wc.lpszClassName = szName;

return (RegisterClass(&wc) != 0);

}

BOOL CreateMenuItem(HMENU hMenu, TCHAR *str, UINT uIns, UINT uCom, HMENU hSubMenu, BOOL flag, UINT fType)

{

MENUITEMINFO mii;

mii.cbSize = sizeof(MENUITEMINFO);

mii.fMask = MIIM_STATE | MIIM_TYPE | MIIM_SUBMENU | MIIM_ID;

mii.fType = fType;

mii.fState = MFS_ENABLED;

mii.dwTypeData = str;

mii.cch = sizeof(str);

mii.wID = uCom;

mii.hSubMenu = hSubMenu;

return InsertMenuItem(hMenu, uIns, flag, &mii);

}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

static HMENU hMainMenu, hFileMenu, hEditMenu;

switch (msg)

{

case WM_CREATE:

{

hMainMenu = CreateMenu();

//Создаем временное меню для раздела "Файлы"

hFileMenu = CreatePopupMenu();

int i=0; //Инициализация позиции в меню hFileMenu

CreateMenuItem( hFileMenu, TEXT("&Открыть"), i++, CM_FILE_OPEN, NULL, FALSE, MFT_STRING);

CreateMenuItem( hFileMenu, TEXT("&Сохранить"), i++, CM_FILE_SAVE, NULL, FALSE, MFT_STRING);

CreateMenuItem( hFileMenu, NULL, i++, 0, NULL, FALSE, MFT_SEPARATOR);

CreateMenuItem( hFileMenu, TEXT("&Выход"), i++, CM_FILE_QUIT, NULL, FALSE, MFT_STRING);

//Создаем временное меню для раздела "Правка"

hEditMenu = CreatePopupMenu();

i=0; //Инициализация позиции в меню hEditMenu

CreateMenuItem( hEditMenu, TEXT("&Найти"), i++, CM_EDIT_FIND, NULL, FALSE, MFT_STRING);

CreateMenuItem( hEditMenu, TEXT("&3аменить"), i++, CM_EDIT_REPLC, NULL, FALSE, MFT_STRING);

//Подключаем временные меню к главному меню

i=0; //Инициализация позиции в меню hMainMenu

CreateMenuItem( hMainMenu, TEXT("&Файл"), i++, 0, hFileMenu, FALSE, MFT_STRING);

CreateMenuItem( hMainMenu, TEXT("&Правка"), i++, 0, hEditMenu, FALSE, MFT_STRING);

SetMenu( hwnd, hMainMenu);

DrawMenuBar( hwnd);

return 0;

}

case WM_COMMAND:

{

switch (LOWORD(wParam))

{

case CM_FILE_OPEN:

{ MessageBox(hwnd, TEXT("Команда CM_FILE_OPEN"), TEXT("Меню"), MB_OK); return 0; }

case CM_FILE_SAVE:

{ MessageBox(hwnd, TEXT("Команда CM_FILE_SAVE"), TEXT("Меню"), MB_OK); return 0; }

case CM_EDIT_FIND:

{ MessageBox(hwnd, TEXT("Команда CM_EDIT_FIND"), TEXT("Меню"), MB_OK); return 0; }

case CM_EDIT_REPLC:

{ MessageBox(hwnd, TEXT("Команда CM_EDIT_REPLC"), TEXT("Меню"), MB_OK); return 0; }

case CM_FILE_QUIT: { DestroyWindow(hwnd); return 0; }

}

return 0;

}

case WM_DESTROY: { PostQuitMessage(0); return 0; }

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

Это приложение демонстрирует применение рассмотренной выше функции CreateMenuItem для создания статического меню. Меню названо статическим потому, что в процессе работы приложения оно не изменяется. Рассмотрим основные шаги создания меню.

  1. Описывают дескрипторы для создаваемых меню:

static HMENU hMainMenu, hFileMenu, hEditMenu;

  1. При обработке сообщения WM_CREATE создают всю систему меню (хотя не запрещается это делать и в любом другом месте).

    1. Создают пустое главное меню окна:

hMainMenu = CreateMenu();

    1. Создают временное меню для раздела "Файлы".

      1. Создают пустое временное меню:

hFileMenu = CreatePopupMenu();

      1. Вставляют элементы в меню hFileMenu:

CreateMenuItem( hFileMenu, "&Открыть", i++, CM_FILE_OPEN,

NULL, FALSE, MFT_STRING);

CreateMenuItem( hFileMenu,"&Сохранить", i++, CM_FILE_SAVE,

NULL, FALSE, MFT_STRING);

CreateMenuItem( hFileMenu, NULL, i++, 0,

NULL, FALSE, MFT_SEPARATOR);

CreateMenuItem( hFileMenu, "&Выход", i++, CM_FILE_QUIT,

NULL, FALSE, MFT_STRING);

Здесь аргумент "&Открыть" обозначает ту строку, которая будет отображена во временном меню. Ключ & обозначает, что символ "О" можно использовать для быстрого доступа к данной строке меню. Аргумент CM_FILE_OPEN является идентификатором той команды, которую получит функция окна при выборе строки "&Открыть".

Так же вставляют второй и четвертый элементы меню. Третьим элементом является разделительная линия.

    1. Создают временное меню для раздела "Правка".

      1. Создают пустое временное меню:

hEditMenu = CreatePopupMenu();

      1. Вставляют элементы в меню hEditMenu:

CreateMenuItem( hEditMenu, "&Найти", i++, CM_EDIT_FIND,

NULL, FALSE, MFT_STRING);

CreateMenuItem( hEditMenu,"&3aMeHHTb", i++, CM_EDIT_REPLC,

NULL, FALSE, MFT_STRING );

    1. Подключают временные меню hFileMenu и hEditMenu к главному меню hMainMenu:

CreateMenuItem( hMainMenu, "&Файл", i++,

0, hFileMenu, FALSE, MFT_STRING);

CreateMenuItem( hMainMenu, "&Правка", i++,

0, hEditMenu, FALSE, MFT_STRING);

  1. Подключают главное меню к окну и перерисовывают полосу меню:

SetMenu(hwnd, hMainMenu);

DrawMenuBar(hwnd);

Приложение обрабатывает команды меню. Как можно увидеть из листинга, обработка команд от меню ничем не отличается от обработки команд от других органов.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]