Разные мелочи, которые при создании ActiveX Control'ов мы обычно забываем.
На что смотрит в первую очередь программист, изучая новый контрол. На функциональность, т.е. насколько он удовлетворяет его требованиям. Во-вторых, на внешний вид — насколько данный контрол будет вписываться в его программу. В-третьих, насколько ему удобно работать с ним. И в последнюю очередь — на help :-). Попробуем сегодня, создавая несложный контрол, предоставить максисмум удобств для нашего будущего программиста, тем более VB позволяет это сделать самыми различными способами.
Контрол данного урока — это линейка с истинным (а не экранным) выводом значений измерения. Создадим проект, назовем его Rulers. Сам контрол переименуем в Ruler. Определимся со свойствами:
Имя |
Описание |
Тип |
Значение по умолчанию |
BackColor |
Цвет фона |
OLE_COLOR |
&H80000005 |
Font |
Шрифт |
Font |
MS Sans Serif, 8 |
ForeColor |
Цвет надписей |
OLE_COLOR |
&H0& |
Measurement |
Система измерения |
const Measurement |
0 |
Orientation |
Ориентация линейки |
constOrientation |
0 |
События используем стандартные: Click, DblClick, MouseDown, MouseMove, MouseUp.
Используем API-функцию GetDeviceCaps. Здесь же привожу полный перечень констант для этой функции и за что они отвечают. В самой программе мы будем использовать только две константы LOGPIXELSX и LOGPIXELSY.
Private Const DRIVERVERSION = 0
' версия
драйвера
устройства
Private Const TECHNOLOGY = 2 '
класс
устройства
Private Const HORZSIZE
= 4 ' горизонтальный
размер в миллиметрах
Private Const VERTSIZE
= 6 ' вертикальный
размер в миллиметрах
Private Const HORZRES
= 8 ' горизонтальный
размер в пикселях
Private Const VERTRES
= 10 ' вертикальный
размер в
линиях
растра
Private Const BITSPIXEL
= 12 ' число бит на
пиксель
Private Const PLANES = 14
' число
слоев
Private Const NUMBRUSHES = 16 ' число
кистей
Private Const NUMPENS = 18
' число
перьев
Private Const NUMMARKERS = 20 ' число
маркеров
Private Const NUMFONTS = 22
' число
шрифтов
Private Const NUMCOLORS
= 24 ' число
поддерживаемых
цветов
Private Const PDEVICESIZE
= 26 ' размер,
требуемый
под
описатель
устройства
Private Const CURVECAPS
= 28 ' возможности
рисования
дуг
Private Const LINECAPS
= 30 ' возможности
рисования
линий
Private Const POLYGONALCAPS
= 32 ' возможности
рисования
многоугольников
Private Const TEXTCAPS
= 34 ' возможности
вывода
текста
Private Const CLIPCAPS
= 36 ' возможности
вырезания
части
изображения
Private Const RASTERCAPS
= 38 ' возможности
пересылки
строки битов
Private Const ASPECTX
= 40 ' относительная
ширина пикселя
Private Const ASPECTY
= 42 ' относительная
высота линии
растра
Private Const ASPECTXY
= 44 ' относительная
диагональ пикселя
Private Const LOGPIXELSX
= 88 ' число
пикселей на
дюйм по
горизонтали
Private Const LOGPIXELSY
= 90 ' число линий
растра на
дюйм по
вертикали
Private Const SIZEPALETTE
= 104 ' число
входов на
физическую
палитру
Private Const NUMRESERVED
= 106 ' число
зарезервированных
входов в
палитре
Private Const COLORRES
= 108 ' действительная
цветная
разрешающая
способность
Создаем два энума для наших свойств:
Public Enum constMeasurement
сантиметры =
0
дюймы
= 1
End Enum
Public Enum constOrientation
горизонтальный
= 0
вертикальный
= 1
End Enum
Теперь напишем процедуру, которая, за все отвечает, а затем обязательно введем ее в Property Let каждого свойства, а также в UserControl_Resize и UserControl_Show.
Private Sub ShowRuler()
Dim inch, cm, i%, countmark%, extent%, mark%, whole%, Measur As constMeasurement
Dim OrientX&, OrientY&, LogPixelsXY
‘очистка контрола перед перерисовкой
Cls
‘в зависимости от ориентации контрола присваиваем переменным ширину и высоту контрола
Select Case m_Orientation
Case 0
OrientX = ScaleWidth
OrientY = ScaleHeight
LogPixelsXY =
LOGPIXELSX
Case 1
OrientX = ScaleHeight
OrientY = ScaleWidth
LogPixelsXY =
LOGPIXELSY
End Select
‘определяем
количество
дюймов
inch = GetDeviceCaps(UserControl.hdc, LogPixelsXY)
‘перевод
в сантиметры
cm = inch / 2.54
Select Case m_Measurement
Case 0
Measur = cm
Case 1
Measur = inch
End Select
For i = 0 To OrientX Step (Measur / 10)
Select Case True
Case countmark / 10 =
Int(countmark / 10) ‘Засечки
между целыми
значениями
дюймов/см
extent
= OrientY
/ 7 * 4 ‘ пропорции
высоты 4/7, 3/7 и 2/7
получены
опытным
путем
mark
= 1
Case countmark
/ 5 = Int(countmark
/ 5) ‘Засечки
между
половинными
значениями
extent
= OrientY / 7 * 3
Case Else ‘Засечки
через каждый
мм
extent
= OrientY / 7 * 2
End Select
‘производится
изменение
цвета
засечек и
цифр
UserControl.ForeColor
= m_ForeColor
‘В
зависимости
от
ориентации
рисуем
засечки
Select Case
m_Orientation
Case 0
Line (i, OrientY)-(i,
OrientY - extent), m_ForeColor
If mark
= 1 Then ‘ если
целое
значение
сантиметров/дюймов
– выводим
цифру
‘
определяем
точку вывода
CurrentX
= CurrentX
- 7
CurrentY
= CurrentY - 15
If whole > 0 Then Print whole ‘ если
не 0, то цифру
печатаем
whole
= whole + 1
End If
Case 1
Line (OrientY, i)-(OrientY
- extent, i), m_ForeColor
If mark = 1 Then
CurrentX
= CurrentX - 15
CurrentY
= CurrentY - 7
If
whole > 0 Then Print whole
whole
= whole + 1
End If
End Select
countmark = countmark + 1
mark = 0
Next
End Sub
Создаем тестировочную форму и выводим наш контрол. Ерунда получается. Значит мы должны вернуться к окну свойств нашего контрола и устанавливаем свойство ScaleMode =3 (Pixel) – так как API-функции работают только с пикселами. Ну вот, это другой разговор. Свернем форму, а затем снова развернем – если все надписи исчезли – значит мы забыли установить AutoRedraw в True.
Не выходя из окна, поднимемся вверх и изменим свойство Alignable на True. Вернемся в тестировочную форму и увидим, что у нашего контрола так же появилось новое свойство Align c пятью вариантами выбора, отвечающее за расположение контрола на форме.
Щелкнем правой клавишей на нашей линейке-контроле. Появляется контекстное меню. Меню как меню, без каких-либо особенностей. Вернемся в окно свойств и выберем свойство PropertyPage. В диалоговом окне отметим страницы, отвечающие за передачу цвета и шрифта, и вернемся на тестировочную форму. Повторим щелчок правой клавиши мыши. В самом низу контекстного меню у нас добавляется строка Properties, по которой вызывается тоже самое диалоговое окно, что и в окне свойств по (Custom). Честно говоря, на данном контроле я не смог придумать какие-либо возможности, позволяющие проводить редактирование — уж больно он простой :-). Однако на будущее, для такой ситуации Вы можете использовать свойство UserControl с именем EditAtDisignTime (установите его в True). И в контекстном меню на тестировочной форме появится новая строка — Edit, которая и позволит Вам проводить редактирование непосредственно на самом конроле.
NB! Дальнейшие строки специально выделены красным. Все что в них описано необходимо будет потом удалить, т.к. они служат примером, который не имеет отношения к нашему контролу.
Разместим на нашем контроле, ну допустим TextBox. Установим свойство контрола EditAtDesignTime = True. Перейдем в тестировочную форму. Как бы мы не старались, напрямую к текстовому блоку – обратиться не можем. Только создав сойство Text и завязав его на свойство Text от TextBox, мы выходим на него через окно свойств. Щелкнем правой клавишей на нашем контроле, выберем меню Edit. Сразу же получаем доступ к свойству Text: можем отредактировать его или вообще удалить, при этом автоматически изменения будут копироваться в свойство Text контрола.
Не забудьте соответствующим образом оформить подписи к свойствам, методам и событиям контрола. Как это делается вы, наверное, помните: меню Tools/ProcedureAttributes…, нажмите кнопку Advanced. Для тех программистов, которые пользуются в окне свойств ярлыком Categorized, обязательно укажем созданные нами свойства в окне Property Category. Если Вы обратили внимание, по умолчанию предоставляется десять основных рубрик плюс одна (None). И если Вы не указали к какой группе данное свойство относится, то VB самостоятельно распределит его в одну из этих групп, чаще всего в Misс. Ну, а если мы захотим чтобы все наши свойства были сгруппированы в одном месте, то давайте напишем в этом поле свое название, например как у нас Ruler. Перейдя в окно свойств и щелкнув на ярлыке Categorized, мы увидим, что все наши свойства сгруппированы в единый блок Ruler.
ActiveX Control – закончен, мелочи предусмотрены. Осталось написать Help. Да, я знаю, что это самое нелюбимое занятие у программистов, но … здесь есть один плюс. Контрол – програмка-то ма-а-аленькая, значит и хелп будет небольшой. С помощью любого редактора хелп-файлов создайте для своего ActiveX Control’а помощь. Выберите меню Project/Rulers Properties … и в поле Help File Name введите имя хелп-файла, а в поле Project Help Context ID – индексный номер стартовой страницы. Снова вернемся в меню Tools/ProcedureAttributes… В поле Project Help File Вы увидите имя своего файла. Теперь Вам осталось проставить индексы страниц в поле Help Context ID, соответствующих Вашим свойствам, событиям и методам.
Работаем!
Кто не до конца разобрался непосредственно с контролом - сюда за листингом.
1999