
4.2.2. Удаление элементов из меню
Функция DeleteMenu удаляет элемент из меню и освобождает все связанные с ним ресурсы. Если удаляемый элемент указывает на временное меню, то функция DeleteMenu удаляет и это временное меню. Прототип функции:
BOOL DeleteMenu( HMENU hMenu, UINT uPosition, UINT uFlags);
Параметры:
hMenu – дескриптор изменяемого меню.
uPosition определяет удаляемый элемент. Его значение связано со значением параметра uFlags.
uFlags задает способ истолкования параметра uPosition. Если uFlags = MF_BYCOMMAND (значение по умолчанию), то значение uPosition равно идентификатору команды удаляемого элемента. Если же uFlags = MF_BYPOSITION, то значение uPosition равно позиции удаляемого элемента в меню.
В случае успешного удаления функция возвращает ненулевое значение.
Функция RemoveMenu удаляет элемент из меню, не разрушая связанные с ним ресурсы. Эти ресурсы можно использовать в дальнейшем. Прототип функции:
BOOL RemoveMenu( HMENU hMenu, UINT uPosition, UINT uFlags);
Параметры функции RemoveMenu подобны параметрам функции DeleteMenu. В случае успешного удаления элемента RemoveMenu возвращает ненулевое значение.
Для разрушения меню вызывают функцию DestroyMenu:
BOOL DestroyMenu( HMENU hMenu);
Эта функция разрушает заданное меню и освобождает ресурсы, которые меню занимает. Эту функцию окна вызывают для разрушения тех меню, которые они создали, но не подключили к себе. Подключенные меню автоматически разрушаются при разрушении окна.
В случае успешного разрушения функция возвращает ненулевое значение.
Задача. Главное меню изначально содержит раздел "Файлы". При выборе строки "Файлы" отображается временное меню со строками "Открыть", "Сохранить", разделительной линией и строкой "Выход". При выборе строки "Открыть" в главное меню добавить элемент "Правка". .При выборе строки "Правка" отображается временное меню со строками "Найти" и "Заменить". Если же затем выбрать строку "Сохранить", то из главного меню удалить элемент "Правка".
Листинг 4.2. Пример удаления элементов меню.
#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("RemoveMenu");
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;
static BOOL fFileOpened;
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);
SetMenu(hwnd, hMainMenu);
DrawMenuBar(hwnd);
fFileOpened = FALSE;
return 0;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case CM_FILE_OPEN:
{
if (!fFileOpened)
{
CreateMenuItem( hMainMenu, TEXT("&Правка"), 1, 0, hEditMenu, FALSE, MFT_STRING);
DrawMenuBar( hwnd );
fFileOpened = TRUE;
}
return 0;
}
case CM_FILE_SAVE:
{
if (fFileOpened)
{
RemoveMenu(hMainMenu, 1, MF_BYPOSITION);
DrawMenuBar( hwnd);
fFileOpened = FALSE;
}
return 0;
}
case CM_EDIT_FIND:
{
MessageBox(hwnd, TEXT("Команда CM_EDIT_FlND"), 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:
{
if (!fFileOpened) DestroyMenu( hEditMenu);
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
Это приложение от предыдущего отличается следующим:
Временное меню hEditMenu в главное меню вставляют лишь после выбора строки "Открыть". При этом проверяют флаг состояния fFileOpened – если файл открыт, то меню hEditMenu уже вставлено в главное меню и еще раз его вставлять не нужно:
if (!fFileOpened)
{
CreateMenuItem( hMainMenu, "&Правка", 1, 0, hEditMenu,
FALSE, MFT_STRING);
DrawMenuBar( hwnd);
fFileOpened=TRUE;
}
Как видим, операция вставки буквально скопирована из предыдущего приложения.
Временное меню hEditMenu удаляют из главного меню после выбора строки "Сохранить". Здесь закрытие файла подразумевается. При этом проверяют флаг состояния fFileOpened – если файл закрыт, то меню hEditMenu уже удалено и еще раз его удалять не нужно:
if (fFileOpened)
{
RemoveMenu( hMainMenu, 1, MF_BYPOSITION );
DrawMenuBar( hwnd);
fFileOpened=FALSE;
}
До разрушения окна проверяют, вставлено ли меню hEditMenu в главное меню. Если нет, то его нужно разрушать отдельно:
if (!fFileOpened) DestroyMenu( hEditMenu);