===[ ListView ]=== #post-id: 5874-03-05 #original-date: 25.08.2016 Thu #original-time: 3:05 AM #original-day: 5874 #original-host: WinXP Home SP3 (Build 2600) В VB5 был набор улучшенных контролов, который появился в Windows 95. Тоесть, контролы появились в системе, а в VB5 был OCX компонент с обёртками для них. Удобные и крутые. Потом пришёл VB6, а вместе с ним – шестая версия этих контролов. Там всё стало ещё удобнее, объектная модель улучшилась, добавили фич (например, цвета строк в ListView). Ну и ещё некоторые контролы добавили, которых в пятой версии не было. А потом пришла Windows XP и война с манифестами, чтобы стиль окон был новый, а не как у старых программ без манифеста. Вот тут и выяснилось, что шестая версия контролов не рисуется с новым стилем, а сохраняет старый стиль, как в классическом интерфейсе. Статьи по использованию манифестов советовали использовать пятую версию, с которой такой проблемы не было. Оказалось, что пятая версия – обёртка вокруг стандартного системного контрола, а шестая полностью рисует такой контрол в обход системы, попутно эмулируя API ListView, да и то не все. Поэтому система и не знает, как вешать на него стили. Поэтому я решила постепенно мигрировать на пятую версию, хоть у неё и менее удобная объектная модель, и иных полезных свойств нет. Так, я написала обёртки для красивостей вроде выделения на всю ширину списка и сетки. Правда, пока руки не дошли до чекбоксов и раскраски элементов (которая потребует нечто большего, чем просто пара вызовов API функций). Попутно начали обнаруживаться баги, которые исправили в шестой версии, но забыли в пятой несмотря на то, что там какие-то «сервиспаки» в названии приписаны. Например только что столкнулась с такой ситуацией. Есть объект ListItem, который представляет строку в списке. У него есть свойство Tag типа Variant – самое то для всяких полезных данных. Внутренние контролы VB оперируют только Tag типа String по причине совместимости едва ли не с VB1, а тут Variant, в который хоть строку, хоть число, хоть объект со всем данными, что тебе нужны. Последний вариант я решила заюзать: беру ListItem с новой строкой, присваиваю Tag объект, содержащий данные о процессе. Ну, тоесть в списке всё отформатировано, красивые числа, прочее, а в объекте – типизированные значения для обработки в будущем. «Runtime error 424: Object required». И всё. И никак. Проблема именно с присвоением к Tag. Там какой-то странный Variant, ибо тут я создаю просто переменную типа Variant и спокойно присваиваю ей, а тут – ошибка. Даже если Nothing попытаться присвоить. В итоге плюнула и стала пихать туда строку с «упакованными» значениями, которые легко распарсить. Но неприятный костыль. А вот другая ситуация. У меня есть библиотека, в которой есть класс для сохранения настроек. Не просто для работы с реестром, а для сохранения настроек без лишних мыслей, куда оно пишется. Среди прочего там есть функции, которые сохраняют и восстанавливают ширину колонок ListView, которые пользователь может спокойно тягать туда-сюда. Функция писалась во времена шестой версии и прекрасно работала. А тут... SaveListViewColumns. В реестр уходят значения, всё красиво. LoadListViewColumns. Ширина колонок восстанавливается, но колонки заметно шире, чем должны быть. Начала выяснять. Читаю свойство Width колонки, получаю цифру. Устанавливаю её же тому же свойству – колонка расширяется. Читаю свойство – та же цифра, хотя она не может быть той же! Взяла в руки API, проверила напрямую – действительно, данные различаются до установки и после. Потом поковырялась и выяснила, что значение свойства обновляется не раньше инициирования события изменения размера колонок, даже если по факту ни одна и колонок размер не изменит – видимо значение где-то кэшируется внутрях и перечитывается только по событию изменения размера. А LoadListViewColumns оперирует только со свойствами контрола. В итоге плюнула и написала гибрид: количество колонок получается через свойства, а размеры получаются и устанавливаются через API. Просто забыла, как получать количество колонок через API, а потом лень стало переделывать. Решила не патчить имеющуюся библиотеку CommonFunctions0301.DLL, а сразу сделать CommonFunctions0302.DLL, в которой заодно поправить то, что исправить нужно было давно, но оно рушило бинарную совместимость. Кстати, последний билд версии 3.01 был аж в 2014 году. Ну или я просто забыла поправить год в копирайте.