Blog. Just Blog

Как зафиксировать ширину столбцов в ListView

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

ListView - очень удобный элемент диалоговых окон для вывода структурированных табличных данных. Но при всех своих плюсах, на мой взгляд, у него есть одно очень неприятное свойство. Чтобы зафиксировать ширину столбцов, ListView надо выводить без заголовков. Если в таблице отображается заголовок, то ширину столбцов пользователь может менять перетаскиванием или двойным кликом на границах заголовков. Чтобы одновременно таблица и с заголовком, и с фиксированной шириной столбцов - так сделать не получится ни через описания ресурсов, ни через установку расширенного стиля ListView. В большинстве случаев это действительно ни к чему, данные в ячейках могут быть шире столбцов, и пользователю может понадобиться двигать границы, чтобы посмотреть содержимое. Но иногда для лучшей функциональности приложению требуется, чтобы и таблица имела заголовок, и пользователь не мог намеренно или случайно изменить ширину ее столбцов.

Если воспользоваться какой-нибудь программой для получения информации о диалоговых окнах и их элементах, то выяснится, что заголовок является дочерним окном ListView. Для подавления всех действий пользователя, надо субклассировать обработчик заголовка, а в нашей собственной процедуре обработки отслеживать сообщения WM_SETCURSOR и WM_LBUTTONDOWN. Это предотвратит изменение формы курсора при наведении на границу заголовка столбца и заблокирует любые действия по нажатию левой кнопки мыши. Все остальные строки списка при этом будут работать без изменений.
  1. ; Сегмент данных
  2. section '.data' data readable writeable
  3.  
  4. szHList db 'SysHeader32',0 ; Класс окна заголовка ListView
  5. OldProc dd ?    ; Предыдущий обработчик для субклассирования
  6. hList   dd ?    ; Хэндл ListView
  7. hHead   dd ?    ; Хэндл заголовка списка
  8. ...
  9. ...
  10.  
  11. ; Сегмент кода
  12. section '.code' code readable executable
  13. ...
  14. ...
  15.         ; Получить хэндл ListView
  16.         invoke  GetDlgItem,[hwnddlg],ID_LIST
  17.         mov     [hList],eax
  18. ...
  19. ...
  20.         ; Найти окно заголовка ListView
  21.         invoke  FindWindowEx,[hList],NULL,szHList,NULL
  22.         mov     [hHead],eax
  23.  
  24.         ; Установить наш собственный обработчик
  25.         invoke  SetWindowLong,[hHead],GWL_WNDPROC,ListWindowProc
  26.         ; Сохранить хэндл предыдущего обработчика
  27.         mov     [OldProc],eax
Процедура субклассированного обработчика заголовка выглядит следующим образом:
  1. ; Субклассированный обработчик заголовка ListView
  2. proc ListWindowProc hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
  3.         ; Установить курсор внутрь заголовка?
  4.         cmp     [uMsg],WM_SETCURSOR
  5.         je      .disable
  6.         ; Нажатие кнопки мыши?
  7.         cmp     [uMsg],WM_LBUTTONDOWN
  8.         je      .disable
  9. .exit:
  10.         ; Передать управление предыдущему обработчику
  11.         invoke  CallWindowProc,[OldProc],[hWnd],[uMsg],[wParam],[lParam]
  12.         ret
  13. .disable:
  14.         ; Подавить сообщение
  15.         xor     eax,eax
  16.         ret
  17. endp
Но это еще не все. Для подавления сообщения LVM_SETCOLUMNWIDTH, с помощью которого меняется ширина столбцов, надо в обработчике окна отслеживать сообщение WM_NOTIFY и, если поступило уведомление HDN_ITEMCHANGING, подавлять его. Делается это примерно так:
  1. ; Обработка сообщений окна
  2.         cmp     [msg],WM_NOTIFY
  3.         je      .wmnotify
  4. ...
  5. ...
  6.  
  7. ; Обработка уведомлений окна
  8. .wmnotify:
  9.         ; Указатель на NMHDR
  10.         mov     eax,[lparam]
  11.         ; Уведомление об изменении ширины столбца
  12.         cmp     dword [eax+NMHDR.code],HDN_ITEMCHANGING
  13.         jne     @f
  14.  
  15.         ; Установить ответ окна
  16.         invoke  SetWindowLong,[hwnddlg],DWL_MSGRESULT,TRUE
  17. @@:
  18.         jmp     .processed
Вот и все, теперь пользователь гарантированно не сможет изменить размеры столбцов ListView через перетаскивание границ заголовка, комбинацией клавиш Ctrl+Grey"+", а также через отправку сообщений окну списка. Чтобы мы сами из своего приложения могли менять ширину столбцов, надо предусмотреть установку какого-нибудь флага, при проверке которого обработчик уведомлений будет пропускать сообщение LVM_SETCOLUMNWIDTH. После изменения ширины флаг надо будет сбросить обратно.

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

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

Fixed.ListView.Demo.zip (3,537 bytes)


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

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

Комментарии

Отзывы посетителей сайта о статье
ManHunter (01.06.2015 в 08:45):
С отключенной галочкой автоподгонка работает, при включении фиксации заголовка - не работает. ЧТД.
Compiller (01.06.2015 в 08:44):
Сорри, Ctrl + Gray"+". Что-то я задумался когда писал...

Проверил, при установленной галке не срабатывает.
ManHunter (31.05.2015 в 22:33):
У меня это сочетание и так не работает. Готовый exe-шник для тестов в архиве.
Compiller (31.05.2015 в 17:16):
А сочетание Ctrl+Gray- будет работать по прежнему для автоподгонки ширины столбцов?

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

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

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