Blog. Just Blog

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

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Создание комбинированных иконок
Создание комбинированных иконок

Комбинирование иконок применяется в Windows очень часто. Самый яркий пример - маленькая иконка со стрелочкой поверх основной иконки приложения на ярлыках. Или иконки расшаренных дисков и каталогов. В приложениях такой трюк тоже можно использовать, когда интерфейс предполагает большое количество кнопок или графических STATIC'ов с разными состояниями. Вместо того, чтобы таскать в ресурсах кучу иконок под каждое состояние каждого элемента интерфейса, достаточно хранить базовый набор иконок и маленькие иконки-оверлеи, а затем их динамически комбинировать.

Как несложно догадаться, тут используется обычное рисование. На холст базовой иконки накладывается изображение оверлея, после чего из полученного рисунка при помощи функции CreateIconIndirect создается комбинированная иконка. У меня получилась следующая процедура:
  1. ;------------------------------------------------------------------
  2. ; Процедура комбинирования двух иконок
  3. ;------------------------------------------------------------------
  4. ; На входе:
  5. ;     BackIcon - хэндл фоновой иконки
  6. ;     FrontIcon - хэндл иконки-оверлея
  7. ; На выходе:
  8. ;     EAX - хэндл комбинированной иконки
  9. ;------------------------------------------------------------------
  10. proc combine_icons BackIcon:DWORD, FrontIcon:DWORD
  11.         struct ICONINFO
  12.                 fIcon    dd ?
  13.                 xHotspot dd ?
  14.                 yHotspot dd ?
  15.                 hbmMask  dd ?
  16.                 hbmColor dd ?
  17.         ends
  18.  
  19.         locals
  20.                 hIcon     dd ?
  21.                 WinDC     dd ?
  22.                 FrontDC   dd ?
  23.                 FrontSv   dd ?
  24.                 BackDC    dd ?
  25.                 BackSv    dd ?
  26.                 FrontInfo ICONINFO
  27.                 BackInfo  ICONINFO
  28.                 bm        BITMAP
  29.         endl
  30.  
  31.         pusha
  32.  
  33.         invoke  GetDC,0
  34.         mov     [WinDC],eax
  35.  
  36.         ; Используются локальные структуры
  37.         lea     esi,[FrontInfo]
  38.         lea     edi,[BackInfo]
  39.  
  40.         invoke  GetIconInfo,[FrontIcon],esi
  41.  
  42.         invoke  CreateCompatibleDC,[WinDC]
  43.         mov     [FrontDC],eax
  44.         invoke  SelectObject,[FrontDC],[esi+ICONINFO.hbmMask]
  45.         mov     [FrontSv],eax
  46.  
  47.         invoke  GetIconInfo,[BackIcon],edi
  48.  
  49.         invoke  CreateCompatibleDC,[WinDC]
  50.         mov     [BackDC],eax
  51.         invoke  SelectObject,[BackDC],[edi+ICONINFO.hbmMask]
  52.         mov     [BackSv],eax
  53.  
  54.         lea     eax,[bm]
  55.         invoke  GetObject,[esi+ICONINFO.hbmMask], sizeof.BITMAP,eax
  56.         lea     eax,[bm]
  57.         invoke  BitBlt,[BackDC],0,0,\
  58.                 [eax+BITMAP.bmWidth],[eax+BITMAP.bmHeight],\
  59.                 [FrontDC],0,0,SRCCOPY
  60.  
  61.         ; Нарисовать оверлей поверх основной иконки
  62.         invoke  SelectObject,[BackDC],[edi+ICONINFO.hbmColor]
  63.         invoke  DrawIconEx,[BackDC],0,0,[FrontIcon],0,0,0,0,DI_NORMAL
  64.  
  65.         ; Создать комбинированную иконку
  66.         invoke  CreateIconIndirect,edi
  67.         ; Сохранить ее хэндл
  68.         mov     [hIcon],eax
  69.  
  70.         ; Прибраться за собой
  71.         invoke  SelectObject,[FrontDC],[FrontSv]
  72.         invoke  DeleteDC,[FrontDC]
  73.         invoke  SelectObject,[BackDC],[BackSv]
  74.         invoke  DeleteDC,[BackDC]
  75.         invoke  ReleaseDC,NULL,[WinDC]
  76.  
  77.         invoke  DeleteObject,[esi+ICONINFO.hbmColor]
  78.         invoke  DeleteObject,[esi+ICONINFO.hbmMask]
  79.         invoke  DeleteObject,[edi+ICONINFO.hbmColor]
  80.         invoke  DeleteObject,[edi+ICONINFO.hbmMask]
  81.  
  82.         popa
  83.  
  84.         ; Вернуть хэндл комбинированной иконки
  85.         mov     eax,[hIcon]
  86.  
  87.         ret
  88. endp
На входе в качестве параметров передаются хэндлы базовой иконки и хэндл иконки-оверлея, на выходе получаем хэндл комбинированной иконки, который можно использовать дальше. Процедура самодостаточная и не требует описания переменных в основном коде. Пример вызова:
  1.         ; Оверлей
  2.         invoke  LoadIcon,[ModuleHandle],2
  3.         push    eax
  4.         ; Базовая иконка
  5.         invoke  LoadIcon,[ModuleHandle],1
  6.         push    eax
  7.         ; Скомбинировать иконки
  8.         stdcall combine_icons
  9.         ; Установить иконку на STATIC
  10.         invoke  SendDlgItemMessage,[hwnddlg],ICON_1,STM_SETIMAGE,IMAGE_ICON,eax
В приложении пример программы с исходным текстом, которая выводит на форму несколько динамически созданных иконок.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Combine.Icons.Demo.zip (10,168 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 430 | Комментариев: 4

Метки: Assembler, иконки

Комментарии

Отзывы посетителей сайта о статье
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))
то есть последовательное рисование на фоне иконки и оверлея, не то же самое, что рисование оверлея на иконке с последующим рисованием результата на фоне.
Rustamer (29.08.2023 в 13:34):
Увы, современным миром иконок правит SVG. Растровым этот мир уже не будет..
Про комбинирование тоже вспомнились шары и древние версии Windows.
Но сам подобный подход, когда отдельно тащат оверлеи и основные иконки, я практически не встречал в реальных приложениях.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.06 сек. / MySQL: 2 (0.0041 сек.) / Память: 4.5 Mb
Наверх