Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Lab_progr_Win / Lab8

.doc
Скачиваний:
7
Добавлен:
23.03.2015
Размер:
516.1 Кб
Скачать

Лабораторна робота №8.

Тема роботи: Створення меню.

Ціль роботи: Придбання досвіду створення прикладного програмного забезпечення для Windows з використанням меню.

ТЕОРЕТИЧНА ЧАСТИНА

Меню — це, імовірно, найбільш важлива частина користувальницького інтерфейсу, що пропонують програми для Windows, а додавання меню до вашої програми — це відносно проста задача програмування для Windows. Ви просто визначаєте структуру меню у вашому описі ресурсів і привласнюєте кожному пункту меню унікальний ідентифікатор. Ви визначаєте ім'я меню в структурі класу вікна. Коли користувач вибирає пункт меню, Windows посилає вашій програмі повідомлення WM_COMMAND, що містить цей ідентифікатор.

Рядок меню виводиться на екрані безпосередньо під рядком заголовка. Цей рядок іноді називається головним меню (main menu) чи меню верхнього рівня (top-level menu) програми. Вибір елемента головного меню звичайно приводить до виклику іншого меню, що з'являється під головним, і яке звичайно називають спливаючим меню (popup menu) чи підменю (submenu). Ви також можете визначити кілька рівнів вкладеності спливаючих меню: тобто визначений пункт спливаючого меню може викликати появу іншого спливаючого меню. Іноді, з метою збільшення інформативності, виклик якихось пунктів меню приводить до появи вікон діалогу. У більшості батьківських вікон, у лівій частині рядка заголовка, мається маленький значок програми. Щелчок на цьому значку приводить до появи системного меню, що фактично є спливаючим меню іншого типу.

Пункти спливаючих меню можуть бути позначені (checked), при цьому ліворуч від тексту елемента меню Windows ставиться спеціальна мітка чи "галочка". Галочки дозволяють користувачу довідатися про те, які опції програми обрані з цього меню. Ці опції можуть бути взаємовиключними. Пункти головного меню позначені бути не можуть.

Пункти меню в головному і спливаючих меню можуть бути "дозволені" (enabled), "заборонені" (disabled) чи "недоступні" (grayed). Слова "активно" (active) і "неактивно" (inactive) іноді використовуються, як синоніми слів "дозволене" і "заборонено". Пункти меню, позначені як дозволені чи заборонені, для користувача виглядають однаково, а недоступний пункт меню виводиться на екран у сірому кольорі.

З погляду користувача всі пункти меню, дозволені, заборонені і недоступні, можуть бути обрані. (Відмінність тільки в тім, що при виборі заборонених чи недоступних пунктів меню з додатком нічого не відбувається.) Користувач може клацнути клавішею миші на забороненому пункті меню, чи перемістити до забороненого пункту меню підсвічування, чи переключитися на пункт меню за допомогою буквеної клавіші, що відповідає цьому пункту. Однак, з позиції вашої програми дозволені, заборонені і недоступні пункти меню функціонують по-різному. Повідомлення WM_COMMAND Windows посилає в програму тільки для дозволених пунктів меню. Використовуйте заборонені і недоступні пункти меню тільки для тих опцій, що у даний момент не можуть бути обрані. Для того щоб користувач знав, які опції не можуть бути виконані, робіть їх недоступними.

Кожен пункт меню визначається трьома характеристиками. Перша характеристика визначає те, що буде відображено в меню. Це або рядок тексту, або бітовий образ. Друга характеристика визначає або ідентифікатор, що Windows посилає вашій програмі в повідомленні WM_COMMAND, або спливаюче меню, що Windows виводить на екран, коли користувач вибирає даний пункт меню. Третя характеристика описує атрибут пункту меню, включаючи те, чи є даний пункт забороненим, недоступним чи позначеним.

У багатьох додатках Windows в описі ресурсів мається тільки одне меню. Посилання в програмі на це меню мають місце у визначенні класу вікна:

wndclass.lpszMenuName = "MyMenu" ;

Для створення меню можна використовувати три методи

По-перше, можна описати шаблон меню у файлі ресурсів додатка. Цей спосіб підходить для створення статичних меню, не мінливих чи мінливих не дуже сильно в процесі роботи додатка.

По-друге, можна створити меню “з нуля” за допомогою спеціальних функцій Windows. Цей спосіб підходить для додатків, що змінюють зовнішній вигляд меню, коли не виходить створити придатний шаблон заздалегідь.

В-третіх, можна підготувати шаблон меню безпосередньо в оперативній пам'яті і створити меню на базі цього шаблона за допомогою LoadMenuIndirect.

Зауваження. При створенні чи зміні меню програми корисно розділяти головне меню і всі спливаючі меню.

У головного меню мається дескриптор меню, у кожного спливаючого меню усередині головного меню мається власний дескриптор меню, і в системного меню теж мається дескриптор меню.

Якщо при реєстрації класу вікна було визначено меню, то можна створити вікно з цим меню, а можна вказати для створюваного вікна інше меню.

Для підключення меню, відмінного від зазначеного в класі вікна, необхідно задати дескриптор потрібного меню при створенні вікна функцією CreateWindow.

Коротше кажучи, вікно може мати меню, визначене в класі вікна, а може мати власне.

Для одержання дескриптора меню ресурс меню необхідно завантажити. У додатках Windows ресурс меню можна завантажити в пам'ять за допомогою функції LoadMenu, що приймає дескриптор копії додатка й ім'я шаблона меню. Значенням цієї функції, що повертається, є дескриптор меню:

HMENU hMenu=LoadMenu(hInst,”MyMenu”);

При використанні числа як ідентифікатора меню виклик функції LoadMenu приймає такий вид:

HMENU hMenu=LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU));

Отриманий дескриптор меню можна вказати як дев'ятий параметр функції CreateWindow:

hWnd=CreateWindow("MyClass","Caption", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, hMenu, hInst, NULL);

Отже,

Меню, зазначене при виклику функції CreateWindow перекриває меню, задане в класі. Меню, що задається в класі вікна можна вважати заданим за замовчуванням для усіх вікон, створених на основі даного класу, якщо дев'ятий параметр функції CreateWindow встановлений у NULL.

Тому можна використовувати різні меню для різних вікон, створених на основі того самого класу вікон.

Коли користувач вибирає пункт будь-якого меню, Windows посилає віконній процедурі кілька різних повідомлень.

Більшість з цих повідомлень звичайно ігнорується програмою і передається на обробку у функцію DefWindowProc.

Повідомлення WM_INITMENU посилається вікну в момент відображення головного меню і може бути використане для ініціалізації даних додатки. Це повідомлення існує для того, щоб дати додатку можливість змінити меню перед тим, як буде обраний пункт меню.

Когда Windows готова вивести на екран спливаюче меню, вона посилає віконній процедурі повідомлення WM_INITMENUPOPUP. Це повідомлення важливе, якщо необхідно чи дозволяти забороняти пункти меню перед їхнім виводом на екран.

При роботі користувача з меню, а саме при переміщенні курсору миші по пунктах меню, додаток одержує повідомлення WM_MENUSELECT. Це повідомлення корисне, наприклад, при використанні рядка стану для відображення в ньому повної інформації про пункт меню. Дане повідомлення може знадобитися і для того, щоб змінити що-небудь у робочій області вікна на основі інформації про переміщення підсвічування по пунктах меню.

Найважливим повідомленням меню є повідомлення WM_COMMAND. Це повідомлення показує, що користувач вибрав дозволений пункт меню вікна. Разом з повідомлення приходить додаткова інформація:

LOWORD(wParam) – ідентифікатор пункту меню;

HIWORD(wParam) – завжди дорівнює 0;

lParam – завжди дорівнює 0 (як і в акселераторів).

Зауваження. У наступній таблиці показані типи повідомлень WM_COMMAND, які можна одержати від акселераторів, команд меню і дочірніх вікон керування.

Таблиця 2.2 Типи повідомлень WM_COMMAND

WM_COMMAND

LOWORD(wParam)

HIWORD(wParam)

lParam

Швидка клавіша

Ідентифікатор швидкої клавіші

1

0

Команда меню

Ідентифікатор пункту меню

0

0

Елемент керування

Ідентифікатор елемента керування

Код повідомлення

Дескриптор дочірнього вікна

Відрізнити повідомлення WM_COMMAND, що прийшли від меню, від повідомлень WM_COMMAND, що надсилаються елементами керування, у випадку, якщо вони мають однакові ідентифікатори, можна за допомогою значення параметра lParam:

для пунктів меню він завжди дорівнює 0,

для елементів керування він дорівнює дескриптору вікна елемента керування.

Відрізнити повідомлення WM_COMMAND, що прийшли від меню, від повідомлень WM_COMMAND, що надсилаються акселераторами (див. їхній опис у наступній главі), у випадку, якщо вони мають однакові ідентифікатори, можна за допомогою значення HIWORD(wParam):

для пунктів меню він завжди дорівнює 0,

для акселератора він завжди дорівнює 1.

Розглянемо простий приклад. У програмі MY_MENU, представленої на малюнку, у головному меню мається два пункти — Файл і Help. У кожнім з цих пунктів мається спливаюче меню. У програмі MY_MENU демонструється найпростіший і найбільш частий спосіб обробки повідомлень меню, що має на увазі перехоплення повідомлень WM_COMMAND і аналіз молодшого слова параметра wParam.

Зовнішній вигляд програми буде наступним:

Рисунок 2.13 Зовнішній вигляд програми MY_MENU.

Створення додатка, що використовує меню.

  1. Створіть новий проект MY_MENU.

  2. Т епер приступимо до створення меню, використовуваного в нашій програмі my_menu.cpp. Для чого проробимо наступне: Project | Add To Project | New. На закладці Files вибираємо в списку Resource Script, задаємо назву файлу ресурсів — my_menu і натискаємо ОК. Перейдіть у вікно Workspace, на вкладку ResourceView правою кнопкою миші кликніть на my_menu resources і виберіть пункт Insert.

Рисунок 2.14 Додавання нового ресурсу до Resource Script.

У вікні, що з'явилося, Insert Resource виберіть Menu і натисніть кнопку New.

  1. Починаємо редагувати меню. Щоб поміняти назву пункту меню, двічі клацніть по ньому й у поле Caption введіть нову назву. Щоб видалити деякий елемент, виділите його, кликнувши на ньому мишкою один раз, а потім натисніть клавішу Del.

  2. Створіть два пункти меню верхнього рівня: «Файл» і «Help». Пункт меню «Файл» повинний містити спливаюче меню з двох пунктів: «About» (ID = ID_ABOUT) і «E&xit» (ID = IDCLOSE), а пункт меню «Help» повинний містити спливаюче меню з одного пункту — «Довідка» (ID = ID_SPR). У якості ID усього меню задайте “MENUDEMO” (при завданні ID обов'язково використовуйте лапки).

  3. Тепер, коли підготовка кінчена, можна переходити до написання програми. Для початку створіть файл my_menu.cpp і скопіюйте в нього уміст файлу sample.cpp, що був створений у Лабораторній роботі №1.

  4. Крім заголовного файлу windows.h підключаємо тільки що створений редактором ресурсів заголовний файл resource.h:

#include <windows.h>

#include "resource.h"

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

  1. Функцію WinMain варто піддати наступним незначним змінам:

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

static char szAppName[] = "MenuDemo" ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

PSTR szCmdLine, int iCmdShow)

{

HWND hWnd;

MSG msg ;

WNDCLASS wndclass ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;

wndclass.lpszMenuName = szAppName;

wndclass.lpszClassName = szAppName ;

RegisterClass (&wndclass) ;

hWnd = CreateWindow (szAppName, "Menu Demonstration", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,hInstance, NULL) ;

  1. Функцію WndProc необхідно піддати більш ретельній обробці. Повідомлення WM_PAINT можна цілком видалити. Т.к. головне вікно програми містить меню, то в програмі потрібно обробляти повідомлення WM_COMMAND. Ідентифікатор дочірнього вікна елемента керування знаходиться в молодшому слові параметра wParam:

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

switch (iMsg)

{

case WM_COMMAND:

switch (wParam){

}

return 0;

case WM_DESTROY :

PostQuitMessage (0) ;

return 0 ;

  1. У даній програмі обробка пунктів меню буде максимально спрощена. При виборі пунктів «About» і «Довідка» буде виводитися на екран вікно повідомлення, а при виборі пункту «E&xit», буде вимагати підтвердження вихід із програми. Тому для обробки пункту меню «About» варто додати до програми наступний код:

switch (LOWORD (wParam))

{

case ID_ABOUT :

MessageBox (hwnd, "Обраний пункт меню About",

szAppName, MB_ICONINFORMATION | MB_OK) ;

return 0 ;

}

break ;

  1. Для обробки пункту меню «Довідка» варто додати до програми наступний код:

case ID_ABOUT :

MessageBox (hwnd, "Обраний пункт меню About",

szAppName, MB_ICONINFORMATION | MB_OK) ;

return 0 ;

case ID_SPR:

MessageBox (hwnd, "Обраний пункт меню Довідка",

szAppName, MB_ICONINFORMATION | MB_OK) ;

return 0;

}

break ;

  1. Для підтвердження виходу з програми буде використовуватися вікно повідомлення, але вже з двома кнопками: ОК і Cancel, що дозволить як підтвердити вихід, так і продовжити роботу з додатком. Для чого додайте до програми наступний код:

case ID_SPR:

MessageBox (hwnd, "Обраний пункт меню Довідка",

szAppName, MB_ICONINFORMATION | MB_OK) ;

return 0;

case IDCLOSE:

if (MessageBox(hwnd, "Ви дійсно хочете вийти?",

"Exit", MB_ICONQUESTION|MB_OKCANCEL)==IDOK)

PostQuitMessage(0);

return 0;

}

break ;

case WM_DESTROY :

PostQuitMessage (0) ;

ПРАКТИЧНА ЧАСТИНА

  1. Виконати програму MenuDemo, описану в лабораторній роботі.

2. Додайте в меню пункт Colors з підпунктами Black, Red, Green, Blue. При виборі відповідного пункту повинний змінюватися тло робочої області.

Контрольні питання:

  1. Що таке шаблон меню і де він зберігається? Чи можна за допомогою шаблона меню створювати багаторівневі меню?

  2. Як у шаблоні меню визначаються такі елементи меню як пункти і підміню?

  3. Для чого необхідні ідентифікатори пунктів меню?

  4. Як указати, що усі вікна класу за замовчуванням повинні мати якесь меню?

  5. Яким способом вікно може установити для себе меню, відмінне від меню класу вікон?

  6. Чи можна (і як) меню створювати динамічно, у процесі роботи додатка?

  7. Які повідомлення вікну приходять від меню? Чим повідомлення WM_COMMAND відрізняється від повідомлення WM_SYSCOMMAND?

  8. Чим повідомлення WM_COMMAND, що приходить від пункту меню, відрізняється від цього ж повідомлення, але керування, що прийшов від елемента?

  9. Чи можна модифікувати системне меню вікна? Як це зробити?

  10. У чому складається особливість обробки повідомлень WM_SYSCOMMAND?

  11. Як створити і використовувати незалежне плавающее меню? Які повідомлення приходять при виборі його пунктів?

Соседние файлы в папке Lab_progr_Win