Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Модальні і немодальні діалогові вікна






3.1.1 Конструктори діалогових вікон

Використання діалогових вікон надає користувачу програми нові, більш широкі можливості. Діалогові вікна у дуже простий спосіб забезпечуються елементами керування, що дає змогу легко контролювати режими роботи програми, особливо, коли мета програми полягає в управлінні будь-яким пристроєм. Саме для діалогових вікон Visual C++ дозволяє використовувати спеціальну програму Class Wizard, що автоматично організовує взаємодію елементів керування програми із відповідними змінними програми.

У бібліотеці MFC діалогові вікна забезпечуються класом CDialog, що у свою чергу успадковує свої властивості від загального класу вікон – СWnd. Багато віконних функцій унаслідується з батьківського класу, разом з тим, CDialog сам забезпечений рядом власних функцій.

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

Побудова діалогових вікон забезпечується трьома конструкторами класу СDialog:

CDialog:: CDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);

CDialog:: CDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL);

CDialog:: CDialog();

де lpszTemplateName містить рядок із ресурсу шаблону діалогового вікна, nIDTemplate - містить ідентифікатор ресурсу шаблону діалогового вікна; pParentWnd – покажчик на вікно-власник, наприклад, головне вікно програми. За замовчуванням, діалогове вікно не має власника, тобто як другий параметр вказується покажчик на нульову адресу – NULL.

За допомогою перших двох конструкторів створюються діалогові вікна модального типу, за допомогою третього – конструктора без параметрів, створюються об’єкти немодальних діалогових вікон.

Для забезпечення роботи з діалоговими вікнами, необхідно:

1) у редакторі ресурсів створити шаблон діалогового вікна із власним ідентифікатором;

2) створити клас діалогового вікна та визначити опис конструктора;

3) забезпечити виклик діалогового вікна у бажаний спосіб.

 

3.1.2 Ресурси діалогових вікон

Для створення ресурсу діалогового вікна необхідно у стандартний спосіб (див. п.2.5) запустити редактор ресурсів та обрати тип ресурсу “Dialog”. Після цього (якщо не обрано спеціальний тип діалогових вікон, позначений „+”), з’являється вікно, подібне зображеному на рисунку 3.1.

 

 

Рисунок 3.1 – Вигляд діалогового вікна у редакторі ресурсів

 

Як видно з рисунка ресурс діалогового вікна розміщений у файлі Script3.rc і має ідентифікатор IDD_DIALOG1 (видно у заголовку вікна). Стан-дартно шаблон діалогового вікна забезпечується двома клавішами: “OK” та “Cancel”. Інші елементи керування можуть бути додані з віконця елементів керування, що на рисунку 3.1 розташоване праворуч. Для цього достатньо лівою клавішею миші обрати необхідний елемент керування та тією ж клавішею розмістити у необхідному місці шаблону діалогового вікна.

 

3.1.3 Створення класів діалогових вікон

Для використання діалогового вікна в програмному проекті, слід створити клас, унаслідуваний від CDialog. У прикладі 3.1 наведено такий клас для модального діалогового вікна. Також у цьому класі об’явлено карту повідомлень.

 

Приклад 3.1 – Оголошення класу модального діалогового вікна

class CSampleDialog: public CDialog

{public: CSampleDialog(UINT id, CWnd *Owner): CDialog(id, Owner){}

DECLARE_MESSAGE_MAP()};

Як видно з прикладу, у класі CSampleDialog оголошено конструктор другого типу. Зазвичай конструктор оголошується всередині опису класу. У прикладі 3.1 параметри id та Owner (ідентифікатор ресурсу діалогового вікна та покажчик на батьківське вікно) передаються з конструктора класу безпосередньо у конструктор батьківського класу CDialog.

Конструктор класу CSampleDialog можна викликати у такий спосіб:

 

CSampleDialog MyDialog(IDD_DIALOG1, NULL);

 

у цьому випадку оголошується об’єкт MyDialog, якому відповідає ресурс із ідентифікатором IDD_DIALOG1. MyDialog не має власника, на що вказує значення NULL другого параметра.

У наступному прикладі 3.2 наведено оголошення класу немодального (англійською мовою - modeless) вікна. Тому не дивно, що конструктор класу не має параметрів.

 

Приклад 3.2 – Оголошення класу немодального діалогового вікна

class CModeLess: public CDialog

{public: CModeLess(): CDialog(){}

DECLARE_MESSAGE_MAP()};

 

Виклик такого конструктора дуже простий: це просто оголошення відповідної змінної:

СModeLess MyModeless;

Таке оголошення звичайно є глобальним у тексті програми.

 

3.1.4 Виклик діалогових вікон

Після того, як створено ресурс діалогового вікна і оголошено його об’єкт, переходять до викликів.

Виклик модальних діалогових вікон забезпечує функція DoModal(). Якщо забезпечити виклик модального діалогового вікна з головного вікна програми, наприклад, вибором відповідного пункту меню можна написати такий приклад:

 

Приклад 3.3 – Виклик модального діалогу з обробника головного вікна

void CMainWin:: OnDialog()

{CSampleDialog a(IDD_DIALOG1, this);

a.DoModal();

}

 

У прикладі спочатку створюється об’єкт модального діалогового вікна, який потім активізується функцією DoModal().

Нагадаємо, що this означає покажчик на об’єкт, для якого викликана функція. Звичайно, що всі функції класу CMainWin викликаються для об’єкта вікна, тому this і є покажчиком на головне вікно програми.

Для немодальних вікон необхідно описати іншу послідовність. Вона відображається прикладом 3.4.

 

Приклад 3.4 – Виклик немодального діалогу з обробника головного вікна

 

CModeLess ml; // глобальна змінна

void CMainWin:: OnModeless()

{ml.Create(IDD_DIALOG2, this);

ml.ShowWindow(SW_SHOWNORMAL);

}

 

Як видно з прикладу, спочатку оголошено глобальний об’єкт класу немодального діалогового вікна, потім у обробнику за допомогою функції Create() об’єкт немодального діалогу пов’язується із шаблоном ресурсу й відображується за допомогою функції ShowWindow().

Закриття модальних діалогових вікон забезпечується стандартними об-робниками OnOK() та OnCancel(). Обидва обробники викликають функцію EndDialog(1).

Закриття немодальних діалогових вікон забезпечується у інший спосіб: викликом функції DestroyWindow(). Саме такий виклик і розміщують у обробниках OnOK() та OnCancel() класу немодального діалогу.

 

3.2 Обробка повідомлень діалогових вікон та їх ініціалізація

 

Вище зазаначувалося, що клас CDialog є спадкоємцем класу CWnd, тобто успадковує усі стандартні властивості звичайних вікон. Тому про події у діалоговому вікні програма дізнається через той же самий механізм надсилання повідомлень. Щоправда, обробка повідомлень вже не орієнтується на головне вікно програми. Навпаки, кожне діалогове вікно повинно мати свою власну чергу повідомлень і власні обробники.

У загальному випадку, кожному елементу керування, що розміщується у діалоговому вікні відповідає власний ідентифікатор. Якщо елемент активується користувачем, діалоговому вікну надсилається повідомлення WM_COMMAND, з яким також асоціюється ідентифікатор обраного елемента. Для обробки повідомлення у карту повідомлень додається макрокоманда ON_COMMAND().

Нехай створено ресурс діалогового вікна, зображений на рисунку 3.2.

 

 

Рисунок 3.2 – Вигляд ресурсу діалогового вікна з кнопкою Button1

 

У даному випадку для реалізації виведення на екран подібного вікна, додамо у проект клас CSampleDialog із оголошенням існування карти повідомлень. Це матиме такий вигляд:

 

Приклад 3.5 – Клас діалогового вікна із оголошенням карти повідомлень

class CSampleDialog: public CDialog

{public:

void OnClose();

CSampleDialog(UINT id, CWnd *Owner): CDialog(id, Owner){}

DECLARE_MESSAGE_MAP()

};

 

У клас окрім конструктора та карти повідомлень включено функцію-обробник – OnClose(). Нехай, саме ця функція буде реакцією програми на натиск користувачем кнопки Button1 у діалоговому вікні, зображеному на рис. 3.2.

Для обробки повідомлення натискання клавіші, у *.cpp файл проекту необхідно додати текст карти повідомлень, що матиме такий вигляд:

BEGIN_MESSAGE_MAP(CSampleDialog, CDialog)

ON_COMMAND(IDC_BUTTON1, OnClose)

END_MESSAGE_MAP()

 

Тут IDC_BUTTON1 – ідентифікатор кнопки Button1 ресурсу діалогового вікна. Зміст карти повідомлень такий: вибір користувачем кнопки із ідентифікатором IDC_BUTTON1 означатиме виклик функції OnClose(). Тому тепер необхідно визначити саму функцію OnClose(), наприклад:

 

void CSampleDialog:: OnClose()

{SendMessage(WM_CLOSE); }

 

У такий простий спосіб обробляються повідомлення кнопок. Програма отримує повідомлення WM_COMMAND від кнопки із ідентифікатором IDC_BUTTON1 і знаходить відповідний йому обробник OnClose().

Інколи стан елементів вікна необхідно задавати перед виведенням діалогового вікна на екран. Для цього Windows автоматично надсилає повідомлення WM_INITDIALOG. Після отримання цього повідомлення MFC викликає функцію OnInitDialog(), що є стандартним обробником класу CDialog із таким прототипом:

 

virtual BOOL CDialog:: OnInitDialog();

 

З тієї причини, що це – стандартний обробник, відповідна йому макрокоманда розміщується у карті повідомлень, але сам обробник слід перевизначити, причому всередині обробника розміщують і виклик функції батьківського класу:

 

BOOL CSampleDialog:: OnInitDialog()

{CDialog:: OnInitDialog();

………………} // тут розміщують ініціалізацію елементів керування

 

Детальні приклади цієї функції стосуватимуться ініціалізації елементів керування і тому розміщені пізніше.

 

3.3 Використання діалогових вікон як головних

 

Після розгляду методів створення діалогових вікон може виникнути бажання скоротити текст програми, виключивши з нього створення головного вікна, наслідуваного від CFrameWnd. Це можна зробити, розмістивши використання конструктора діалогового вікна безпосередньо у функції InitInstance() класу прикладки проекту:

 

BOOL CApp:: InitInstance()

{CSampleDialog a(IDD_DIALOG1, m_pMainWnd);

a.DoModal();

return TRUE; }

Тоді весь код проекту скоротиться до такого вигляду:

 

Приклад 3.6 – Використання діалогового вікна як головного вікна проекту

// файл d01.h

class CApp: public CWinApp

{public: BOOL InitInstance(); };

 

class CSampleDialog: public CDialog

{public: BOOL OnInitDialog();

void OnClose();

CSampleDialog(UINT id, CWnd *Owner): CDialog(id, Owner){}

DECLARE_MESSAGE_MAP()};

 

// файл d01.cpp

#include < afxwin.h>

#include " d01.h"

#include " resource.h"

 

BOOL CApp:: InitInstance()

{CSampleDialog a(IDD_DIALOG1, m_pMainWnd);

a.DoModal();

return TRUE; }

 

CApp App;

 

BEGIN_MESSAGE_MAP(CSampleDialog, CDialog)

ON_COMMAND(ID_CLOSE, OnClose)

END_MESSAGE_MAP()

 

void CSampleDialog:: OnClose(){SendMessage(WM_CLOSE); }

 

BOOL CSampleDialog:: OnInitDialog()

{CDialog:: OnInitDialog();

// у цьому прикладі функція OnInitDialog() фактично є зайвою

return TRUE;

}


3.4 Діалогові вікна та стандартні елементи керування

 

3.4.1 Загальна інформація

Використання елементів керування дозволяє зробити вигляд інтерфейсу програми більш зручним і виразним. Елементи керування розрізнюються за своєю складністю і поділяються на стандартні, спільні та ActiveX-елементи. На відміну від двох останніх, стандартні елементи керування не вимагають підключення спеціальних файлів заголовків. Для них достатньо включити вже звичний файл afxwin.h.

У MFC всі стандартні елементи керування описані в класах, які успадковують властивості базового класу CWnd, тобто можна сказати, що усі вони є вікнами певного вигляду. Тому, кожен елемент керування має власний доступ до тих самих функцій, як будь-який інший тип вікна.

До стандартних елементів керування належать: кнопка, контрольний перемикач, селекторна кнопка, список, поле редагування, розширений список, смуга прокручування, статичний елемент. Вони описуються такими класами: CButton – описує кнопки, контрольні та селекторні перемикачі, CListBox – списки, CEdit – вікна редагування, CComboBox – списки із розширеними властивостями, CScrollBox – смуги прокручування, CStatic – статичні елементи. Вигляд стан-дартних елементів керування наведено на рисунку 3.3.

 

3.4.2 Використання списків

Список (або вікно списку) є одним з стандартних елементів керування. Він призначений для відображення послідовності однотипних даних. У MFC списки забезпечуються класом CListBox.

Вікно списку генерує повідомлення різних типів. Наприклад, повідомлення про подвійне натискання кнопки миші на елементі списку, повідомлення на втрату активного стану (на бездіяльність вікна списку), повідомлення про вибір елемента списку. Кожному такому повідомленню може відповідати макрокоманда. За необхідності її можна включити до тексту карти повідомлень. У таблиці 3.1 наведено основні макрокоманди, пов’язані із використанням списків.

 

Таблиця 3.1 – Макрокоманди повідомлень списків

Ім’я макрокоманди Коментар
ON_LBN_DBLCLK Подвійне натискання лівої клавіші миші на списку
ON_LBN_ERRSPACE Недостатньо пам’яті
ON_LBN_KILLFOCUS Втрата фокусу списком
ON_LBN_SELCANCEL Переривання поточного вибору у вікні списку (стиль списку – LBS_NOTIFY)
ON_LBN_SELCHANGE Обраний елемент змінюється (стиль списку – LBS_NOTIFY)
ON_LBN_SETFOCUS Список отримує фокус вводу
ON_WM_CHARTOITEM Пустий список отримує повідомлення WM_CHAR
ON_WM_VKEYTOITEM Список зі стилем LBS_WANTKEYBOARDINPUT отримує повідомлення WM_KEYDOWN

Рисунок 3.3 – Стандартні елементи керування та їх зовнішній вигляд

 

У відповідність кожній макрокоманді можна поставити функцію-обробник. Загальний вигляд запису макрокоманди ON_LBN_DBLCLK має вигляд:

 

ON_LBN_DBLCLK (ідентифікатор_списку, Ім’я_функції_обробника)

 

Прототипи основних функцій класу CListBox наведені у таблиці 3.2.

 

Таблиця 3.2 – Деякі функції-члени класу CListBox

Прототип функції Коментар
CListBox:: AddString(LPCTSTR lpszItem); Додає рядок у список, lpszItem – покажчик на рядок, що додається. Повертає індекс доданого рядка.
int CListBox:: GetCurSel();   Повертає індекс обраного рядка. Якщо жоден рядок списку не обраний – повертає LB_ERR.
int CListBox:: GetText(int nIndex, LPTSTR lpszBuffer); Записує вміст рядку nIndex у покажчик lpzsBuffer. Повертає довжину рядка в байтах.
int CListBox:: DeleteString(UINT nIndex); Вилучає рядок із номером nIndex зі списку. По-вертає кількість рядків, що залишилася.
int CListBox:: InsertString(int nIndex, LPCTSTR lpszItem); Додає покажчик на рядок lpszItem у позицію nIndex списку, або у кінець списку, якщо nIndex дорівнює -1. Повертає номер позиції, у яку додано рядок.
int CListBox:: GetCount() Повертає кількість рядків у списку або LB_ERR у разі помилки.

 

Для організації роботи зі списком у діалоговому вікні забезпечте такі умови:

1) побудуйте проект за прикладом 3.6, у якому ідентифікатор IDD_DIALOG1 відповідає ресурсу діалогового вікна, створеному у редакторі ресурсів;

2) додайте список у ресурс діалогового вікна та занотуйте його ідентифікатор, наприклад IDC_LIST1;

3) додайте покажчик на об’єкт типу СListBox у клас діалогового вікна CSampleDialog;

4) у функції OnInitDialog() зв’яжіть покажчик на список та ресурс списку;

5) забезпечте ініціалізацію списку.

Перші три пункти послідовності – вже відомі. Останні два - забезпечується у функції OnInitDialog().

 

Приклад 3.7 – Ініціалізація списку

BOOL CSampleDialog:: OnInitDialog()

{CDialog:: OnInitDialog();

lb=(CListBox*)GetDlgItem(IDC_LIST1); //Зв’язування покажчика lb та ресурсу IDC_LIST1






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.