ActiveX

Опыт создания линейки прокрутки.

 

Я неоднократно сталкивался с ситуациями, когда создавая нестандартный интерфейс, вынужден был использовать стандартные компоненты, не отвечающие общей идее. Самым ярким примером может служить линейка прокрутки. Это наверное единственный элемент управления, который не может изменять свою окраску. Поэтому создавая разноцветные формы, чтобы избежать не согласованности, всегда приходится думать чем заменить линейку прокрутки. В конце концов это меня вынудило создать свой собственный ActiveX Control, который отвечал бы моему интерфейсу. Художник я неважный поэтому нашел способ, позволяющий без особых проблем создавать различного вида схематические рисунки. В данном случае я использовал Автофигуры в Word'е с последующей их раскраской. Сохранив документ как HTML-файл, я получил возможность использовать их в своей программе.

Если уж делать, то делать, убивая сразу двух зайцев. Я решил вместо двух линеек прокрутки (горизонтальной и вертикальной) создать один элемент управления, обладающий свойствами обеих. Если Вам это интересно, то последовательно вместе со мной Вы сможете создать себе такой же.

Создадим проект ActiveX Control: Name = DoubleScroll; сам UserControl назовем DblScroll. Расположим на нем:

pic PictureBox Является контейнером для нижеуказанных элементов управления
picSignH PictureBox Height=Width=195 твипов
picSignV PictureBox Height=Width=195 твипов

На первом этапе, еще не создавая свойств и событий, добьемся чтобы наш будущий контрол имел прозрачную подложку. Я не буду подробно останавливаться на на этих функциях (они достаточно хорошо описаны на сайте vbrussian.com). Скажу только, что смысл их заключается в попиксельном считывании картинки и невключении пикселов заданного цвета в регион. Далее выводим этот регион на нашем UserControl'е. Данную процедуру (Draw) необходимо инициализировать в событии UserControl_Show, для полноценного отображения всех наших преобразований во время выполнения.

NB! Попиксельное считывание картинки - достаточно длительная процедура. Помните об этом, когда будете создавать свои картинки, не делайте их слишком большими!

Создайте тестировочный проект, расположите на форме создаваемый контрол и посмотрите промежуточный результат.

Расположите picSignH на горизонтальной части линейки прокрутки, а picSignV - на вертикальной. Займемся движениями бегунков при нажатии на них и перетаскивании.

NB! Обратите внимание на константы, объявляемые нами в разделе деклараций: 
Private Const SIGN_SIZE = 195 'высота(ширина) бегунка в твипах
Private Const SIDE_SIZE = 420 'высота(ширина) звездочки (заменяет стрелку на обычной линейке) в твипах
Если Вы будете использовать свой рисунок, не забудьте поменять значения этих констант для корректной работы контрола.

Создадим 2 процедуры, считывающие начальную и конечную координаты бегунков:

Private Sub picSignMouseDown()
    Dim res As Long
    startMove = True
    res = GetCursorPos(FirstPos)
End Sub

Private Sub picSignMouseUp()
    Dim res As Long
    res = GetCursorPos(LastPos)
    startMove = False
End Sub

И используем их, соответственно, для событий MouseDown и MouseUp наших бегунков. А вот в событии MouseMove мы будем перемещать непосредственно сам бегунок, предварительно ограничив его движения по краям
Если сейчас мы запустим тестировочный проект, то вполне сможем насладиться нашим контролом и перетаскиванием бегунков. Однако, до получения законченного результата еще далеко, так как в настоящий момент мы имеем "вещь в себе". Красивая безделушка, не связанная ни с чем. Настало самое время добавить свойства и методы.

Воспользуемся мастером создания ActiveX Control'ов и создадим элементы интерфейса, указанные ниже в таблице. Учитывая, что у нас, по сути, 2 линейки прокрутки, все свойства придется дублировать (вертикальные и горизонтальные):

  Имя Тип Значение по умолчанию Описание
Свойство MaxH Long 100 Максимальное значение горизонтальной части
Свойство MaxV Long 100 Максимальное значение вертикальной части
Свойство MinH Long 0 Минимальное значение горизонтальной части
Свойство MinV Long 0 Минимальное значение вертикальной части
Свойство LargeChangeH Long 10 Смещение (в единицах) при щелчке между бегунком и краем по горизонтали
Свойство LargeChangeV Long 10 Смещение (в единицах) при щелчке между бегунком и краем по вертикали
Свойство SmallChangeH Long 1 Смещение (в единицах) при щелчке на концевую часть по горизонтали
Свойство SmallChangeV Long 1 Смещение (в единицах) при щелчке на концевую часть по вертикали
Свойство ValueH Long 0 Текущее горизонтальное значение
Свойство ValueV Long 0 Текущее вертикальное значение
Событие Scroll - - Событие, возникающее при щелчке на любую из линеек
Событие HorizontalScroll - - Событие, возникающее при щелчке на горизонтальную линейку
Событие VerticalScroll - - Событие, возникающее при щелчке на вертикальную линейку

Напишем две процедуры, описывающие положение бегунка, с учетом ограничения движения (вот где нам понадобились константы!):

Private Sub PosHorizontal()
    picSignH.Left = (pic.ScaleWidth - (2 * SIDE_SIZE) - SIGN_SIZE) * m_ValueH / (m_MaxH - m_MinH) + SIDE_SIZE
End Sub

Private Sub PosVertical()
    picSignV.Top = (pic.ScaleHeight - (2 * SIDE_SIZE) - SIGN_SIZE) * m_ValueV / (m_MaxV - m_MinV) + SIDE_SIZE
End Sub

Вставим эти процедуры в Property Let свойств Min, Max и Value (горизонтальные и вертикальные соответственно).
И теперь (наверно, самое сложное в этом контроле) мы должны описать реакцию нашего элемента на щелчок по его различным "частям тела". Делается это в событии pic_MouseDown. Здесь же устанавливаются проверки на допустимость выставляемых значений свойств.
Не забудьте добавить выполнение событий контрола в picSignV_MouseMove и picSignV_MouseMove.

Вот теперь наш контрол готов. Осталось добавить необходимые мелочи: описание свойств и событий для возможности их прочтения в Object Browser, создания PropertyPage, формы About и желательно Help).

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


Назад К Листингу Скачать пример
Hosted by uCoz