ActiveX

Урок 4

Контрол, написанный "с нуля"

Добавление собственной Property Page

Четвертый урок посвящен созданию ActiveX Control'а "с нуля", поэтому и пояснения я постараюсь делать поподробнее. В качестве примера возьмем ProgressBar. "У-у-у", - скажете Вы. - "Их уже столько создано…" Тогда сразу же возникает резонный вопрос: "А почему так много?" По всей видимости, то, что уже существует по каким-либо параметрам не подходит для программистов. Элементарный вроде бы контрол, всего три свойства: минимальное, максимальное и текущее значения. Но он несет в себе одну важную функцию - скрашивает ожидание пользователя, когда по каким-либо причинам происходит задержка в работе программы. Так давайте отвлечем его: почему это должна быть обязательно синяя полоска, и почему она обязательно должна бежать именно слева - направо? И, в конце концов, давайте вообще откажемся от полоски как от таковой. Давайте создадим ProgressBar в форме песочных часов. Да это сложнее, но зато в конце получим более яркий эффект.

Открываем новый проект, назовем его pbHourglass, а сам UserControl переименуем в pbHrglss.

Итак, шаг первый: вырезаем из ActiveX Control'a песочные часы. Для этого будем использовать две API-функции: CreatePolygonRgn и SetWindowRgn, а также тип POINTAPI. Скопируем их с помощью API Text Viewer. Там же в глобальных объявлениях запишем нашу переменную Private rgnPts() As POINTAPI. Внутри процедуры UserControl_Resize объявим количество точек, рисующих фигуру и переопределим массив.

NB! Так как массив начинается с 0, то переменная, несущая информацию о количестве точек, естественно, будет на 1 меньше.

numAngle = 17

ReDim rgnPts(0 To numAngle) As POINTAPI

Далее определим координаты каждой точки по осям X и Y, и запишем их в массив. Для того чтобы сделать зависимой нашу фигуру от размеров контрола дадим координаты в относительных величинах, используя свойства UserControl'a - ScaleWidth и ScaleHeight.

rgnPts(0).X = 0

rgnPts(0).Y = 0

rgnPts(1).X = ScaleWidth

rgnPts(1).Y = 0

rgnPts(2).X = ScaleWidth

rgnPts(2).Y = ScaleHeight * 0.1

…ну и так далее, вплоть до rgnPts(17) - подробнее смотри в листинге. Рисуем фигуру:

hRgn = CreatePolygonRgn(rgnPts(0), numAngle + 1, WINDING)

А теперь вырезаем:

SetWindowRgn UserControl.hWnd, hRgn, True

Давайте пока на этом остановимся и перейдем ко второму шагу, созданию свойств нашего ActiveX Control'a. С тремя основными мы уже определились вначале, это Max, Min, Value. Наверно неплохо бы было создать свойство Percent, несущее в себе информацию о проценте выполненного действия. Сделаем это свойство "только для чтения" (Read Only). Ну и, конечно, хотелось бы "побаловаться" с цветом. Поэтому добавим еще 3 свойства, отвечающие за фоновый цвет, цвет окантовки и цвет "песка": BackColor, BasisColor и SandColor, соответственно. Сделаем свойство BackColor контрола равным &H00FFFFC0& (голубой цвет). А затем с помощью мастера создадим "болванку" (не забыли как это делается?). Для BackColor определим свойство BackColor от UserControl'a, а остальные свойства наберем согласно приведенной табличке:

Name

Type

Default Value

Max

Long

100

Min

Long

0

Value

Long

0

Percent

String

vbNullString

BasisColor

OLE_COLOR

&HFF0000

SandColor

OLE_COLOR

&H80FF&

Откроем лист кодов и посмотрим, что у нас получилось. Из процедуры UserControl_WriteProperties смело удаляем строку, касающуюся Percent (у нас ведь свойство только для чтения). А Property Get Percent изменим следующим образом:

Percent = Format((m_Value - m_Min) * 100 / (m_Max - m_Min), "0") & "%"

NB! Функция Format используется для округления числа до целого, а вычитание m_Min производится для тех случаев, когда минимальное значение, устанавливаемое пользователем/программистом, не равно нулю.

Теперь напишем основную процедуру нашего контрола - DrawControl, которая и будет рисовать как сам ProgressBar, так и движение процесса.

Private Sub DrawControl()

'очищаем контрол от предыдущей графики

Cls

'напоминаем установки контрола

ScaleMode = 3 ' пикселы

DrawWidth = 2 ' толщина рисуемых линий

DrawStyle = 6 ' Inside Solid

AutoRedraw = True ' автоперерисовка контрола

'рисуем песок

If m_Value <> m_Max Then

'верхняя часть песочных часов. ScaleHeight умножаем на 0.5 т.к. используем только половину контрола.

'Рисуем прямоугольник, контрол-то уже вырезан.

Line (0, (m_Value - m_Min) * ScaleHeight * 0.5 / _

(m_Max - m_Min))-(ScaleWidth, ScaleHeight * 0.5), m_SandColor, BF

'струя песка.

Line (ScaleWidth * 0.45, ScaleHeight * 0.5)-(ScaleWidth * 0.54, ScaleHeight * 0.95), m_SandColor, BF

'нижняя часть

Line (0, ScaleHeight - ((m_Value - m_Min) * ScaleHeight * 0.5 / _

(m_Max - m_Min)))-(ScaleWidth, ScaleHeight * 0.95), m_SandColor, BF

End If

'рисуем верх и низ базисным цветом

Line (0, 0)-(ScaleWidth, ScaleHeight * 0.05), m_BasisColor, BF

Line (0, ScaleHeight * 0.95)-(ScaleWidth, ScaleHeight), m_BasisColor, BF

'окантовка так же базисным цветом. Окантовка проходит по тем же точкам, что и вырезался контрол

Line (ScaleWidth, 0)-(ScaleWidth, ScaleHeight * 0.1), m_BasisColor

Line -(ScaleWidth * 0.9, ScaleHeight * 0.25), m_BasisColor

Line -(ScaleWidth * 0.7, ScaleHeight * 0.45), m_BasisColor

'… ну и так далее по всем точкам.

'обновляем

Refresh

End Sub

Раз у нас все изменения завязаны на процедуру DrawControl, то добавим ee в Property Let каждого свойства последней строкой. Добавим ее так же и в UserControl_Resize.

NB! Имя Property, которое описывается первым в окне кодов - будет первым выделяться в окне свойств при попадании фокуса на контрол во время разработки. Поэтому давайте переместим Property Let и Property Get свойства Value перед другими свойствами в окне кодов.

Закончив с написанием кодов, займемся "уборкой в квартире", т.е переходим к заключительному третьему шагу создания ActiveX Control'a. Напишем комментарии к созданным нами свойствам, установим свойство Value как Default (не забыли? меню Tools/Procedure Attributes… кнопка Advanced и в поле Procedure ID выберем опцию (Default)). Создадим frmAbout, добавим в окно кодов

Public Sub About()

frmAbout.Show vbModal

End Sub

и все в том же Tools/Procedure Attributes… --> кнопка Advanced --> поле Procedure ID устанавливаем опцию AboutBox.

"Аппетит приходит во время еды!" AboutBox с Вашей фамилией автора - это, конечно, ласкает самолюбие, но… Вот в других контролах есть такая опция (Custom), нажимаешь ее и появляется окошко с закладками, а там сразу все твои свойства. Удобно? - Удобно! Сделаем? А почему бы и нет. Показываю как это сделать проще всего. Меню Add-Ins/Add-In Manager…Выбираем Property Page Wizard. Открываем его. Мастер у нас умный, поэтому, прочитав, что есть свойства As OLE_COLOR, он сразу же предлагает стандартную страничку по цветам StandartColor. Пометим ее CheckBox. А теперь создадим свою страничку. Нажмем кнопку Add и в диалоговом окне введем свое название.

NB! Название не должно совпадать с именем контрола или проекта и должно состоять из одного слова. Позже, открыв Property Page, в свойстве Caption, мы сможем задать любое другое название, которое захотим увидеть в названии ярлыка.

Поэтому дадим ему что-то нейтральное типа General, или как в данном случае можно назвать ProgressBar. ОК! Так же пометим его и с помощью кнопок слева поднимем в первую строку списка.

NB! Перемещать странички мы можем и позже. Для этого выбирается в окне свойств UserControl'a свойство PropertyPages. Там же Вы сможете ознакомиться, какие еще стандартные странички предлагает нам VB.

В следующем шаге выберем наши свойства и поместим их в правое окно под ярлыком ProgressBar. Кстати, если щелкнуть на ярлыке StandartColor то увидим, что наши свойства, завязанные на цвет - уже там.

Кнопка Finish. В окне проектов появилась новая папка Property Pages, а в ней наша страничка ProgressBar. Откройте ее и исследуйте, я думаю на будущее это Вам пригодится.

Теперь самое время создать тестировочный проект, чтобы посмотреть, что у нас получилось (Это в статье - когда автор рассказывает об уже созданных и отработанных свойствах и методах. В жизни же, обычно, тестировочный проект создается гораздо раньше, для проверки работоспособности отдельных блоков). Добавляем проект Standart EXE, называем его prjTest, переименовываем форму в frmTest. Разместим на форме наш ActiveX Control, Label с именем lblPercent и командную кнопку Command1. Теперь осталось придумать, чем бы занять наш ProgressBar. Допустим, это будет цикл перебора значений. Запишем код:

' делаем их невидимыми - пока нет для них работы.

Private Sub Form_Load()

pbHrglss1.Visible = False

lblPercent.Visible = False

End Sub

 

Private Sub Command1_Click()

Dim i&

With pbHrglss1

' устанавливаем значения (эти 2 строки можно не писать, а просто установить их в окне свойств)

.Min = 0

.Max = 300

' делаем видимыми

.Visible = True

lblPercent.Visible = True

' запускаем цикл

For i = .Min To .Max

.Value = i

lblPercent.Caption = .Percent

DoEvents ' для обеспечения доступа к программе, например, работа кнопки отмена процесса

Next

Beep ' сигнал об окончании цикла

' снова делаем невидимыми - работа окончена

.Visible = False

lblPercent.Visible = False

End With

End Sub

Протестируем. Работает! Ну и напоследок еще одна "мелочевка". Поиграем с окном свойств для нашего контрола. Откроем frmTest, выделим pbHrglss1, и в окне свойств по очереди будем выбирать: (About) - работает!, (Custom) - замечательно!, BackColor - как и положено выпадает цветное меню, Max … Стоп! Хотели ввести цифры, а выходит все равно (Custom). Аналогичная ситуация и с Min и с Value. Давайте поправим. Закрываем форму, открываем pbHrglss и снова в меню Tools/Procedure Attributes… --> кнопка Advanced. В поле Name выбираем Max и что же мы видим? Наш Property Page Wizard слегка перестарался: в поле Use this Page in Property Browser он, по умолчанию, установил ProgressBar. Снимем эту опцию и установим (None). Аналогичную операцию проведем для свойств Min и Value. Вернемся в frmTest и попробуем снова. Вот теперь порядок.

Можно компилировать наш ActiveX Control. Для желающих: увеличив количество точек, по которым вырезается контрол, Вы можете сделать его более изящным за счет плавности линий.

Как всегда в конце статьи полный листинг.

Скачать пример

Назад

1999 г

Hosted by uCoz