Раскраска строк ListView на Ассемблере
Элемент диалоговых окон ListView (или SysListView32) - очень удобный элемент, особенно для табличного отображения данных или ведения логов. При всем своем удобстве, у него есть недостаток, что при заполнении списка нельзя указывать цвета текста и фона для отдельных строк. Но способ раскрасить строки ListView все-таки есть. При отрисовке списка окну приложения посылается сообщение WM_NOTIFY, которое можно перехватить и самостоятельно обработать. В lParam сообщения передается указатель на структуру NMLVCUSTOMDRAW, в которой и описаны все подробности об отрисовываемой строке. Это составная структура и ее составляющие зависят от версии библиотеки Comctl32, но описываемый способ не сработает разве что на Windows 95, если вы его где-то откопаете. Однако компилятор FASM тоже ни сном, ни духом про структуру NMLVCUSTOMDRAW, придется сделать описание самостоятельно:Code (Assembler) : Убрать нумерацию
- ; Структура для обработки сообщений
- struct NMLVCUSTOMDRAW
- ; NMHDR
- hwndFrom dd ?
- idFrom dd ?
- code dd ?
- ; NMCUSTOMDRAWINFO
- dwDrawStage dd ?
- hdc dd ?
- left dd ?
- top dd ?
- right dd ?
- bottom dd ?
- dwItemSpec dd ?
- uItemState dd ?
- lItemlParam dd ?
- ; NMLVCUSTOMDRAW
- clrText dd ?
- clrTextBk dd ?
- ends
После теоретической подготовки переходим к практике. Сперва сделаем список с раскраской "зеброй", то есть чередование светлого и более темного фона строк. Это значительно повышает наглядность, особенно на широких таблицах. В параметре dwItemSpec структуры NMLVCUSTOMDRAW передается индекс (порядковый номер) строки. Проверяем его, и, если индекс четный, то устанавливаем один фон, если нечетный - другой. Обработчик WM_NOTIFY для окна ListView будет выглядеть примерно так:
Code (Assembler) : Убрать нумерацию
- ; Сообщение NM_CUSTOMDRAW?
- cmp dword [eax+nml.code],NM_CUSTOMDRAW
- jne .processed
- ; Пред-отрисовка строки?
- cmp dword [eax+nml.dwDrawStage],CDDS_PREPAINT
- jne @f
- ; Установить ответ окна
- invoke SetWindowLong,[hwnddlg],DWL_MSGRESULT,CDRF_NOTIFYITEMDRAW
- mov eax,CDRF_NOTIFYITEMDRAW
- jmp .processed
- @@:
- ; Требуется нарисовать строку?
- cmp dword [eax+nml.dwDrawStage],CDDS_ITEMPREPAINT
- jne @f
- ; Цвет фона нечетных строчек
- mov esi,0E0E0E0h
- ; Проверить индекс строки на четность
- test dword [eax+nml.dwItemSpec],1
- jnz .row_odd
- ; Цвет фона четных строчек
- mov esi,0FFFFFFh
- .row_odd:
- ; Установить цвет текста строки
- mov dword [eax+nml.clrText],0
- ; Установить цвет фона
- mov dword [eax+nml.clrTextBk],esi
- @@:
- jmp .processed
Code (Assembler) : Убрать нумерацию
- section '.data' data readable writeable
- ...
- colors rd 1000 ; Массив фоновых цветов строк
- ...
Code (Assembler) : Убрать нумерацию
- ; Заполнить список строчками
- xor ebx,ebx
- @@:
- ...
- ; Тут вызывается какая-нибудь функция генерации случайного числа,
- ; результат которой записывается в EAX
- ...
- ; Сохранить цвет фона в массиве
- mov ecx,ebx
- shl ecx,2
- and eax,0FFFFFFh
- mov [colors+ecx],eax
- ...
- ; Добавляем строку в список
- ...
- inc ebx
- cmp ebx,1000
- jb @b
Code (Assembler) : Убрать нумерацию
- ; Сообщение NM_CUSTOMDRAW?
- cmp dword [eax+nml.code],NM_CUSTOMDRAW
- jne .processed
- ; Пред-отрисовка строки?
- cmp dword [eax+nml.dwDrawStage],CDDS_PREPAINT
- jne @f
- ; Установить ответ окна
- invoke SetWindowLong,[hwnddlg],DWL_MSGRESULT,CDRF_NOTIFYITEMDRAW
- mov eax,CDRF_NOTIFYITEMDRAW
- jmp .processed
- @@:
- ; Требуется нарисовать строку?
- cmp dword [eax+nml.dwDrawStage],CDDS_ITEMPREPAINT
- jne @f
- ; Получить номер строки
- mov ebx,dword [eax+nml.dwItemSpec]
- ; Вычислить индекс массива фоновых цветов
- shl ebx,2
- mov esi,[colors+ebx]
- ; Вычислить текст текста - инверсный от цвета фона
- mov edi,esi
- not edi
- and edi,0FFFFFFh
- ; Установить цвет текста строки
- mov dword [eax+nml.clrText],edi
- ; Установить цвет фона
- mov dword [eax+nml.clrTextBk],esi
- @@:
- jmp .processed
В приложении две программы с исходными тестами, реализующие оба описанных в статье способа. Первая программа создает список, раскрашенный "зеброй", двойной клик удаляет выбранную строку из списка. Вторая программа создает список, в котором строки раскрашены случайным образом.
Просмотров: 5673 | Комментариев: 6
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(20.12.2013 в 15:18):
"Нельзя просто взять и воткнуть иконки" (С) Боромир :)
Иконки можно взять откуда угодно напрямую, но вставить их в ListView все равно придется только через ImageList, предварительно добавив их туда.
Иконки можно взять откуда угодно напрямую, но вставить их в ListView все равно придется только через ImageList, предварительно добавив их туда.
Grey
(20.12.2013 в 15:17):
Т.е. без добавления ImageList не обойтись...? Я наивно полагал что и напрямую иконки можно воткнуть.
ManHunter
(20.12.2013 в 15:05):
Не планируется, но подумаю.
И штудирование MSDN никто не отменял:
http://msdn.microsoft.com/en-u...s.85%29.aspx
http://www.frolov-lib.ru/books...2/ch3_1.html
И штудирование MSDN никто не отменял:
http://msdn.microsoft.com/en-u...s.85%29.aspx
http://www.frolov-lib.ru/books...2/ch3_1.html
Grey
(20.12.2013 в 15:03):
Как добавить иконки к строкам в ListView (или TreeView)? Второй части статьи не будет?
int_90
(03.02.2012 в 01:06):
А не подскажите как работать с выделенной строкой?(к примеру выделил(не кликнул) строку открылась подсказка).Перерыл пол гугля
Добавить комментарий
Заполните форму для добавления комментария
;-)))