Повідомлення дочірніх вікон батьківському вікну
Якщо орган управління змінює свій стан, то функція батьківського вікна отримує повідомлення WM_COMMAND. Разом з повідомленням віконна процедура отримує і додаткову інформацію. Ці додаткові параметри мають наступний сенс:
- ідентифікатор дочірнього вікна (тип UINT);
- код повідомлення (тип UINT);
- дескриптор дочірнього вікна (тип HWND).
• Ідентифікатор дочірнього вікна - це значення, яке передається функції
CreateWindow, коли створюється робоче вікно.
• Дескриптор дочірнього вікна - це значення, яке Windows повертає при виконанні функції CreateWindow.
• Код повідомлення - це додатковий код, який дочірнє вікно використовує для того, щоб повідомити батьківському вікну більш точні відомості про повідомленні.
Константи, що ідентифікують різні коди повідомлення, визначені в заголовних файлах Windows і мають відповідно такі префікси: BN_ -
"Button", EN_ - "edit", LBN_ - "listbox", CBN_ - "combobox" і SB_ - "scrollbar".
Розглянемо фрагмент віконної процедури батьківського вікна, в якому відбувається обробка натискання на дочірнє вікно-кнопку з ідентифікатором
HWND hChild = (HWND) lParam; // дескриптор дочірнього вікна if (idCtl == ID_buttoncode == BN_CLICKED)
// кнопка була натиснута
CloseWindow (hWnd); // закрити вікно-батька
Повідомлення батьківського вікна дочірнім вікнам
Батьківське вікно також може передавати повідомлення дочірнім вікнам, у відповідь на які це дочірнє вікно буде виконувати різні дії. Для цього необхідно знати дескриптор дочірнього вікна.
• Надіслати можна як звичайне віконне повідомлення (з префіксом WM_), так і специфічні для кожного типу елемента керування
Константи, що ідентифікують різні повідомлення для дочірніх вікон управління, визначені в заголовних файлах Windows і мають відповідно такі префікси: BM_ - "button", EM_ - "edit", LB_ - "listbox", CB_ - "combobox".
Для роботи з вікнами класу "scrollbar" застосовуються спеціальні Set / Get -Функції
(.) Існує два способи передачі повідомлень.
• Запис повідомлення в чергу програми. Він заснований на використанні функції
PostMessage. Ця функція поміщає повідомлення в чергу повідомлень для вікна, вказаного в параметрах, і відразу повертає управління. записане при
допомогою функції PostMessage повідомлення буде вибрано і оброблено в циклі обробки повідомлень.
• Безпосередня передача повідомлення функції вікна, минаючи чергу повідомлень. Цей метод реалізується функцією SendMessage. На відміну від функції PostMessage функція SendMessage викликає функцію вікна і повертає управління тільки після повернення з функції вікна, якому передано повідомлення.
Кожне дочірнє вікно має дескриптор вікна (тип HWND) і ідентифікатор вікна (тип UINT), які є унікальними серед інших. Знання одного з цих елементів дозволяє додатку отримати інший.
• Якщо відомий дескриптор hWndChild дочірнього вікна, то можна отримати його ідентифікатор:
• Також можна використовувати іншу функцію (хоча частина "Dlg" імені функції відноситься до вікна діалогу, насправді це функція загального призначення):
• Знаючи ідентіфіктор id дочірнього вікна, можна отримати його дескриптор: HWND hWndChild = GetDlgItem (hWndParent, id);
Розглянемо повідомлення батьківського вікна hWnd дочірньому вікна редагування класу "edit". Вікна редагування c дескриптором hWndEdit передається повідомлення про встановлення максимальної кількості символів, що вводять (5 символів):
static UINT ID_edit = 3;
static HWND hWndEdit;
Дочірні вікна і фокус введення
Дочірні елементи управління отримують фокус при натисканні миші на них.
Коли дочірні вікна управління отримують фокус введення, батьківське вікно втрачає його;
весь введення з клавіатури направляється тепер не на батьківське вікно, а на дочірнє вікно управління.
• Така ситуація створює очевидну проблему: додаток втрачає контроль над обробкою повідомлень від клавіатури.
Прикладом є те, що перекривається вікно не має можливості забезпечити перехід користувача від елемента управління до елементу управління за допомогою клавіш
Вирішення цієї проблеми полягає у використанні прийому, званого створенням підкласу вікна (window subclassing, розбиття на підкласи, установка нової віконної процедури).
• Віконна процедура дочірніх вікон управління знаходиться в надрах Windows.
Однак, можна отримати адресу цієї віконної процедури за допомогою виклику
GetWindowLong, в якому в якості параметра використовується ідентифікатор
Викликаючи функцію SetWindowLong можна не тільки отримати адресу віконної процедури дочірнього вікна управління, але і встановити нову віконну процедуру.
Так, наприклад, нові віконні процедури дочірніх вікон управління при отриманні повідомлень про натискання клавіш
Дочірні вікна управління і колір
Якщо на перекривається вікно білого кольору вивести кілька дочірніх вікон управління, в тому числі кнопки різних стилів, то видно, що кнопки типу прапорців і радіо-перемикачів виглядають не дуже привабливо - вони мають загальний сірий фон, що не дуже красиво на білому тлі батьківського вікна . Так відбувається тому, що
вікна управління в основному призначаються для виведення на екран у вікнах діалогу,
а вони зазвичай мають сіру поверхню.
Щоб дочірні вікна управління виглядали привабливо, необхідно
• або якось змінити колір робочої області вікна, погоджуючи його з квітами вікон управління;
• або змінити налаштування кольорів вікон управління.
Зміна кольору робочої області вікна
Розглянемо тепер перший спосіб вирішення проблеми кольору. Попередньо обговоримо, як Windows використовує системні кольори (system colors).
Windows підтримує 25 системних квітів, призначених для відтворення різних елементів екрану. Додаток може отримати або встановити значення на поточний цих квітів (на час поточного сеансу Windows) за допомогою функцій GetSysColor і SetSysColor і ідентифікаторів системних кольорів. Ідентифікатори системних кольорів з префіксом COLOR_, визначені в заголовних файлах Windows.
• Наприклад, колір COLOR_BTNFACE є основним кольором поверхні натискає кнопок і кольором фону інших (цей же колір використовується у вікнах діалогу і повідомлень). А колір COLOR_WINDOWTEXT для прапорців і радіопереключателей використовується як колір тексту.
При визначенні класу батьківського вікна для фону робочої області можна використовувати системний колір, наприклад COLOR_BTNFACE:
• Windows розуміє, що якщо значення поля hbrBackground таке низьке, то воно фактично посилається на системний колір, а не реальний дескриптор кисті. Windows в цьому випадку вимагає, щоб при використанні ідентифікаторів системних квітів до них додавали 1 (щоб це значення Герасимчука рівним
• Якщо виводити текст на екран, використовуючи функцію TextOut, то Windows для кольору фону тексту (колір, який стирає фон позаду тексту) і кольору самого тексту використовує значення, визначені в контексті пристрою. За замовчуванням це білий (фон) і чорний (текст) кольору незалежно від системних кольорів і поля hbrBackground структури класу вікна.
Для зміни кольору і фону тексту, що виводиться в робочій області батьківського вікна, на системні кольори, необхідно після отримання дескриптора hDC контексту пристрою для вікна батьківського вікна викликати функції:
В результаті колір фону робочої області батьківського вікна, колір фону тексту і колір самого тексту приведені у відповідність з кольором кнопок.
Налаштування кольорів дочірніх вікон управління
Коли дочірнє вікно управління збирається малювати свою робочу область, воно посилає процедурі батьківського вікна відповідне повідомлення
WM_CTLCOLOR ... (наприклад, кнопка посилає повідомлення WM_CTLCOLORBTN).
• Батьківське вікно на підставі цього повідомлення може міняти кольори,
які буде використовувати віконна процедура дочірнього вікна при малюванні.
• Батьківське вікно може керувати кольорами своїх дочірніх вікон. Саме обробка повідомлень запиту дочірніми вікнами інформації про колір і є другий спосіб вирішення проблеми неузгодженості квітів.
Розглянемо приклад управління кольором кнопки. Коли кнопка збирається малювати свою робочу область, вона посилає процедурі батьківського вікна повідомлення WM_CTLCOLORBTN. Батьківське вікно на підставі цього повідомлення може міняти кольори, які буде використовувати віконна процедура кнопки при малюванні.