6 БЛОКНОТ І ТРОХИ ЧАРІВНИЦТВА
Якщо ваш додаток складне і має велику кількість параметрів, слід добре подумати про те, як користувач буде їх налаштовувати. Зазвичай для настройки пропонується багаторівнева система вкладених меню і нагромадження діалогових панелей, які викликаються одна з одної, однак це зовсім не те, чого зрадіє користувач.
Якщо ви подивіться, як виглядає система настройки параметрів, наприклад, в додатку Microsoft Word for Windows версії 6.0, то побачите, що вона організована у вигляді блокнота, що складається з декількох діалогових панелей із закладками (рис. 6.1). Мабуть, це найбільш вдалий варіант, так як користувач може легко знайти і вибрати потрібну йому групу параметрів.
Мал. 6.1. Блокнот настройки параметрів в додатку Microsoft Word for Windows версії 6.0
Реалізація блокнота засобами програмного інтерфейсу Microsoft Windows версії 3.1 вельми непроста, проте в операційній системі Microsoft Windows 95 є вбудоване засіб, що значно полегшує створення подібних систем настройки параметрів. Це засіб - органи управління Tab і Property Sheet.
Орган управління Tab виглядає як набір закладок (верхня частина рис. 6.1). Його можна використовувати окремо (вихідні тексти у відповідній програмі TABCTRL є в SDK), проте ми обмежимося випадком, який зустрічається частіше - використанням його в складі органу управління Property Sheet, який ми і будемо називати блокнотом.
Орган управління Property Sheet в Microsoft Windows 95 виглядає трохи інакше, ніж блокнот, показаний на рис. 6.1. Для порівняння ви можете поглянути на рис. 1.6, розташований в першому розділі, або на рис. 6.2 (див. Нижче). Відмінність полягає в тому, що кнопки управління блокнотом (OK, Cancel, Help і Apply) розташовані в нижній частині вікна блокнота.
Як працюють ці кнопки?
Якщо натиснути на кнопку OK, будуть встановлені нові значення параметрів, після чого вікно блокнота зникне з екрану. Як і слід було очікувати, за допомогою кнопки Cancel можна скасувати внесення змін до параметри. Кнопка Help надає доступ до довідкової системи.
Кнопка Apply дає можливість змінити параметри і подивитися, як позначаться ці зміни на додатку. Якщо натиснути на цю кнопку, вікно блокнота залишиться на екрані, так що якщо нова комбінація параметрів вас не задовольнить, ви зможете спробувати іншу. При цьому вам не доведеться знову вибирати з меню рядок, що викликає на екран блокнот.
Тепер про чарівність.
Звичайно, наша книжка не про чаклунство або магії, однак користувачі люблять, коли програми самостійно виконують за них всю роботу або хоча б частину роботи (чим не диво?). Проте, яка б "розумна" була ваша програма, все ж їй доводиться при виконанні завдань в напівавтоматичному режимі задавати користувачеві питання або ставити його перед необхідністю вибору різних альтернатив.
І хоча Microsoft Windows 95 не містить ніяких магічних органів управління, здатних впорається з будь-якою роботою, в цій операційній системі все ж є засіб, що дозволяє легко організувати діалог з користувачем в процесі напівавтоматичного виконання тих чи інших завдань. Прикладом може послужити діалог при установці операційної системи Microsoft Windows 95. Це засіб - орган управління Wizard (в перекладі це означає "чаклун", однак ми утримаємося від такої термінології).
Орган управління Wizard. так само як і блокнот, являє собою набір діалогових панелей (рис. 1.7, 6.6, 6.7 і 6.8). Різниця полягає в тому, що в блокноті користувач має доступ до будь-якої діалогової панелі, висуваючи її на передній план за допомогою закладки, а в органі управління Wizard він пересувається від однієї панелі до іншої і назад за допомогою кнопок Back і Next. При досягненні останньої діалогової панелі кнопка Next замінюється на кнопку Finish. Варто на неї натиснути і. (О, диво!) Все буде зроблено.
Незважаючи на зазначені відмінності, органи управління Property Sheet і Wizard дуже схожі один на одного (не по зовнішньому вигляду, а за способом створення і управління). Тому ми і розглянемо їх в одному розділу.
Спочатку займемося органом управління Property Sheet.
Для створення органу управління Property Sheet ви повинні зробити наступне:- підготувати шаблони діалогових панелей в ресурсах додатка (хоча їх можна створювати і динамічно);
- підготувати функції діалогу для кожної діалогової панелі (можливо також використання однієї і тієї ж функції діалогу для декількох панелей, що містять однакові органи управління);
- створити і заповнити масив структур типу PROPSHEETPAGE. кожен елемент якого описує окрему сторінку блокнота;
- створити і заповнити структуру типу PROPSHEETHEADER. описує блокнот;
- створити окремі сторінки блокнота за допомогою функції CreatePropertySheetPage і потім відобразити блокнот функцією PropertySheet (як ми покажемо далі, можна обійтися без функції CreatePropertySheetPage, що спрощує процес створення блокнота).
Відразу відзначимо, що для створення органу управління Wizard необхідно використовувати таку саму процедуру. Відмінності полягають у заповненні структур і обробці повідомлень у функціях діалогу.
Розглянемо перераховані вище кроки докладніше.
Підготовка шаблонів діалогових панелей
Шаблон діалогової панелі готується звичайним способом за допомогою інтегрованого середовища розробки додатків Microsoft Visual C ++. Єдине, на що нам хотілося б звернути увагу: на сторінках блокнота і органу управління Wizard немає кнопок OK, Cancel і Help, так як ці кнопки відносяться до всього блокноту і розташовуються в нижній частині його вікна. В іншому шаблони сторінок блокнота нічим не відрізняються від шаблонів звичайних діалогових панелей.
Функція діалогу сторінки блокнота
На відміну від звичайної функції діалогу, функція діалогу для сторінки блокнота або органу управління Wizard не викликає функцію EndDialog. так як це призвело б до знищення органу управління. Ось приклад функції діалогу для сторінки блокнота, взятий з програми Property Sheet Demo, повні вихідні тексти якого ви знайдете нижче в розділі "Додаток Property Sheet Demo":
Так само як і у функції головного вікна додатків, в функції діалогу для організації обробки повідомлень ми скористалися зручною макрокомандою HANDLE_MSG.
Підготовка масиву структур PROPSHEETPAGE
Для кожної сторінки блокнота або органу управління Wizard ви повинні підготувати структуру PROPSHEETPAGE. записавши в неї опис сторінки. Структура PROPSHEETPAGE визначена наступним чином:
Можливо, ця структура виглядає дещо громіздко, проте її заповнення не викличе у вас ніяких труднощів.
В поле dwSize необхідно записати розмір структури, т. Е. Значення sizeof (PROPSHEETPAGE).
В поле dwFlags слід записати прапори, які відзначають задіяні поля структури і визначають зовнішній вигляд органу управління. Тут можна використовувати такі значення:
У нашому додатку ми використовували прапори PSP_USETITLE і PSP_USEICONID.
Поле hInstance повинно містити ідентифікатор додатки, який передається через відповідний параметр функції WinMain.
Поля pszTemplate і pResource об'єднані, тому ви можете використовувати тільки одне з них. За замовчуванням ви повинні записати в поле pszTemplate ідентифікатор ресурсу, що містить шаблон діалогової панелі. Однак вказавши прапор PSP_DLGINDIRECT, ви замість цього можете створити шаблон діалогової панелі динамічно в оперативній пам'яті і записати покажчик на цей шаблон в поле pResource.
Аналогічним чином об'єднані поля hIcon і pszIcon. Якщо в поле pszIcon ви збираєтеся записати ідентифікатор піктограми, яка буде відображатися в закладці, слід вказати прапор PSP_USEHICON. Якщо ж піктограма визначена в ресурсах додатка, ви повинні записати відповідний ідентифікатор ресурсу в поле pszIcon і вказати прапор PSP_USEICONID.
У тому випадку, коли вам не потрібно відображати піктограму на закладці, не вказуйте прапори PSP_USEHICON і PSP_USEICONID, а в поле pszIcon (або hIcon, що одне й те саме) запишіть значення NULL.
При створенні шаблону діалогової панелі ви можете вказати її заголовок. Однак замість цього можна використовувати поле pszTitle і прапор PSP_USEICONID.
Ось як ми заповнили поля структури PROPSHEETPAGE для трьох сторінок блокнота в додатку Property Sheet Demo:
Заповнення структури PROPSHEETHEADER і створення блокнота
Структура PROPSHEETHEADER. як це видно з її назви, описує заголовок блокнота. Вона має такий вигляд:
В поле dwSize потрібно записати розмір структури.
Поле dwFlags може містити логічну комбінацію наступних значень:
Створюється орган управління Wizard, а не блокнот Property Sheet
У додатку Property Sheet Demo ми заповнили структуру PROPSHEETHEADER наступним чином:
Після заповнення заголовка блокнота можна створити блокнот (або орган управління Wizard, якщо вказано прапор PSH_WIZARD) за допомогою функції PropertySheet.
Є ще один спосіб створення блокнота або органу управління Wizard без використання функції CreatePropertySheetPage. Ми застосували цей спосіб в додатку Wizard Demo:
Тут ми не використовуємо піктограму, так як вона все одно не відображається, тому в поле pszIcon записано значення NULL. Крім того, вказані прапори PSH_PROPSHEETPAGE і PSH_WIZARD.
Для органів управління Propery Sheet і Wizard визначені наступні коди повідомлень:
Це повідомлення передається функції діалогу, коли активізується відповідна сторінка блокнота або органу управління Wizard. Оброблювач повідомлення може виконати всі необхідні ініціалізували дії
Сторінка відсувається на задній план або віддаляється з екрану. Оброблювач цього сповіщення може перевірити введені користувачем значення і якщо вони неправильні, заблокувати перемикання на інші сторінки блокнота
Це повідомлення надсилається коли користувач натискає кнопку OK або Apply
Повідомлення PSN_HELP надсилається коли користувач натискає кнопку Help
Повідомлення PSN_QUERYCANCEL надсилається коли користувач натискає кнопку Cancel, збираючись закрити блокнот. Оброблювач може заборонити це дія, наприклад, якщо користувач не вказав будь-які необхідні параметри
Це повідомлення надсилається слідом за повідомленням PSN_QUERYCANCEL, якщо обробник останнього не заборонив закриття блокнота
Надсилається, коли користувач натиснув кнопку Back в органі управління Wizard
Надсилається, коли користувач натиснув кнопку Next в органі управління Wizard
Надсилається, коли користувач натиснув кнопку Finish в органі управління Wizard
Обробники повідомлень можуть повертати значення FALSE або TRUE, проте в більшості випадків додатково необхідно встановлювати код завершення в структурі даних діалогу за допомогою функції SetWindowLong. При цьому в якості другого параметра для цієї функції слід вказати значення DWL_MSGRESULT.
У наступному фрагменті коду, який взятий з програми "Property Sheet Demo", перевіряється довжина рядка szTempBuf. Якщо вона більше 8, повертається значення TRUE, а якщо менше - FALSE:
Більш детальну інформацію про використання цих повідомлень ви зможете знайти в довідковій системі SDK. Найпотрібніші з них будуть зазначені у пунктах "Додаток Property Sheet Demo" і "Wizard Demo".
Обробники повідомлень, розташовані в функціях діалогу, можуть посилати органам управління Property Sheet і Wizard різні повідомлення, додаючи або видаляючи окремі сторінки, змінюючи стан кнопок, таких як Apply або Next, і т. Д.
Нижче ми привели список таких повідомлень з коротким описом.
Додавання нової сторінки в кінець блокнота
Дія цього повідомлення еквівалентно дії кнопки Apply. При цьому поточна сторінка отримає повідомлення з кодом PSN_KILLACTIVE
Якщо послати це повідомлення, замість кнопки Cancel з'явиться кнопка Close. Використовується в тих випадках, коли користувач виконав такі зміни, від яких вже не можна відмовитися
Це повідомлення розблокує кнопку Apply
За допомогою цього повідомлення можна дізнатися ідентифікатор органу управління Tab (в нашій книзі не описаний), який використовується для створення закладок в блокноті
За допомогою цього повідомлення можна симулювати дію кнопок управління блокнотом або органом управління Wizard, таких як, наприклад, OK, Next або Finish
Передача повідомлення функцій діалогу всіх сторінок в блокноті