Идёт загрузка страницы...

htp://aptem.net.ru






На главную страничку учебника Visual Basic

Создание компонента ActiveX - графической кнопки

Итак, вам нужен определённый компонент (контрол). Есть несколько путей для решения этой проблемы:

  • Найти похожий контрол в Интернете (или, к примеру, на диске).
  • Создать свой собственный!

Первый вариант достаточно прост, но имеет недостатки. Во-первых контрол обязательно чем-то вам не угодит (поверьте мне, Обязательно!). Например, вам не понравится то, что нельзя изменить цвет фона или что-то другое. Во-вторых разве можно назвать приложение "вашим", если оно целиком и полностью будет состоять из чужих компонентов? Нет. Так что остаётся второй вариант, а именно Создание своего контрола.

Для украшения своих приложений я решил создать свой контрол - кнопку, с 3-мя состояниями (не нажата и нет курсора мыши, не нажата и есть курсор, нажата). На это у меня ушёл всего навсего один день! Кстати таких компонентов в интернете очень и очень много, но мы будем создавать свой.

Шаг №1. Создание свойств и методов, которые будет поддерживать контрол.

Итак, запускаем VB6. Выбираем из меню тип приложения - ActiveX Control. Теперь перед нами пустая форма без заголовка. Лезем в меню Add-Ins и выбираем там ActiveX Control Interface Interface Wizard. (Если вы не нашли такого пункта, то выберите команду Add-In Manager. Там отметьте галочкой всё, что нужно и жмите ОК. Ну, а если у вас и там нет такого пункта, то вам нужно запустить установку VB и добавить этот Wizard). Если вы всё сделали правильно, то должно появиться окошко, в котором слева будет список доступных свойств, методов и событий, которые вы можете включить в ваш компонент. Оставляем всё, как есть и жмём Next. Далее нам предлагают создать свои собственные события, свойства или методы. Нажмите на кнопку New. В поле Name наберите MouseOut, а в поле Type - Event. Таким образом мы создали новое событие MouseOut. Теперь нам необходимо создать свойства NormalState, DownState, OverState. Можно ещё добавить метод About (если хотите). Жмём 2 раза Next. Теперь нам нужно задать тип созданных нами свойств и методов. Для свойств NormalState, DownState, OverState выбираем тип Picture и в списках RunTime и DesignTime выбираем Read/Write (т.е. свойство доступно и для чтения, и для записи). Для метода ставим ReturnType в Empty. Всё, создание каркаса закончено, можно приступать к программированию!

Шаг №2. Программирование нашего компонента.

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

Теперь создадите 3 Image. В них будут храниться наши рисунки для разных состояний кнопки. Назовите из соответственно imgNormalState, imgDownState, imgOverState. В них загрузите картинки, соответстующие разным состояниям кнопки. Я наваял в PhotoShop три картинки, которые вы можете взять тут.

Нам понадобятся 3 API ф-ции Windows. Вот их определения:

Private Declare Function SetCapture Lib "user32" _
(ByVal hwnd As Long) As Long
Private Declare Function ReleaseCapture Lib "user32" () As Long
Private Declare Function GetCapture Lib "user32" () As Long

Первая устанавливает обработку события мыши на компонент. Вторая возвращает обработку в обычное состояние. Третья возвращает Handle элемента управления, для которого в данный момент определён SetCapture.

Вы скажете: "А нафига нам эти ф-ции? Чё, нельзя было обойтись стандартными - бейсиковскими???". Нельзя. Подумайте, как вы будете определять событие MouseOut? То-то. А при помощи этих ф-ций событие MouseMove будет происходить даже тогда, когда курсор мыши будет находится за пределами элемента управления! И следовательно мы легко можем определить событие MouseOut.

Теперь объявите переменную bstate, которая будет хранить Boolean значение. (находится над кнопкой курсор, или нет).

Dim bstate As Boolean

Здесь необходимо напомнить, что свойства в UserControl (т.е. в нашем компоненте) задаются и читаются с использованием разных процедур Set и Get. Вообще об этом можно написать целую страницу, но мы не будем вдаваться в подробности - сейчас главное - суть. Теперь найдите в коде реализацию процедуры Set NormalState. Она выполняется всякий раз, когда мы изменяем свойство NormalState UserControl'a. Нам необходимо добавить в конце вот такие строчки:

Picture = NormalState 'Положить на фон UserControl'a картинку
'определённую только что определённым свойством NormalState

imgNormalState = New_NormalState 'назначить эту же картинку для Image

В процедуры Set DownState и Set OverState добавьте соответственно строчки:

imgDownState.Picture = New_DownState

imgOverState.Picture = New_OverState

Теперь найдите обработчик события UserControl_InitProperties. В нём задаются начальные свойства (как у формы событие Load). Добавьте вот такую строчку:

UserControl.Picture = imgNormalState 'Задаём начальную картинку

В обработку события MouseDown UserControl'a добавьте строчки:

RaiseEvent MouseDown(Button, Shift, X, Y) 'запуск события MouseDown
'которое будет происходить, когда наш компонент уже будет находиться
'на использующей его форме

UserControl.Picture = imgDownState 'Изменяем картинку на DownState
bstate = True 'Устанавливаем переменную bstate

В событие MouseUp добавьте:

RaiseEvent MouseUp(Button, Shift, X, Y) 'То же самое, что и выше
UserControl.Picture = imgNormalState 'Изменяем картинку на NormalState
bstate = False 'Устанавливаем переменную bstate
RaiseEvent Click 'запускаем событие Click

Для обработки события Show UserControl'a я приготовил такой вот код (он сработает сразу тогда, когда пользователь поместит элемент на форму):

imgNormalState = NormalState
imgOverState = OverState
imgDownState = DownState
'загружаем умолчательные картинки в Imag'ы
'(т.е. те которые я создавал в PhotoShop)

UserControl.Picture = imgNormalState 'Отображаем на UserControl'e
'картинку NormalState

Кстати здесь необходимо заметить, что в VB есть умолчательные свойства. Для разных элементов они разные. Например, у Label - это Caption, у Text - Text, а у Image - Picture. Поэтому я могу сразу поставить знак равенства и присвоить значение.

А сейчас найдите обработку WriteProperties UserControl'a и замените строчку:

эту:
Call PropBag.WriteProperty("NormalState", m_NormalState, Nothing)

на вот эту:
Call PropBag.WriteProperty("NormalState", m_NormalState, _
imgNormalState)

Таким образом, мы задали умолчательное свойство для переменной m_NormalState, хранящей значение свойства NormalState.

Теперь осталась самая трудная задача - обработка события MouseMove. Вот предложенный мною код (без отступов разобраться очень сложно, поэтому я советую посмотреть этот код в исходнике кнопки):

Private Sub UserControl_MouseMove (Button As Integer, _
Shift As Integer, X As Single, Y As Single)

If bstate <> True Then
RaiseEvent
MouseMove(Button, Shift, X, Y)
Dim k, ret As Long
If GetCapture() <> UserControl.hwnd Then
ret = SetCapture(UserControl.hwnd)
End If
If (X < 0) Or (Y < 0) Or (X > UserControl.ScaleWidth) Or _
(Y > UserControl.ScaleHeight) Then
RaiseEvent
MouseOut
If
UserControl.Picture <> imgNormalState Then
UserControl.Picture = imgNormalState
End If
ret = ReleaseCapture()
Else
If
UserControl.Picture <> imgOverState Then
UserControl.Picture = imgOverState
End If
End If
Else
If
(X < 0) Or (Y < 0) Or (X > UserControl.ScaleWidth) Or _
(Y > UserControl.ScaleHeight) Then
RaiseEvent MouseOut
If UserControl.Picture <> imgNormalState Then
UserControl.Picture = imgNormalState
End If
bstate = False
End If
End If

End Sub

Этот код очень прост, несмотря на кажущуюся сложность. Вкратце могу сказать, что сначала мы проверяем не установлена ли уже обработка событий мыши для UserControl'a. Если нет - то устанавливаем. После установки в обработку события MouseMove передаются и отрицательные координаты (т.е. когда мышь выходит за пределы UserControl'a слева или сверху). Далее идёт проверка этих координат на предмет наступления MouseOut. После возвращаем стандартный обработчик ф-цией ReleaseCapture.

Важно: не забудьте включить AutoRedraw у UserControl'a, а то кнопка будет подмигивать при нажатии.

Ну вот и всё!!! Теперь для тестирования можете добавить ещё один проект типа Standart EXE. Активизируйте, а затем закройте форму UserControl'a. Если этого не сделать, то вы не сможете поместить элемент на форму добавленного проекта.

Итак, поместите только что созданный элемент на форму и запустите проект. Если вы всё сделали правильно, то контрол должен работать. Можете поэкспериментировать, загружая другие картинки. КОНТРОЛ Я ПРАКТИЧЕСКИ НЕ ТЕСТИРОВАЛ, так что вы можете найти кучу багов (если найдёте - напишите мне).

Да, ещё можете изменить иконку, которая появляется на панели элементов. Для этого необходимо загрузить bitmap картинку в свойство ToolBoxBitmap размером 16x15 пикселей.

Исходники кнопки можно загрузить здесь.

На главную страничку учебника Visual Basic