Програміст, вперше спробувавши створити Windows-програму,
виявить, що цей процес суттєво відрізняється від процесу створення програм
для середовища DOS.
Специфіка організації багатозадачності накладає суттєвий
відбиток на технологію програмування задач, що повинні виконуватись у середовищі
Windows.
Принципова відмінність створення програм для Windows
полягає в тому, що кожна програма тепер повинна розроблятися на основі
передачі та обробки повідомлень.
Рисунок 2 - Схема обробки повідомлень
У зв’язку з керуванням та організацією зв’язку між
програмами за допомогою повідомлень у кожній програмі (для кожного вікна)
повинні бути явно виділені такі обов’язкові елементи, як цикл введення
повідомлень та процедура їх обробки. Тобто кожна програма повинна в циклі
аналізувати чергу повідомлень, обробити (процедурою вікна) повідомлення,
що призначені саме їй, і, якщо програма не закінчила своєї роботи, повернутися
до читання наступного повідомлення, в протилежному випадку - передати керування
Windows. Процедура обробки повідомлень (або процедура вікна, WinProc) і
є, власне, ядром кожної програми для Windows. Така організація роботи програми
схематично проілюстрована на рис. 2.
Для полегшення складання і читання програм програмісти
дотримуються такого принципу: імена змінних повинні містити префікс, який
описує тип даних змінної. Наведемо декілька таких префіксів:
а: масив ( array );
сh: символ ( char );
by: байт ( byte );
i: ціле ( int );
fn: функція ( function );
w: слово ( word );
p: покажчик ( pointer );
l: довге ціле ( long );
dw: подвійне слово ( dword );
s: рядок ( string );
Константи:
wm_XXX: повідомлення(windows message);
cs_XXX: стиль класу ( class style );
id_XXX: ідентифікатор елемента.
Розглянемо дві прості програми: перша використовує функції
Windows API, а друга - об'єктно - орієнтовану бібліотеку ObjectWindows.
program WinMin;
{ Наступні модулі містять опис основних типів та
функцій, що використовуються в Windows’95 }
uses WinTypes, WinProcs;
const
AppName = 'WinMin';
{ Віконна функція. Розпізнає повідомлення і виконує
відповідні дії. У нашому випадку функція опрацьовує тільки одне повідомлення
wm_Destroy. У відповідь на це повідомлення викликом процедури PostQuitMessage
наша програма поміщує в чергу повідомлення wm_Quit. Коли функція GetMessage
отримує це повідомлення, цикл обробки повідомлень припиняє свою роботу
і програма завершується }
function WindowProc(Window:HWnd; Message, WParam:word;
LParam:longint):longint;export;
begin
WindowProc:=0;
case Message of
{Обробка повідомлень}
wm_Destroy: {Розпізнали повідомлення}
begin { wm_Destroy }
PostQuitMessage(0); { Ставимо в чергу}
Exit {повідомлення про закриття}
end;
end;
{ Якщо наша віконна функція не опрацювала повідомлення,
то викликаємо стандартну віконну функцію, яка обробляє всі повідомлення,
що не оброблені заміщеною }
WindowProc:=DefWindowProc(Window, Message, WParam,
LParam)
end;
{ Ініціюючі дії процедури WinMain полягають в створенні
і регістрації класу вікна, створенні і відображенні вікна на екрані і активації
циклу обробки повідомлень }
procedure WinMain;
var Window:HWnd; { Покажчик на вікно}
Message:TMsg; { Повідомлення}
WindowClass:TWndClass; { Клас вікна }
begin
if HPrevInst = 0 then {Тільки для першого екземпляра
програми}
begin {Опис атрибутів WindowClass.Style := класу}
cs_HRedraw or cs_VRedraw; {Стиль вікна}
WindowClass.lpfnWndProc:= { Покажчик на }
@WindowProc; { віконну функцію }
WindowClass.cbClsExtra:=0; { Використовується
WindowClass.cbWndExtra:=0; для виділення
пам'яті }
WindowClass.HInstance:= { Ресурси }
HInstance;
{ Покажчик на іконку }
WindowClass.hIcon:=LoadIcon(0, idi_Application);
{ Покажчик на курсор } WindowClass.hCursor:=LoadCursor(0,idc_Arrow);
{ Заповнення фону вікна } WindowClass.hbrBackground:=GetStockObject(white_Brush);
WindowClass.lpszMenuName:=''; { Меню}
{ Ім'я програми}
WindowClass.lpszClassName:=AppName;
{Регістрація класу}
if not RegisterClass(WindowClass) then Halt(255)
end;
{Створення вікна}
Window:=CreateWindow(AppName,'Win_Min',ws_OverlappedWindow,
cw_UseDefault,cw_UseDefault,cw_UseDefault,
cw_UseDefault,0,0,hInstance,nil);
ShowWindow(Window,CmdShow);
UpdateWindow(Window);
{Цикл обробки повідомлень}
while GetMessage(Message,0,0,0) do begin
TranslateMessage(message);
DispatchMessage(Message)
end;
Halt(Message.WParam);
end;
begin
WinMain
end.
Під час виконання даної програми на екрані з'явиться
вікно, яке можна переміщувати, змінювати його розмір і, нарешті, закрити.
Розглянемо дії, які виконують частини програми.
Вікно завжди створюється на основі класу. Спочатку
відбувається заповнення властивостей класу, а потім - реєстрація. Клас
вікна наведений в структурі TWndClass.
При створенні конкретного вікна, використовуючи функцію
CreateWindow, можна зазначити більш детальні характеристики вікна.
Після відображення вікна керування передається циклу
обробки повідомлень.
У цьому циклі повідомлення добуваються з черги. Для
всіх повідомлень, крім wm_Quit ( закінчення роботи програми ), функція
GetMessage повертає не нульове значення і цикл продовжується.
Процедура TranslateMessage передає повідомлення ядру
Windows, яке викликає процедуру WinProc даного класу вікна.
Віконна функція розпізнає повідомлення і виконує
відповідні дії. В нашому випадку функція опрацьовує тільки одне повідомлення
wm_Destroy. У відповідь на це повідомлення, викликом процедури PostQuitMessage
наша програма поміщує в чергу повідомлення wm_Quit. Коли функція GetMessage
отримує це повідомлення, цикл обробки повідомлень припиняє свою роботу
і програма завершується.
Як ви вже зрозуміли, процес створення навіть найпростішої
програми для Windows є достатньо трудомісткий. Одним із засобів спростити
програмування є використання об’єктно-орієнтованої бібліотеки Object Windows
(OWL), яка бере на себе всю рутинну роботу по початковому створенню програми.
Бібліотека повністю об’єктно-орієнтована.
Кожна програма, створена за допомогою OWL, базується
на нащадку об’єкта TApplication.
Конструктор Init виконує
ініціалізацію об’єкта з віртуальними методами, створює і відображає головне
вікно програми і підключає віконну функцію.
Деструктор Done виконує необхідні процедури
для закінчення роботи програми і деініціалізації об’єкта.