
- •Int winapi WinMain(hinstance hInstance, hinstance hPrevInstance,
- •Int winapi WinMain(hinstance hInstance, hinstance hPrevInstance,
- •Step 1: Реєстрація даних віконного класу
- •If(!RegisterClassEx(&wc))
- •Step 2: Створення вікна за занесеними даними
- •Step 3: Цикл чекання повідомлень
- •Step 4: Віконна процедура
Step 3: Цикл чекання повідомлень
Те, що ми викладаємо нижче насправді є двигуном а\всієї програми. Це – цикл чекання і обробки подій
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
GetMessage() читає інформацію із черги повідомлень ОС (рух мишкою, натискання клавіш кмишки чи клавіатури , тощо). За одне звернення до gets a message ми отримуємо інформацію про одну (чергову) подію.
TranslateMessage() виділяє додаткову інформацію із події WM_CHAR (у випадку натискання клавіш клавіатури) , вирізняючи подію втоплювання від події відпускання клавіш (WM_KEYUP і WM_KEYDOWN)
DispatchMessage() повертає повідомлення тому вікну, від якого воно отримало повідомлення ( частіше за все, вікну ОС)
Step 4: Віконна процедура
Обробкою подій, які розпізнаються в циклі читання черги подій, обробляються віконною процедурою із наступним стандартним оформленням..
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
В залежності від подій , користувач тут може описати їх обслуговування. За умовчуванням віконна процедура обслуговує тільки такі повідомлення:
WM_CLOSE-
поступає у випадку натисканні користувачем
кнопки
(справа
вверху)
Викликом функції DestroyWindow() система посилає повідомлення WM_DESTROY вікну, яке має бути ліквідованим (вікно з хендлом hwnd та всі його вікна-потомки). Для повного завершення прикладної програми потрібно послати в ОС повідомлення WM_QUIT, яке і здійснюється функцією PostQuitMessage(0)
Все, що не передбачено вами в циклі чекання, обробляється за умовчуванням системною функцією DefWindowProc.
Що таке цикл чекання повідомлень
Що таке повідомлення ( a Message)?
Повідомлення – це іменоване значення цілого числа. Якщо ви заглянете до файлу включення windows.h, то там визнайдете таке
#define WM_INITDIALOG 0x0110
#define WM_COMMAND 0x0111
#define WM_LBUTTONDOWN 0x0201
і т.д
І якщо ви хочете, щоб вікно щось виконало, то ви посилаєте йому повідомлення. Звичайно ви повинні передбачити обробку цього повідомлення так як у попередньому прикладі.
Загалом, всяке віконне повідомлення може мати два іменовані (системні) параметри: wParam та lParam. Як правило, wParam має 16 bit, а lParam - 32 bit. Правда, у Win32 вони обидва 32 бітні і не всяке повідомлення їх використовує. Наприклад, повідомлення WM_CLOSE не використовує їх взагалі., в той час як повідомлення WM_COMMAND,яке формується при виборі пункта меню, використовує обидва числа.
Слово wParam містить два 16 розрядних значення HIWORD(wParam) та LOWORD(wParam). У випадку WM_COMMAND iперше містить ознаку меню (галочку вибору), а друге – номер пункта меню. Параметр lParam містить HWND (window handle) того об’єкту керування, від якого поступило повідомлення.
Для посилки повідомлення програмно користуйтесь системними функціями PostMessage() або SendMessage().
PostMessage() поміщає повідомлення в чергу і продовжує подальше виконання програми без затримки. SendMessage()посилає повідомлення до віконної процедури іншого вікна поза чергою і чекає від нього відповіді.
Що таке черга повдомлень
Уявімо собі, що ваша програма оборобляє повідомлення WM_PAINT ( малює щось у вікні). А в цей час ви натиснули якусь клавішу на клавіатурі. Яка може бути подальша поведінка вашої програми?
можна перервати малювання і обслужити натискання клавіші;
можна продоажити малювання, але при цьому втратити подію натискання.
Система поступає інакше. Вона занесе повідомлення до спеціального буфера(черги) і продовжить малювання, а після закінчення малювання прочитає чергове повідомлення і обслужить його.
Шо таке цикл чекання повідомлень
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
Цикл викликає функцію GetMessage(), яка переглядає чергу повідомлень і вибирає чергове повідомлення заносячи його до структури Msg.
Якщо повідомлення є (функція повертає додатнє значення) тоді здійснюється його обробка.
Значення із Msg заноситься до функції TranslateMessage(&Msg),яка із події натискання на клавішу клавіатури (якщо це була така подія) виділяє події утоплювання і відпускання клавіші.
Функція DispatchMessage()приймає повідомлення, визначає від якого вікна воно надійшло і та викликає процедуру, відповідальну за обробку цього повідомлення. (вміст віконної процедури і як його може змінювати програміст ми вже розглядали.
Схема роботи циклу чекання зображена на наступному малюнку