Как известно, в Кларионе не предусмотрен стандартный вывод иконок в заголовки колонок лист-бокса. В этой статье я расскажу вам о том, каким образом
можно обойти это ограничение.
Идея достаточно проста. Если рассмотреть заголовок как таковой, то он похож на обычную кнопку.
На стандартной кнопке мы легко можем показать иконку. Более того мы можем отцентрировать иконку по правому/левому краю или по центру. Таким образом, наложив стандартную
кнопку на заголовок колонки мы добьемся желаемого результата. Поэтому все что нужно, это знать координаты заголовка.
Создание кнопки
В Кларионе есть возможность создания контролов "на лету". Для этого используется оператор CREATE. Команда создает контрол. Атрибуты контрола (текст, размеры, иконка и т.д.) задаются через соответствующие свойства. Создание кнопки выглядит примерно так:
ButtonFEQ LONG ! переменная, которая будет использована для идентификации кнопки
code
ButtonFEQ=CREATE(0,CREATE:Button) ! создаем кнопку
ButtonFEQ{Prop:Icon}=clip(ImageName) ! присваиваем какую-нибудь картинку
ButtonFEQ{Prop:Flat}=TRUE ! кнопка будет плоской
ButtonFEQ{Prop:Skip}=TRUE ! пропускать кнопку при переходе по TAB
ButtonFEQ{Prop:Trn}=TRUE ! прозрачная кнопка
ButtonFEQ{Prop:Left}=TRUE ! выравнивание влево, на кнопке ничего не будет написано
ButtonFEQ{Prop:Text}='<13>' ! строка нужна для правильного выравнивания
ButtonFEQ{Prop:Xpos}=10 ! задание размеров кнопки
ButtonFEQ{Prop:Ypos}=10
ButtonFEQ{Prop:Width}=20
ButtonFEQ{Prop:Height}=10
unhide(ButtonFEQ) ! показать вновь созданную кнопку
Определение координат
Определение координат, это чистой воды лирика. Нет ничего сложного,
используются известные свойства лист-бокса ... и эмпирические наблюдения, на которые было потрачено
каких-то полных 3 дня :)
Таблица: Свойства лист-бокса
Свойство
Описание
Prop:Xpos
x координата лист-бокса
Prop:Ypos
y координата лист-бокса
Prop:Width
ширина лист-бокса
Prop:HeaderHeight
высота заголовка
Prop:HScrollPos
значение горизонтального скролл бара
Proplist:Width, ColumnNum
ширина колонки ColumnNum
Proplist:Exists, ColumnNum
возвращает TRUE, если колонка существует, в противном случае FALSE
Proplist:HeaderLeft, ColumnNum
возвращает TRUE, если текст колонки выравнивается по левому краю
Proplist:HeaderRight, ColumnNum
возвращает TRUE, если текст колонки выравнивается по правому краю
Proplist:HeaderCenter, ColumnNum
возвращает TRUE, если текст колонки выравнивается по центру
Proplist:HeaderLeftOffset, ColumnNum
отступ текста колонки слева
Proplist:HeaderRightOffset, ColumnNum
отступ текста колонки справа
Proplist:HeaderCenterOffset, ColumnNum
отступ текста колонки по центру - не работает
Proplist:MouseDownRow
номер строки, на которой нажали кнопку мыши, 0 если нажали на заголовке колонки
Proplist:MouseDownZone
зона, в которой нажали кнопку мыши, LISTZONE:Header если нажали на заголовке колонки
Proplist:MouseDownField
номер колонки, на которой нажали кнопку мыши
Proplist:GroupNo, ColumnNum
возвращает номер группы, если колонка входит в группу, если не входит возвращает номер колонки
Proplist:GroupNo+Proplist:Group, ColumnNum
возвращает количество колонок в группе, если колонка входит в группу, если не входит возвращает ноль
Proplist:Width+Proplist:Group, ColumnNum
возвращает ширину группы, в которую входит указанная колонка
Это далеко не полный перечень свойств лист-бокса.
Известные проблемы
Свойство Proplist:Width,ColumnNum не всегда возвращает корректную ширину колонки. Это происходит в случае если колонка является последней колонкой в лист-боксе или в группе.
Если колонка является последней колонкой в листе: ширина определяется как разница между всей шириной лист-бокса и шириной всех видимых колонок левее искомой. Если колонка является последней колонкой в группе - как разница между
шириной группы и шириной всех колонок в группе левее искомой.
Свойство Prop:HScrollPos. Возвращает значение горизонтального скролл-бара. Это значение изменяется от 0 до N, где N = (количества колонок в листе) - 1.
Немного расшифрую: допустим у вас есть 4 (четыре) колонки в листе. Следовательно свойство Prop:HScrollPos может принимать значения 0, 1, 2, 3. Когда горизонт. скролл бар установлен в крайнее левое положение
свойство Prop:HScrollPos=0, в крайнее правое Prop:HScrollPos=3. Т.е. это свойство как бы говорит - сколько колонок спрятано, не видно, находится левее первой видимой колонки в листе.
Это свойство работает хорошо ... пока не появляются группы колонок. При наличии групп свойство изменяется до M, где M = (количество колонок без групп) + (количество групп) - 1.
Вертикальный скролл-бар. Вертикальный скролл-бар может присутствовать или отсутствовать в лист-боксе. Также ширина
скролл-бара зависит от настроек Windows. Я не нашел стандартной возможности Клариона определить эти параметры. Существуют две API функции: GetSystemMetrics(SM_CXVSCROLL) - возвращает ширину скролл-бара, GetScrollInfo - помогает определить
видимость скролл-бара.
Точность измерения размеров. Все измерения желательно проводить в пикселях. Для этого для окна необходимо установить свойство MyWindow{Prop:Pixels}=TRUE.
Не забудьте восстановить это свойство в первоначальное значение после всех измерений.
Я измеряю x-координату путем суммирования ширины всех колонок левее искомой. При таком способе необходимо помнить
о наличии разделительной линии Proplist:RightBorder,ColumnNum шириной в 1 пиксель.
При измерении высоты заголовка колонки и y-координаты необходимо помнить о возможности группирования колонок.
Перерисовка кнопок
После того как вы создали кнопку и наложили ее на заголовок лист-бокса попробуйте изменить размеры колонки. Вы увидите, что кнопка останется
на месте, т.е. не переместится и не изменит своих размеров вместе с колонкой. Если вы переместите ползунки вертикального или горизонтального скролл-бара, то кнопка вообще исчезнет. "Исчезновение" произойдет также
и при изменении размеров лист-бокса. Раз так, следует учесть этот момент и при возникновении таких событий перерисовывать кнопки (опять узнать размеры заголовков колонки и присвоить их свойствам кнопки).
Для учета изменения размеров колонок, можно использовать событие EVENT:ColumnResize. Например, так:
эта строка говорит о том, что при возникновении события EVENT:ColumnResize в контроле self.ListBoxFEQ (лист-бокс) будет вызван метод self.Redraw (перерисовать кнопки).
Возможно вы уже подумали, что для обработки изменения размеров лист-бокса необходимо использовать событие Event:Sized. Неа...нельзя :) Потому что при обработке события Event:Sized Кларионом system is modal, а это означает, что пока идет обработка
этого сообщения вы ничего не можете сделать с контролами. Если не можем напрямую обработать событие, то это можно сделать через сабклассинг. Я отлавливаю сообщения
WM_HSCROLL/WM_VSCROLL (перемещение ползунка горизонт/вертик. скролл-баров ), WM_SIZE (изменение размеров) и посылаю свое собственное событие EVENT:Redraw лист-боксу.
А для этого события, также выполнен код:
пока происходит этот несколько "хитрый" обмен сообщениями system перестает быть modal :) и вы сможете изменить размеры ваших кнопок так как вам нужно.
Следует помнить, что может возникнуть ситуация, что заголовка колонки, на котором вы хотите отрисовать кнопку, не видно на экране.
В этом случае ранее отрисованную кнопку необходимо скрывать, используя свойство Prop:Hide или совсем уничтожать, используя команду DESTROY.
Эмуляция нажатия кнопки мыши на заголовке
Здесь тоже все просто. Опять используем сабклассинг и отлавливаем события WM_LBUTTONDOWN - нажатие левой кнопки мыши, WM_LBUTTONUP - отпускание левой кнопки мыши.
Используя свойства Proplist:MouseDownField, Proplist:MouseDownRow, Proplist:MouseDownZone убеждаемся, что нажали именно на заголовке, и узнаем номер колонки.
По нажатию кнопки создаем на заголовке контрол Region. Эффект нажатия создается за счет выставления атрибута ?Region{Prop:Bevel,1}=-1. По отпусканию кнопки регион уничтожается.
Код
Эта статья сможет вам помочь понять и разобраться в коде класса, который позволит вам отрисовывать иконки
в заголовке лист-бокса и отлавливать момент нажатия кнопок мыши. Переопределив виртуальные методы, вы сможете задать свое поведение при нажатии на заголовок: это может быть сортировка колонок; реверсная сортировка; вы можете
обработать нажатие клавиш Ctrl и Shift вместе с кнопкой мыши для создания множественной сортировки и т.д.
Код выполнен на C55H, ABC, на Legacy-шаблонах не проверялся.
Written by ovv on 2007-12-03 11:05:43Привет! Попробовал прикрутить к проекту и обнаружил интересный эффект пропадания контролов в окне, из которого вызывается окно с прикрученным xHeaderClass. Вскрытие показало, что в xHeaderClass.clw надо в деструкторе оставить только dispose очереди, а цикл с destroy вынести в метод Kill. А так все здорово.
Only registered users can write comments. Please login or register.