Предмет:
Тип роботи:
Лабораторна робота
К-сть сторінок:
25
Мова:
Українська
style="text-align: justify;">switch (iMsg)
{
case WM_PAINT: //Перемалювати вміст клієнтської області вікна
{... }
break;
case WM_DESTROY: // Користувач видалив вікно
{... }
break;
default:
return DefWindowProc (hWnd, msg, wParam, lParam) ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}//кінець WndProc
Додайте вищенаведений код до свого файлу з початковим кодом.
Функція вікна одержує повідомлення з двох джерел: із циклу обробки повідомлень і від Windows:
З циклу обробки повідомлень надходять повідомлення введення, : переміщення і натискання клавіш миші, натискання і відпускання клавіш клавіатури і, якщо встановлений генератор подій таймера, повідомлення від таймера.
Windows посилає функції вікна повідомлення підтримки вікна прямо, минаючи чергу додатка і цикл обробки повідомлень. Ці повідомлення звичайно викликані подіями, що вимагають негайної реакції по зміні виду вікна.
2.9. Повідомлення WM_PAINT
Повідомлення WM_PAINT украй важливо для програмування під Windows. Воно повідомляє програмі, що частина чи вся робоча область вікна недійсна (invalid), і її варто перемалювати.
Розглянемо ситуації, коли робоча область може ставати недійсною.
При першому створенні вікна недійсна вся робоча зона (інша назва – клієнтська частина) вікна, оскільки програма ще нічого не намалювала. Повідомлення WM_PAINT, що посилається, коли додаток викликає функцію UpdateWindow, змушує віконну процедуру щось намалювати в робочій області.
Коли користувач змінює розмір вікна, у стилі якого задані прапори CS_HREDRAW і CS_VREDRAW, робоча область також стає недійсною. Операційна система слідом за цим посилає у віконну процедуру повідомлення WM_PAINT.
Коли користувач мінімізує вікно програми, а потім знову відновлює до колишнього розміру, то в Windows уміст робочої області не зберігається (у графічному середовищі це б привело до того, що довелося б зберігати занадто багато даних). Замість цього Windows робить недійсним усе вікно. Потім віконна процедура одержує повідомлення WM_PAINT і сама відновлює вміст вікна.
Коли користувач переміщає вікна так, що вони перекриваються, Windows не зберігає ту частину вікна, що закривається іншим вікном. Коли ця частина пізніше відкривається, Windows відзначає цю область як недійсну. Віконна процедура одержує повідомлення WM_PAINT для відновлення вмісту вікна.
Якщо по логіці роботи додатка при обробці того чи іншого повідомлення потрібно змінити уміст вікна, то додаток може саме за допомогою функції InvalidateRect оголосити будь-яку область вікна як недійсну (тобто потребуючу відновлення) :
InvalidateRect (hWnd, NULL, TRUE) ;
Зауваження. Перший параметр функції InvalidateRect є ідентифікатором вікна, для якого виконується операція. Другий параметр – покажчик на структуру типу RECT, що визначає прямокутну область, що підлягає відновленню (якщо він дорівнює NULL, те недійсної з'являється уся внутрішня частина вікна). Третій параметр визначає необхідність стирання фону вікна (якщо параметр заданий як TRUE, фон вікна підлягає стиранню).
Отже,
Повідомлення WM_PAINT посилається операційною системою вікну, коли його частина вимагає перемальовування, і в черзі повідомлень потоку, що володіє цим вікном, не знаходиться інших неопрацьованих повідомлень.
Якщо вікно містить одну чи кілька областей, що підлягають відновленню, то додаток одержує одне повідомлення WM_PAINT, у якому визначена область, що охоплює всі зазначені області.
Обробка повідомлення WM_PAINT майже завжди починається з виклику функції BeginPaint, а закінчується EndPaint.
Додайте цей код:
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
…
case WM_PAINT: // Обновити вміст клієнтської області вікна
{
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, «Hello, Windows!», -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
break;
case WM_DESTROY:
…
В обох функціях перший параметр – це дескриптор вікна додатка, а другий – це покажчик на структуру типу PAINTSTRUCT. У цій структурі міститься деяка інформація, яку віконна процедура може використовувати для малювання в робочій області вікна.
Зокрема, одне з полів цієї структури являє собою наймаленький прямокутник, що містить всі області вікна, що вимагають перемальовування. Обмеживши свої дії по малюванню тільки цією прямокутною областю, додаток може прискорити процес перемальовування.
При обробці виклику BeginPaint, Windows
- обновляє фон робочої області за допомогою кисті, що вказувалася при реєстрації класу вікна;
- робить усю робочу область дійсною (не потребуючою перемальовування) ;
- повертає дескриптор контексту пристрою (цей дескриптор необхідний для виводу в робочу область тексту і графіки).
При використанні дескриптора контексту пристрою, що повертається функцією BeginPaint, додаток не може малювати поза робочою областю. Функція EndPaint звільняє дескриптор пристрою, після чого його не можна використовувати.
Зауваження 1. Функцію BeginPaint варто викликати тільки у відповідь на повідомлення WM_PAINT. Кожен виклик цієї функції повинний сполучатися з наступним викликом функції EndPaint.
Зауваження 2. Тому що додаток практично ніколи при обробці повідомлення WM_PAINT не знає розмірів усієї своєї клієнтської області, то перед малюванням воно може одержати цю інформацію за допомогою функції:
BOOL GetClientRect (HWND hWnd, LPRECT rect) ;
Перший параметр – дескриптор вікна, другий – покажчик на змінну типу RECT, у цю змінну функція GetClientRect поміщає інформацію про розмір робочої області в пікселях.
Функція DrawText () призначена для виводу тексту на екран у визначеній позиції. У загальному вигляді вона виглядає так:
int DrawText (
HDC hdc, // дескриптор контексту дисплея
LPCTSTR lpString, // покажчик на відображуваний рядок
int nCount, // довжина рядка
LPRECT rect, // куди виводити
UINT uFormat) ; // прапори форматованого відображення тексту
Якщо lpString указує на рядок, що закінчується 0, то nCount=-1. DT_SINGLELINE означає, що текст розташовується в один рядок, тобто не містить символів переводу рядка і повернення каретки. DT_CENTER і DT_VCENTER визначають положення рядка в межах клієнтської області (тому що перед використанням цієї функції ми викликали функцію визначення робочої області додатка – GetClientRect (hwnd, &rect) ;) – у центрі вікна.
Функція TextOut () призначена для виводу рядка символів на екран у зазначеній позиції, використовуючи поточний шрифт. У загальному вигляді вона виглядає так:
BOOL TextOut (
HDC hdc, // дескриптор контексту дисплея
int nXStart, // x-координата початкової позиції
int nYStart, // y- координата початкової позиції
LPCTSTR lpString, // покажчик на відображуваний рядок
int cbString // кількість символів у рядку
) ;
2.10. Видалення вікна, повідомлення WM_DESTROY
Повідомлення WM_DESTROY є ще одним важливим повідомленням. Це повідомлення показує, що Windows знаходиться в процесі ліквідації вікна у відповідь на отриману від користувача команду (користувач викликає надходження цього повідомлення, якщо натисне мишею на піктограмі “Close”, вибере пункт “Close” із системного меню чи натисне комбінацію клавіш Alt+F4).
Головне вікно стандартне реагує на це повідомлення, викликаючи функцію PostQuitMessage (0), що також варто додати до вашої програми.
…
EndPaint (hWnd, &ps) ;
break;
case WM_DESTROY:
PostQuitMessage (0) ;
break;
}
Ця функція ставить повідомлення WM_QUIT у чергу повідомлень додатка. Це змушує функцію WinMain перервати цикл обробки повідомлень і вийти в систему, завершивши роботу додатка.
ПРАКТИЧНА ЧАСТИНА
Знайомство із середовищем програмування Microsoft Visual C++ 6. 0, створення проекту, файлу з вихідним кодом та модуля, що виконується.
Створити найпростіший додаток sample, що виводить одне (головне) вікно. Текст додатка sample зберегти для подальшого його використання як шаблон для інших додатків.
Замінити заголовок вікна на «My second program».
Поміняти іконку створеного додатка.
Використати інший покажчик миші.
Використовуючи функцію DrawText () вивести в робочій області вікна:
у лівому верхньому куті – ім'я, прізвище, по батькові;
у лівому нижньому куті – номер групи;
у центрі назву факультету.
Заборонити мінімізувати/максимізувати вікно.
Вивести вікно без системного меню.
Контрольні питання:
- Яка функція є точкою входу в Windows-програму?
- Які характеристики класу вікон можна задати при його реєстрації? Які поля структури, що описує клас вікна, є найбільш важливими?
- Що таке віконна процедура? Для чого вона призначена? Хто її викликає в процесі роботи додатка?
- Для чого служить цикл обробки повідомлень? Відкіля додаток витягає чергове повідомлення? Яким образом і ким повідомлення створюються?
- Хто звичайно посилає повідомлення (і яке), що перериває цикл обробки повідомлень?
- З яких джерел віконна процедура одержує повідомлення?
- Яке повідомлення приходить вікну, якщо частина його робочої області (чи уся вона) вимагає перемальовування? Що таке недійсна область?
- У яких ситуаціях робоча область може ставати недійсною?
- З виклику якої функції повинна починатися обробка повідомлення WM_PAINT? Викликом якої функції вона повинна закінчуватися? Для чого викликаються ці функції?
- Як звичайно реагує стандартне головне вікно додатка на одержання повідомлення про його видалення? Що при цьому відбувається з додатком?