InfoCity
InfoCity - виртуальный город компьютерной документации
Реклама на сайте







Размещение сквозной ссылки

 

Как создать свой ActiveX Control
часть четвертая - создаем сложный контрол


Михаил Эскин 


Начиная первую статью на эту тему, никак не ожидал, что изучение создания ActiveX Control'ов настолько актуально. Продолжая отвечать на письма, вынужден констатировать, что некоторые вопросы остались вне поля зрения. Настоящая (уже четвертая) статья и послужит для их освещения.

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

Сегодня мы будем создавать 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, 0)

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

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") & "%"

Маленькое пояснение: функция 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! Название не должно совпадать с именем контрола или проекта и должно состоять из одного слова.

Поэтому дадим ему что-то нейтральное типа 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.

 

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

[Назад][Содержание][Вперед]


Реклама на InfoCity

Яндекс цитирования



Финансы: форекс для тебя








1999-2009 © InfoCity.kiev.ua