Previous slide Next slide Toggle fullscreen Toggle overview view Open presenter view
Системное программирование
Тема 5. Механизм сообщений в операционных системах
Системное программирование
План лекции
Учебные вопросы
Консольная модель vs событийный оконный GUI
Класс окна (WNDCLASSEXW) и дескриптор HWND
Анатомия структуры MSG, WPARAM и LPARAM
Поток RIT, очереди потока и главный цикл выборки
Синхронный SendMessage vs асинхронный PostMessage
Системный ввод мыши и клавиатуры (WM_CHAR)
Цели занятия
Освоить концепцию инверсии управления (IoC)
Изучить регистрацию и параметры оконного класса
Разобрать внутреннее устройство структуры сообщения MSG
Понять работу очередей потока и синтетических флагов
Освоить построение циклов с GetMessage и PeekMessage
Изучить механизмы хит-тестинга и трансляции символов
Механизм сообщений в операционных системах
Системное программирование
Консольная парадигма против событийного GUI
Консольная модель (Линейная)
Программа жестко управляет потоком выполнения
Блокирующий ввод: scanf усыпляет поток до нажатия Enter
Невозможно параллельно реагировать на действия пользователя
Монопольное исполнение без интерактивности
Событийная модель (GUI)
Инверсия управления (Inversion of Control):
ОС управляет главным потоком событий
Программа регистрирует функции обратного вызова
Цикл сообщений: непрерывный опрос очереди
Отзывчивый интерфейс и параллельная обработка окон
Механизм сообщений в операционных системах
Системное программирование
Парадигмы программирования: Консоль vs Событийный GUI
Механизм сообщений в операционных системах
Системное программирование
Архитектура оконного класса: WNDCLASSEXW
Понятие класса окна
Окно не может быть создано без предварительно зарегистрированного класса
Задает общие атрибуты окон данного типа
Регистрируется вызовом RegisterClassExW
Ключевые поля WNDCLASSEXW
lpfnWndProc: указатель на оконную процедуру (Callback)
style: стили перерисовки (CS_HREDRAW | CS_VREDRAW)
hInstance: дескриптор загруженного модуля
hCursor, hIcon: системный курсор и пиктограмма
lpszClassName: уникальное имя класса в системе
Механизм сообщений в операционных системах
Системное программирование
Архитектура оконного класса и создание окна (HWND)
Механизм сообщений в операционных системах
Системное программирование
Предопределенные оконные классы
Стандартные элементы управления
Все элементы управления Windows — это полноценные окна HWND
Создаются вызовом CreateWindowExW со стилями WS_CHILD | WS_VISIBLE
Имеют встроенную стандартную процедуру окна внутри USER32.DLL
Базовые предопределенные классы
L"BUTTON": командные кнопки, чекбоксы, радиокнопки
L"EDIT": однострочные и многострочные поля ввода текста
L"STATIC": текстовые надписи, рамки и изображения
L"LISTBOX": списки элементов с выбором
L"COMBOBOX": комбинированные выпадающие списки
Механизм сообщений в операционных системах
Системное программирование
Дополнительные данные окна: GetWindowLongPtrW
Проблема связывания с C++
WndProc в Си обязана быть статической функцией
Не может напрямую обращаться к нестатическим полям класса C++
Требуется безопасный механизм доступа к указателю this
Системное решение UserData
SetWindowLongPtrW(hwnd, GWLP_USERDATA,
(LONG_PTR)pThis);
MyWindow *pWnd = (MyWindow*)
GetWindowLongPtrW(hwnd, GWLP_USERDATA);
if (pWnd) {
return pWnd->HandleMessage(uMsg, wParam, lParam);
}
Механизм сообщений в операционных системах
Системное программирование
Анатомия оконного сообщения: структура MSG
Поля структуры MSG
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
Назначение WPARAM и LPARAM
WM_SIZE: wParam — тип изменения; lParam хранит width (LOWORD) и height (HIWORD)
WM_LBUTTONDOWN: wParam — флаги кнопок (MK_CONTROL); lParam хранит X X X и Y Y Y
WM_COMMAND: LOWORD(wParam) — ID элемента, HIWORD(wParam) — код события
Механизм сообщений в операционных системах
Системное программирование
Классификация и анатомия оконных сообщений
Механизм сообщений в операционных системах
Системное программирование
Системный поток реального времени в ядре win32k.sys
Считывает аппаратные прерывания клавиатуры и мыши
Выполняет хит-тестинг: определяет окно под курсором
Маршрутизирует ввод в аппаратную очередь целевого потока
Структура очереди потока
Очередь отложенных сообщений (Posted Queue): FIFO буфер для сообщений PostMessage
Очередь аппаратного ввода: события мыши и клавиатуры
Синтетические флаги:
WM_PAINT — взводится при инвалидации области
WM_TIMER — взводится по таймеру
Обрабатываются только при пустых очередях 1 и 2!
Механизм сообщений в операционных системах
Системное программирование
Архитектура очередей и главный цикл сообщений
Механизм сообщений в операционных системах
Системное программирование
Синхронная и асинхронная отправка сообщений
Сравнение SendMessage и PostMessage
Свойство
PostMessageW()
SendMessageW()
Тип
Асинхронный
Синхронный
Очередь
В хвост очереди
В обход очереди
Блокировка
Немедленно (0 мс)
Блокирует поток
Результат
BOOL (успех)
LRESULT из WndProc
Потоки
Безопасен
Опасность дедлока
Практическое применение
PostMessage: безопасное уведомление GUI из фоновых рабочих потоков
SendMessage: мгновенный опрос дочерних элементов или получение статуса контролов
Опасность: вызов SendMessage между двумя GUI-потоками может вызвать взаимную блокировку!
Механизм сообщений в операционных системах
Системное программирование
Главный цикл выборки сообщений
Блокирующий цикл: GetMessage
MSG msg;
while (GetMessageW(&msg, NULL , 0 , 0 ) > 0 ) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return (int )msg.wParam;
Поток спит в ядре, если сообщений нет (0% нагрузки ЦПУ)
Неблокирующий цикл: PeekMessage
while (true ) {
if (PeekMessageW(&msg, 0 , 0 , 0 , PM_REMOVE)) {
if (msg.message == WM_QUIT) break ;
TranslateMessage(&msg);
DispatchMessageW(&msg);
} else {
RenderNextFrame();
}
}
Механизм сообщений в операционных системах
Системное программирование
Оконная процедура и функция DefWindowProc
Структура функции WndProc
LRESULT CALLBACK MainWindowProc (
HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
return 0 ;
}
case WM_DESTROY:
PostQuitMessage(0 );
return 0 ;
default :
return DefWindowProcW(hwnd,
uMsg, wParam, lParam);
}
}
Важность DefWindowProcW
Выполняет базовую системную обработку сотен служебных сообщений Windows
Отвечает за анимацию рамки, системное меню, отрисовку неклиентской зоны
Пропуск DefWindowProcW приводит к зависанию окна !
Механизм сообщений в операционных системах
Системное программирование
Обработка сообщений мыши в системном API
Клиентские сообщения мыши
Генерируются при нахождении курсора над рабочей областью окна
WM_MOUSEMOVE: перемещение мыши
WM_LBUTTONDOWN / WM_LBUTTONUP: нажатие и отпускание ЛКМ
WM_RBUTTONDOWN: контекстные действия (ПКМ)
WM_MOUSEWHEEL: дельта вращения колеса мыши
Извлечение координат курсора
case WM_LBUTTONDOWN: {
int x = GET_X_LPARAM(lParam);
int y = GET_Y_LPARAM(lParam);
UINT flags = (UINT)wParam;
return 0 ;
}
Механизм сообщений в операционных системах
Системное программирование
Захват мыши и неклиентские события
Механизм захвата мыши (SetCapture)
По умолчанию сообщения мыши привязаны к окну под курсором
При перетаскивании (Drag-and-Drop) курсор может покинуть границы окна
SetCapture(hwnd): направляет все сообщения мыши окну, даже вне экрана
ReleaseCapture(): обязательно вызывается при отпускании кнопки
Хит-тестинг: WM_NCHITTEST
Опрашивает окно: «В какой зоне находится курсор?»
HTCLIENT: рабочая область
HTCAPTION: заголовок (перетаскивание)
HTCLOSE: кнопка закрытия [X]
Возврат HTCAPTION в теле клиентской зоны позволяет перетаскивать окно за любое место!
Механизм сообщений в операционных системах
Системное программирование
Обработка клавиатурного ввода
Уровни обработки ввода
Аппаратные скан-коды (Scan Codes):
Номера контактов микроконтроллера клавиатуры
Зависят от физической модели устройства
Виртуальные коды (Virtual-Key Codes, VK_*):
Аппаратно-независимые системные константы
VK_LEFT, VK_RIGHT, VK_F1, VK_RETURN, VK_SPACE
Системные сообщения клавиш
WM_KEYDOWN: физическое нажатие клавиши; код клавиши передается в wParam
WM_KEYUP: отпускание клавиши
WM_SYSKEYDOWN: нажатия системных комбинаций (с клавишей Alt)
Механизм сообщений в операционных системах
Системное программирование
Фокус ввода и текстовый ввод: WM_CHAR
Генерация символов: TranslateMessage
WM_KEYDOWN не содержит символа с учетом раскладки и регистра
Функция TranslateMessage(&msg) сопоставляет скан-код, раскладку и Shift/Caps
Синтезирует сообщение WM_CHAR и ставит его в очередь потока
В wParam передается готовый код UTF-16 (wchar_t)
Фокус клавиатурного ввода
Сообщения клавиатуры направляются только окну с фокусом
WM_SETFOCUS: окно получило фокус ввода
WM_KILLFOCUS: окно потеряло фокус (переключение на другой элемент)
Программная установка: SetFocus(hwnd)
Механизм сообщений в операционных системах
Системное программирование
Резюме лекции
Классы и очереди
Архитектура GUI построена на инверсии управления (IoC)
WNDCLASSEXW связывает класс окна с оконной процедурой (lpfnWndProc)
Поток RIT транслирует аппаратные прерывания в очереди потоков
WM_PAINT и WM_TIMER — синтетические флаги низкого приоритета
Сообщения и ввод
PostMessage ставит сообщение в очередь; SendMessage вызывает WndProc напрямую
GetMessage обеспечивает энергоэффективный сон; PeekMessage — неблокирующий опрос
Пропуск DefWindowProcW приводит к фатальному зависанию окна
TranslateMessage преобразует скан-коды в символы Юникода WM_CHAR
Механизм сообщений в операционных системах
Системное программирование
Вопросы для самопроверки
Вопросы 1–5
В чем заключается фундаментальная разница между консольной и событийно-ориентированной парадигмой?
Какую роль играет структура WNDCLASSEXW и почему окно нельзя создать без класса?
Каким образом SetWindowLongPtrW связывает дескриптор HWND с объектом класса C++?
Какие поля входят в структуру MSG и какую информацию несут WPARAM и LPARAM?
В чем разница между диапазонами WM_USER, WM_APP и строковыми сообщениями?
Вопросы 6–10
За какие задачи отвечает системный поток Raw Input Thread (RIT) в ядре Windows?
Почему сообщение WM_PAINT называется синтетическим и когда оно извлекается?
В чем заключается принципиальная разница в поведении SendMessage и PostMessage?
Что произойдет с окном, если в WndProc не передавать сообщения в DefWindowProc?
Каким образом функция TranslateMessage формирует символьные сообщения WM_CHAR?
Механизм сообщений в операционных системах
Системное программирование
Литература и рекомендуемые ресурсы
Учебная литература
Устройство и функционирование OC Windows — Коньков К. А. М.: Бином, 2008. 208 с.
Современные операционные системы (4-е изд.) — Таненбаум Э., Бос Х. СПб.: Питер, 2021. 1119 с.
Операционные системы (2-е изд.) — Гордеев А. В. СПб.: Питер, 2009. 415 с.
Программирование для Windows 95 (в 2-х томах) — Петцольд Ч. СПб.: BHV, 1997.
Документация и справочники
Механизм сообщений в операционных системах
Лекция №5.
Цель: сформировать детальное понимание событийно-ориентированной модели операционных систем, архитектуры оконных классов, механизмов очередей сообщений потока, работы системного потока RIT, синхронной и асинхронной диспетчеризации, а также обработки событий мыши и клавиатуры на уровне системного API.
Связь с предыдущими темами: опирается на Тему 2 (процессы и потоки) и Тему 3 (объекты ядра и примитивы взаимодействия).
Связь с практической работой: теоретическая база для лабораторной работы №4 "Обработка сообщений. Очереди сообщений".
План ориентирован на освоение низкоуровневой механики оконной подсистемы USER32 и WIN32K.
Подчеркнуть: переход от активного опроса к функциям обратного вызова (Голливудский принцип).
Слева — линейная блокирующая модель консоли, справа — цикл выборки и оконная процедура GUI.
Оконный класс связывает строковое имя типа окна с функцией-обработчиком lpfnWndProc.
Схема регистрации класса, фабрики окон CreateWindowExW и связывания дескриптора HWND.
Предопределенные классы предоставляют готовые оконные процедуры стандартных элементов Windows.
SetWindowLongPtrW сохраняет указатель на C++ объект прямо в структуре WND в памяти ядра.
Параметры wParam и lParam полиморфны и интерпретируются в зависимости от кода сообщения message.
Иерархия: системные сообщения, пользовательские диапазоны WM_USER, WM_APP и строковые IPC.
Синтетические сообщения WM_PAINT имеют низший приоритет и не перегружают очередь потока.
Схема: аппаратный ввод через RIT, очереди потока, цикл выборки и прямой обходной вызов SendMessage.
SendMessage выполняет синхронный RPC-вызов оконной процедуры; опасен взаимными блокировками.
GetMessage оптимален для стандартного GUI, PeekMessage — для игр и рендеринга реального времени.
DefWindowProcW — системная реализация по умолчанию, обеспечивающая штатное поведение окна.
Координаты мыши упакованы в 32 бита LPARAM и извлекаются макросами GET_X_LPARAM / GET_Y_LPARAM.
SetCapture гарантирует получение WM_LBUTTONUP при отпускании за пределами окна.
WM_KEYDOWN фиксирует факт нажатия аппаратной кнопки, но еще не знает печатного символа.
TranslateMessage превращает аппаратно-зависимый скан-код в готовый символ Юникода WM_CHAR.
Подвести итог: механизм сообщений — кровеносная система графического интерфейса Windows.
Опросить слушателей по различиям Send/PostMessage, роли RIT и структуре MSG.
Завершить лекцию, объявить тему следующего занятия (Тема 6. Графический интерфейс пользователя).