Повідомлення

Величезну роль в організації роботи прикладних програм і самої системи Windows грають повідомлення (messages). На обробці повідомлень, що посилаються системою, заснована вся робота з графічним інтерфейсом програм. Процеси також можуть обмінюватися повідомленнями з метою синхронізації дій та обміну даними.

Повідомлення являє собою структуру даних, що містить тип повідомлення, адресат повідомлення (конкретне вікно, всі вікна або нитка процесу), час посилки повідомлення, координати курсора (для повідомлень від миші), а також два параметри, зміст яких залежить від типу повідомлення.

Система посилає повідомлення придатків із найрізноманітніших приводів: при натисканні клавіш і кнопок миші, створенні та закритті вікон, зміни розмірів і положення вікна, виборі об'єкта в якомусь списку, виборі команди в меню і т.п. Часто одне і те ж дія користувача (наприклад, клацання лівою кнопкою миші на пункті меню) викликає посилку декількох різних повідомлень.

Велика частина посилаються повідомлень може оброблятися самою системою за замовчуванням. Прикладна програма може взяти обробку деяких повідомлень на себе, щоб забезпечити необхідну логікою роботи реакцію на певні події (наприклад, при зміні розмірів вікна перерозподілити його площа між окремими панелями; при спробі закрити вікно запросити підтвердження і т.п.). Програма повинна також обробляти повідомлення про посиланих їй командах (при використанні меню, кнопок і т.п.) і повідомлення про необхідність перемалювати вміст вікна.

При створенні будь-якого нового вікна Windows вимагає задати віконну функцію, яка повинна обробляти повідомлення, спрямовані цьому вікну. Нитка, що отримала повідомлення, або викликає віконну функцію одного зі своїх вікон (для вибору вікна використовується функція DispatchMessage), або обробляє повідомлення сама (якщо воно не пов'язане з конкретним вікном).

Є два принципово різних способу посилки повідомлення. Посилаючи повідомлення синхронно, відправник чекає закінчення його обробки, перш ніж продовжити роботу. Асинхронна посилка нагадує опускання листи в поштову скриньку, вона не робить впливу на подальшу роботу відправника. Прикладна програма може посилати будь-які повідомлення синхронним або асинхронним способом, як вважатиме за потрібне розробник. Для цього можуть використовуватися, відповідно, функція SendMessage (синхронна посилка) або функція PostMessage (асинхронна посилка).

Нитка процесу отримує повідомлення, адресовані належним їй вікнам або самої нитки. Для вибірки повідомлень з черги використовується функція GetMessage. У разі відсутності повідомлень нитка блокується до їх надходження. При бажанні програміст може використовувати функцію PeekMessage, яка перевіряє наявність повідомлення, не блокуючи зухвалу нитку.

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

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

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