Система, заснована на повідомленнях, C / C + +, Програмування, статті

Windows можна назвати об’єктно-орієнтованою системою, хоча формально вона
такою не є. Уявіть собі систему у вигляді набору об’єктів, основним
з яких є вікно. У процесі роботи, Windows “спілкується” з кожним
об’єктом за допомогою системних повідомлень. При виникненні певних
подій, Windows повідомляє про це вікна програми, посилаючи йому відповідне
повідомлення. Вікно, після отримання повідомлення, має обробити його і повернути
результат назад в систему.

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

Win32 API


Win32 API (Application Programming Interface – інтерфейс прикладного
програмування) – це набір функцій, що дозволяють програмісту створювати
програми для Windows. Win32 API є основою для кожної Windows-програми.

Програмісти, що пишуть на С + + вже звикли, що точкою входу в програму
є функція main (). Але в системі Windows це не так. Всі Win32-додатки
використовують як точки входу в програму функцію WinMain. Її оголошення
можна знайти в заголовному файлі winbase.h:

int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd
);

Давайте розглянемо всі її аргументи:


Як бачите – все не так складно! Вас, напевно, здивували тільки якісь
незрозумілі типи даних. Не хвилюйтеся – розберемося.

Типи даних в Windows


При першому погляді на вихідний код Windows-програми, початківців
програмістів починають лякати “дивні” типи даних, що використовуються в програмі.
Але це тільки на перший погляд. На самому, справі розібратися в них вам не складе
особливих труднощів. Основні типи даних Win32 API наведено в таблиці 1.

Таблиця 1






































BOOL, BOOLEAN Булев. Має тільки 2 значення: TRUE або FALSE
CHAR 8-бітний символ (ANSI Windows)
WCHAR 16-бітний символ (Unicode)
TCHAR CHAR або WCHAR (якщо використовується Unicode)
USHORT, WORD Ціле беззнаковое 16-бітове число
DWORD, DWORD32, UINT32 Ціле беззнаковое 32-бітове число
DWORD64, UINT64, ULONGLONG Ціле беззнаковое 64-бітове число
FLOAT Число з плаваючою точкою
SHORT Ціле знакова 16-бітове число
INT, INT32, LONG, LONG32 Ціле знакова 32-бітове число
INT64, LONG64, LONGLONG Ціле знакова 64-бітове число
VOID Порожній тип

Структура Windows-програм


Кожна Windows-програма складається як мінімум з двох основних функцій. Це
WinMain і функція вікна.

Давайте напишемо просту програму, що створює порожнє вікно. Для цього в Visual
C + + створіть порожній проект Win32 Application, додайте новий файл (наприклад,
myprog.cpp), і вставте туди наступний код:

/ / Включаємо необхідний заголовний файл для Windows-програм
#include <windows.h>

/ / Оголошення функції вікна (віконної процедури)
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

HINSTANCE hInst; / / Ідентифікатор програми

/ / Покажчик на константну рядок символів – ім’я програми і класу вікна
LPCSTR AppName = "MyProgramm";

/ / Точка входу в програму – функція WinMain
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd; / / Унікальний ідентифікатор вікна (handle)
MSG msg; / / Оголошення структури типу MSG, для роботи з повідомленнями

hInst = hInstance; / / Зберігаємо ідентифікатор програми

/ / Заповнюємо структуру WNDCLASS
WNDCLASS wc;
/ / Ініціалізували виділену для структури пам’ять нулями
ZeroMemory(&wc, sizeof(wc));
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszClassName = AppName;

RegisterClass (& wc); / / Створюємо і реєструємо віконний клас

/ / Створюємо вікно програми
hWnd = CreateWindow(
AppName, / / ​​Ім’я класу вікна
AppName, / / ​​Заголовок вікна
WS_OVERLAPPEDWINDOW, / / ​​Стиль вікна
CW_USEDEFAULT, 0, / / ​​Горизонтальна і вертикальна позиції вікна
300, 300, / / ​​Ширина і висота вікна
NULL, / / ​​хендл батьківського вікна
NULL, / / ​​хендл меню
hInst, / / ​​Ідентифікатор програми
NULL); / / Додаткові дані вікна

ShowWindow (hWnd, SW_SHOW); / / Відображаємо вікно
UpdateWindow (hWnd); / / перемальовували вікно

/ / Стандартний цикл обробки повідомлень
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;
}

/ / Віконна процедура
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}

return 0;
}


Тепер давайте розглянемо наведений код детальніше.

На жаль, привести тут опису всіх типів даних, структур, функцій і
т.д., що використовуються в Win32 API, не представляється можливим, тому раджу
звернутися до офіційного джерела, де можна знайти всю необхідну інформацію
про програмування під Windows – Microsoft Developer Network
(msdn.microsoft.com).

Для того щоб створити вікно, спочатку необхідно зареєструвати в системі
новий віконний клас. Для цього потрібно заповнити структуру WNDCLASS і передати
покажчик на область пам’яті, що містить цю стуктуру, функції RegisterClass ().
Ця функція створює і реєструє новий віконний клас, використовуючи значення
елементів переданої їй структури для визначення характеристик класу. Нижче
приведені описи всіх елементів структури WNDCLASS.


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

Після реєстрації класу вікна можна приступати до створення самого вікна. Для
цього використовується функція CreateWindow (), яка повертає хендл створюваного
вікна.

Створивши вікно, нам необхідно відобразити його на екрані. Цим займається функція
ShowWindow (), яка приймає в якості аргументів ідентифікатор вікна, і
прапор, який вказує на спосіб відображення вікна (в даному випадку SW_SHOW,
визначає, що вікно необхідно показати на екрані). Потім, за допомогою функції
UpdateWindow () ми посилаємо нашу вікна повідомлення WM_PAINT, яке вказує на
необхідність перемалювати клієнтську область вікна.

Далі слід цикл обробки повідомлень. Він складається з керуючої структури
while, яка при кожному проході циклу отримує чергове повідомлення з черги,
за допомогою функції GetMessage (), потім переводить всі повідомлення від віртуальних
клавіш в символьні повідомлення за допомогою функції TranslateMessage () (про
призначення даної операції ми поговоримо пізніше), і після цього відсилає
отримане повідомлення на обробку віконної процедури, використовуючи функцію
DispatchMessage().

Функція GetMessage () повертає ненульове значення, тому цикл не
завершується до моменту завершення програми. При завершенні програми вікна
надсилається повідомлення WM_QUIT, яке є єдиним повідомленням, при
отриманні якого функція GetMessage () повертає нуль, і цикл обробки
повідомлень завершується, а код виходу з програми, що зберігається в елементі wParam
структури MSG, повертається функцією WinMain.

І нарешті, пора розібратися яким же чином віконна процедура обробляє
передані їй повідомлення. В функції вікна є чотири аргументи:


У Windows існує більше тисячі стандартних повідомлень. Звичайно ж,
програміст не повинен опрацьовувати їх все. Для цього існує функція
DefWindowProc (), яка обробляє передане їй повідомлення за замовчуванням.
Таким чином, ви повинні обробляти тільки ті повідомлення, обробка по
замовчуванням яких вас не влаштовує. Також, функція DefWindowProc () не
обробляє повідомлення WM_DESTROY, тому ви повинні передбачити його обробку
самостійно. У наведеному прикладі, при отриманні вікном повідомлення WM_DESTROY,
ми, за допомогою функції PostQuitMessage (), ставимо в чергу повідомлення WM_QUIT,
щоб завершити роботу програми.

Зауважте, яким чином повідомлення обробляються за замовчуванням. У структурі
switch віконної процедури передбачена мітка default, яка пересилає все
необроблювані нашою програмою повідомлення функції DefWindowProc () і повертає
результат цієї функції. А якщо повідомлення обробляється нашою програмою, тоді
повертається нуль.

Ось воно, чудо


Тепер, розібравшись з кодом програми, відкомпілюйте створений проект і
запустіть додаток. Ви побачите порожнє вікно, з яким вже можна виконувати
стандартні дії – переміщати, змінювати розміри, згортати / розгортати,
і навіть закрити! : Все це досягається одним єдиним стилем вікна
WS_OVERLAPPEDWINDOW, визначеним при створенні вікна функцією CreateWindow ().

Примітка: у елементі style, структури WNDCLASS, визначається загальний стиль
для всіх вікон даного класу. Слід зауважити, що стиль класу це не теж
саме що і стиль вікна, зазначений у виклику функції CreateWindow (). Той стиль,
який встановлюється за допомогою функції CreateWindow (), є
індивідуальним стилем вікна, а не загальним стилем, визначеним у класі.

Ресурси програми


Практично в кожній Windows-програмі можна побачити різні елементи
управління, меню, і інші ресурси програми. Створити в вікні який або елемент
управління, наприклад, кнопку, можна двома способами. Перший, це створити нове
вікно використовуючи функцію CreateWindow () з визначеним в системі віконним
класом “button”. Другий спосіб, це використовувати файли ресурсів, в яких
міститься опису всіх ресурсів програми, будь то меню, елементи управління,
ікони і навіть діалогові вікна. Кожен елемент управління має свій унікальний
ідентифікатор (хендл) визначається програмістом. Коли користувач здійснює
будь-які дії над елементом управління, повідомлення про це надходять вікна,
і після цього виконуються відповідні дії. Наприклад, при натисканні на
кнопку вікно отримує повідомлення WM_COMMAND, яке в параметрі wParam містить
ідентифікатор кнопки.

Детальніше про ресурси програми та роботі з повідомленнями ми поговоримо трохи
пізніше.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*