Прямой Win32 API и окна нестандартной формы
- title
- Прямой Win32 API и окна нестандартной формы
- type
- summary
- summary
- Как Win32 позволяет создавать непрямоугольные окна и почему эта эпоха десктопных интерфейсов почти исчезла
- tags
- win32, gui, nostalgia
- created
- 2026-04-15
- updated
- 2026-04-15
- lang
- ru
- translation_of
- win32-weird-shaped-windows
- source_updated
- 2026-04-15
- translated
- 2026-09-01
- translator
- lllm/antigravity/gemini-3.7-flash-medium
Иван Рогоз сокрушается о состоянии современных приложений для Windows - раздутом софте на Electron, где блокнот занимает 50MB - и показывает, что Win32 всё ещё позволяет создавать программы с ощутимым физическим присутствием. В статье разбираются три способа создания непрямоугольных окон с рабочим кодом.
Модель на основе сообщений
В Win32 нет цикла обновления кадра. Вместо него вы получаете сообщения:
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Windows отправляет события (WM_CREATE, WM_PAINT, WM_SIZE, WM_DESTROY), а оконная процедура решает, что они значат. Вы выстраиваете поведение шаг за шагом, сообщение за сообщением. Как только вы это понимаете, окна странной формы перестают казаться чем-то загадочным.
Способ 1: регионы окон
Обычное окно прямоугольное, но в Windows есть объекты регионов (HRGN). Привяжите такой регион через SetWindowRgn, и только эта область будет считаться настоящим окном - как визуально, так и интерактивно.
region = CreateEllipticRgn(0, 0, rc.right, rc.bottom);
SetWindowRgn(hwnd, region, TRUE);
Этого достаточно для овального окна. Не фальшивого овала, нарисованного внутри прямоугольника, а настоящего овального HWND.
Подвох в том, что как только вы убираете заголовок, система перестаёт перетаскивать окно за вас. Поэтому на WM_LBUTTONDOWN вы имитируете перетаскивание за заголовок, отправляя WM_NCLBUTTONDOWN с HTCAPTION. Задать форму просто; настоящая работа начинается там, где нужно заново реализовать то, что обычная рамка делала бесплатно.
Способ 2: регионы на основе растровых изображений
Вместо математических фигур регион можно получить из данных растрового изображения. Загружаете картинку, сканируете пиксели строка за строкой, объединяете непрозрачные отрезки в прямоугольники и собираете из них итоговый регион.
#define TRANSPARENT_COLOR RGB(255, 0, 255)
Пурпурный цвет означает пустоту. Всё остальное становится частью окна. Растровое изображение выполняет две задачи: именно его вы рисуете в WM_PAINT, и оно же задаёт форму самого окна.
Так работали старые приложения со скинами. Если картинка изображала собаку, космический корабль или стереосистему, окно могло принять в точности эту форму. Рамка переставала быть законом природы и становилась обычным ресурсом.
Способ 3: layered windows
У регионов из растра жёсткие края: пиксель либо входит в окно, либо нет. Для мягких краёв, полупрозрачности или анимации используются layered windows.
Создаёте всплывающее окно со стилем WS_EX_LAYERED и передаёте 32-битное изображение с альфа-каналом через UpdateLayeredWindow. В статье показан анимированный маскот для рабочего стола: используется спрайтшит, кадры переключаются по таймеру, а отрисовка идёт через GDI+. Вы больше не утверждаете "моё окно - эллипс", вы говорите "моё окно - это то, что прямо сейчас представляют собой эти пиксели".
Попиксельный альфа-канал, аккуратные края, честная прозрачность и возможность менять форму в каждом кадре.
Почему это исчезло
Нестандартные окна означают, что всё приходится делать вручную: перетаскивание, изменение размера, логику закрытия, hit testing, обработку клавиатуры, корректную перерисовку, поддержку DPI. Сделать прототип просто, довести до ума - дорого.
Культура десктопного UI изменилась. В эпоху Windows XP безумные скины были в почёте: медиаплееры в виде реальной аппаратуры, маскоты на рабочем столе, панели утилит в форме пультов управления инопланетного корабля. Затем странные окна стали ассоциироваться с дешёвыми трюками, adware и раздутыми утилитами. Нормой стало правило: "работай надёжно и не мешай".
В большинстве случаев обычное прямоугольное окно - правильный выбор. Но это именно выбор, а не закон. Win32 не пытается отговорить вас от подобных экспериментов. Он даёт вам сообщения, дескрипторы, API для отрисовки и достаточно свободы, чтобы собрать что-то интересное.
Связь со стабильностью Win32
Эта статья дополняет win32-stable-abi. Стабильность Win32 заключается не только в бинарной совместимости - дело в самой модели программирования, которая по-прежнему работает в точности так, как была задокументирована десятилетия назад. Те же API регионов из Windows 95 работают и сегодня. Платформа может быть немодной, но она всё ещё способна на вещи, которые современным фреймворкам не так просто повторить.