EnglishРусский Map

Прямой Win32 API и окна нестандартной формы

title
Прямой Win32 API и окна нестандартной формы
type
summary
summary
Как Win32 позволяет создавать непрямоугольные окна и почему эта эпоха десктопных интерфейсов почти исчезла
tags
win32, gui, nostalgia
created
2026-04-15
updated
2026-04-15
lang
ru
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 работают и сегодня. Платформа может быть немодной, но она всё ещё способна на вещи, которые современным фреймворкам не так просто повторить.

Код: github.com/IvRogoz/WierdApps