
Создание комбинированных иконок

Создание комбинированных иконок
Комбинирование иконок применяется в Windows очень часто. Самый яркий пример - маленькая иконка со стрелочкой поверх основной иконки приложения на ярлыках. Или иконки расшаренных дисков и каталогов. В приложениях такой трюк тоже можно использовать, когда интерфейс предполагает большое количество кнопок или графических STATIC'ов с разными состояниями. Вместо того, чтобы таскать в ресурсах кучу иконок под каждое состояние каждого элемента интерфейса, достаточно хранить базовый набор иконок и маленькие иконки-оверлеи, а затем их динамически комбинировать.
Как несложно догадаться, тут используется обычное рисование. На холст базовой иконки накладывается изображение оверлея, после чего из полученного рисунка при помощи функции CreateIconIndirect создается комбинированная иконка. У меня получилась следующая процедура:
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------------
- ; Процедура комбинирования двух иконок
- ;------------------------------------------------------------------
- ; На входе:
- ; BackIcon - хэндл фоновой иконки
- ; FrontIcon - хэндл иконки-оверлея
- ; На выходе:
- ; EAX - хэндл комбинированной иконки
- ;------------------------------------------------------------------
- proc combine_icons BackIcon:DWORD, FrontIcon:DWORD
- struct ICONINFO
- fIcon dd ?
- xHotspot dd ?
- yHotspot dd ?
- hbmMask dd ?
- hbmColor dd ?
- ends
- locals
- hIcon dd ?
- WinDC dd ?
- FrontDC dd ?
- FrontSv dd ?
- BackDC dd ?
- BackSv dd ?
- FrontInfo ICONINFO
- BackInfo ICONINFO
- bm BITMAP
- endl
- pusha
- invoke GetDC,0
- mov [WinDC],eax
- ; Используются локальные структуры
- lea esi,[FrontInfo]
- lea edi,[BackInfo]
- invoke GetIconInfo,[FrontIcon],esi
- invoke CreateCompatibleDC,[WinDC]
- mov [FrontDC],eax
- invoke SelectObject,[FrontDC],[esi+ICONINFO.hbmMask]
- mov [FrontSv],eax
- invoke GetIconInfo,[BackIcon],edi
- invoke CreateCompatibleDC,[WinDC]
- mov [BackDC],eax
- invoke SelectObject,[BackDC],[edi+ICONINFO.hbmMask]
- mov [BackSv],eax
- lea eax,[bm]
- invoke GetObject,[esi+ICONINFO.hbmMask], sizeof.BITMAP,eax
- lea eax,[bm]
- invoke BitBlt,[BackDC],0,0,\
- [eax+BITMAP.bmWidth],[eax+BITMAP.bmHeight],\
- [FrontDC],0,0,SRCCOPY
- ; Нарисовать оверлей поверх основной иконки
- invoke SelectObject,[BackDC],[edi+ICONINFO.hbmColor]
- invoke DrawIconEx,[BackDC],0,0,[FrontIcon],0,0,0,0,DI_NORMAL
- ; Создать комбинированную иконку
- invoke CreateIconIndirect,edi
- ; Сохранить ее хэндл
- mov [hIcon],eax
- ; Прибраться за собой
- invoke SelectObject,[FrontDC],[FrontSv]
- invoke DeleteDC,[FrontDC]
- invoke SelectObject,[BackDC],[BackSv]
- invoke DeleteDC,[BackDC]
- invoke ReleaseDC,NULL,[WinDC]
- invoke DeleteObject,[esi+ICONINFO.hbmColor]
- invoke DeleteObject,[esi+ICONINFO.hbmMask]
- invoke DeleteObject,[edi+ICONINFO.hbmColor]
- invoke DeleteObject,[edi+ICONINFO.hbmMask]
- popa
- ; Вернуть хэндл комбинированной иконки
- mov eax,[hIcon]
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ; Оверлей
- invoke LoadIcon,[ModuleHandle],2
- push eax
- ; Базовая иконка
- invoke LoadIcon,[ModuleHandle],1
- push eax
- ; Скомбинировать иконки
- stdcall combine_icons
- ; Установить иконку на STATIC
- invoke SendDlgItemMessage,[hwnddlg],ICON_1,STM_SETIMAGE,IMAGE_ICON,eax
Просмотров: 608 | Комментариев: 4

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(06.10.2023 в 11:22):
Косяк досадный исправлен теперь мною, Сила благодарит тебя!

==DJ==[ZLO]
(06.10.2023 в 09:08):
Исходного текста внутри не обнаружил я

DRON
(29.08.2023 в 16:02):
Нельзя использовать DrawIconEx для создания "комбинированных иконок", потому что при использовании premultiplied alpha
DrawIconEx(Background,Icon)+DrawIconEx(Background,Overlay)
НЕ РАВНО
DrawIconEx(Background,DrawIconEx(Icon,Overlay))
то есть последовательное рисование на фоне иконки и оверлея, не то же самое, что рисование оверлея на иконке с последующим рисованием результата на фоне.
DrawIconEx(Background,Icon)+DrawIconEx(Background,Overlay)
НЕ РАВНО
DrawIconEx(Background,DrawIconEx(Icon,Overlay))
то есть последовательное рисование на фоне иконки и оверлея, не то же самое, что рисование оверлея на иконке с последующим рисованием результата на фоне.

Rustamer
(29.08.2023 в 13:34):
Увы, современным миром иконок правит SVG. Растровым этот мир уже не будет..
Про комбинирование тоже вспомнились шары и древние версии Windows.
Но сам подобный подход, когда отдельно тащат оверлеи и основные иконки, я практически не встречал в реальных приложениях.
Про комбинирование тоже вспомнились шары и древние версии Windows.
Но сам подобный подход, когда отдельно тащат оверлеи и основные иконки, я практически не встречал в реальных приложениях.

Добавить комментарий
Заполните форму для добавления комментария
