Blog. Just Blog

Создание выпадающего списка (Combobox) с иконками

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Ранее я рассказывал, как сделать простой комбобокс. Сейчас давайте усовершенствуем его, а точнее дополним строки списка иконками. Я уже делал подобное с меню, тут принцип точно такой же. К стилям комбобокса в ресурсах добавляется CBS_OWNERDRAWFIXED, что в дальнейшем позволит нам самостоятельно обрабатывать процесс отрисовки каждой строки выпадающего списка. Теорию и принцип работы вы можете почитать по приведенной ссылке, повторяться я не буду. В обработчик окна, в котором находится комбобокс, добавляется реакция на два события - это WM_MEASUREITEM, которое приходит перед отрисовкой строки, и WM_DRAWITEM, при котором мы будем рисовать эту строку.
  1.         cmp     [msg],WM_MEASUREITEM
  2.         je      wm_measure
  3.         cmp     [msg],WM_DRAWITEM
  4.         je      wm_drawitem
Начнем с первого обработчика. Тут система в параметре lParam сообщения передает нам структуру MEASUREITEMSTRUCT, в которой сообщает нашей программе тип объекта, который она планирует нарисовать, а также его идентификаторы и размеры прямоугольника, который он будет занимать.
  1. wm_measure:
  2.         ; Отрисовываем строку комбобокса?
  3.         mov     ebx,[lparam]
  4.         cmp     [ebx+MEASUREITEMSTRUCT.CtlType],ODT_COMBOBOX
  5.         jne     processed
  6.  
  7.         ; Высота строки комбобокса с учетом размера иконки
  8.         mov     [ebx+MEASUREITEMSTRUCT.itemHeight],26
  9.  
  10.         jmp     processed
Проверяем, если это комбобокс, то меняем его высоту на фиксированные 26 пикселов. Ширина остается без изменений. Обратите внимание, что тут не проверяется идентификатор комбобокса CtlID, так как в нашем примере он один единственный. В реальных проектах, когда на форме может быть более одного выпадающего списка, такие проверки надо выполнять в обязательном порядке.

Переходим к основному пользовательскому обработчику - отрисовке строки выпадающего списка. Здесь в структуре DRAWITEMSTRUCT, на которую ссылается параметр lParam, приходят данные, непосредственно относящиеся к рисованию строки. Также первым делом проверяем, что на отрисовку передана именно строка комбобокса, при необходимости убеждаемся, что она принадлежит нужному списку, а затем начинаем художества.
  1. wm_drawitem:
  2.         ; Отрисовываем строку комбобокса?
  3.         mov     ebx,[lparam]
  4.         cmp     [ebx+DRAWITEMSTRUCT.CtlType],ODT_COMBOBOX
  5.         jne     processed
  6.  
  7.         ; Это выделенная или обычная строка?
  8.         test    [ebx+DRAWITEMSTRUCT.itemState],ODS_SELECTED
  9.         jnz     selected_text
  10.  
  11.         ; Обычная строка
  12.         invoke  GetSysColorBrush,COLOR_WINDOW
  13.         lea     ecx,[ebx+DRAWITEMSTRUCT.rcItem]
  14.         invoke  FillRect,[ebx+DRAWITEMSTRUCT.hDC],ecx,eax
  15.         invoke  GetSysColor,COLOR_WINDOW
  16.         invoke  SetBkColor,[ebx+DRAWITEMSTRUCT.hDC],eax
  17.         invoke  GetSysColor,COLOR_WINDOWTEXT
  18.         invoke  SetTextColor, [ebx+DRAWITEMSTRUCT.hDC],eax
  19.         jmp     @f
  20.  
  21. selected_text:
  22.         ; Выделенная строка
  23.         invoke  GetSysColorBrush,COLOR_HIGHLIGHT
  24.         lea     ecx,[ebx+DRAWITEMSTRUCT.rcItem]
  25.         invoke  FillRect,[ebx+DRAWITEMSTRUCT.hDC],ecx,eax
  26.         invoke  GetSysColor,COLOR_HIGHLIGHT
  27.         invoke  SetBkColor,[ebx+DRAWITEMSTRUCT.hDC],eax
  28.         invoke  GetSysColor,COLOR_HIGHLIGHTTEXT
  29.         invoke  SetTextColor, [ebx+DRAWITEMSTRUCT.hDC],eax
  30. @@:
  31.         invoke  SetBkMode,[ebx+DRAWITEMSTRUCT.hDC],TRANSPARENT
  32.  
  33.         ; Отступ для рисования текста
  34.         mov     [ebx+DRAWITEMSTRUCT.rcItem.left],26
  35.  
  36.         ; Текст в строке комбобокса
  37.         invoke  SendMessage,[ebx+DRAWITEMSTRUCT.hwndItem],\
  38.                 CB_GETLBTEXT,[ebx+DRAWITEMSTRUCT.itemID],buff
  39.         ; EAX = длина строки
  40.         lea     ecx,[ebx+DRAWITEMSTRUCT.rcItem]
  41.         invoke  DrawText,[ebx+DRAWITEMSTRUCT.hDC],\
  42.                 buff,eax,ecx,DT_SINGLELINE+DT_VCENTER+DT_LEFT
  43.  
  44.         ; Иконка по индексу строки комбобокса
  45.         invoke  GetModuleHandle,0
  46.         mov     ecx,[ebx+DRAWITEMSTRUCT.itemID]
  47.         inc     ecx
  48.         invoke  LoadIcon,eax,ecx
  49.  
  50.         mov     ecx,[ebx+DRAWITEMSTRUCT.rcItem.bottom]
  51.         sub     ecx,[ebx+DRAWITEMSTRUCT.rcItem.top]
  52.         sub     ecx,16
  53.         shr     ecx,1
  54.         add     [ebx+DRAWITEMSTRUCT.rcItem.top],ecx
  55.         mov     [ebx+DRAWITEMSTRUCT.rcItem.left],6
  56.         invoke  DrawIconEx,[ebx+DRAWITEMSTRUCT.hDC],\
  57.                 [ebx+DRAWITEMSTRUCT.rcItem.left],\
  58.                 [ebx+DRAWITEMSTRUCT.rcItem.top],\
  59.                 eax,16,16,NULL,NULL,DI_NORMAL+DI_COMPAT
  60.  
  61.         jmp     processed
Для выделенной строки списка рисуется залитый фон с использованием стандартных системных цветов, для обычной строки рисуется пустой прямоугольник. Затем загружается текст строки и рисуется со сдвигом вправо на ширину иконки плюс несколько пикселов отступа для красоты. Иконка рисуется слева с вертикальной центровкой. В приведенном примере иконки загружаются сразу из ресурсов на основании индексов рисуемой строки, в других случаях иконки могут быть предварительно загружены, а их хэндлы помещены в массивы для каждого списка в отдельности. Размер иконок значения не имеет, просто подкорректируйте отступы текста и высоту строк в зависимости от их пропорций, можно даже сделать различную высоту для разных строк комбобокса и поместить в один список иконки разных размеров.

Выпадающий список с иконками
Выпадающий список с иконками

Вот и все, как видите, в создании красивых выпадающих списков с иконками нет ничего сложного. Обработка событий самого списка остается без изменений, я специально оставил ее такой же, как она была в старом примере.

В приложении пример программы с исходным текстом, которая отрисовывает выпадающий список с иконками и обрабатывает выбор элементов.

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

Combobox.Icon.Demo.zip (5,079 bytes)


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

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (23.08.2019 в 01:38):
Все, теперь эта говносистема совместима с примером. Архив с исходником обновлены. Алексей, спасибо!
Алексей (22.08.2019 в 21:11):
Что то под win 10 (х64) криво работает, заводишь, а она завершает свой процесс спустя пару секунд.

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

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

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