Visual Basic, .NET, ASP, VBScript
 

   
 

Михаил Эскин немало сделал для развития русскоязычных VB сайтов. Многие знают его по статьям про ActiveX на VB сайтах, другие читают статьи Михаила уже на его собственном сайте. Михаил родился в Городском роддоме №1 города Астрахани, в “черную пятницу”, ну, так скажем, почти сорок лет назад. По-прежнему живет на Юге, правда теперь уже Германии, в прекрасном городе Мюнхене.

 
     
   
 

    Мир ActiveX Control'ов многолик и многообразен. Встречаются совершенно различные по внешнему виду (и даже без него) и по внутреннему содержанию. Одни используют для построения стандартные ActiveX Control'ы, другие предпочитают создавать "с нуля". Одни контролы облегчают коммуникацию, другие производят внутри себя сложные вычисления, выдавая "на-гора" уже готовый результат, а третьи служат просто для украшения программы.

    ActiveX Control'ы - это программы в программе. И, завершив создание его, получаешь удовлетворение нисколько не меньшее, чем завершив большой проект. Мы садимся писать контролы, когда хотим облегчить себе работу в будущем, просто используя готовый интерфейс и набор свойств, событий и методов. В большинстве случаев, начало создания контрола является спонтанным событием. Просто-напросто замечаешь, что в программе появляется два-три куска идентичных кодов, завязанных на интерфейс. И тогда, выделяешь их в отдельный контрол, попутно наделив дополнительными свойствами и методами (на будущее).

    К созданию нынешнего ActiveX Control'а меня подтолкнул Д.Соловьев. Он создает программу, завязанную на проверку знаний иностранных слов. Причем в одном месте, выводить эти слова необходимо с выделением окончания. Однако, как оказалось, ни Label, ни TextBox не позволяют производить разбивку слова по цветам или шрифтам. Эрзац-решением стало использование для этой цели RichTextBox'а. Однако идея уже "проклюнулась", и был создан контрол SelTextEx. Его интересной особенностью является использование в методе, выводящим текст, массива пользовательского типа.

    Итак, создайте новый проект ActiveX Control. Назовем его SelectedTextEx. Созданный по умолчанию UserControl переименуем в SelTextEx. Кроме того установим свойство AutoRedraw = True. Размеры уменьшите до разумных :)

Неплохо сразу же добавить проект для тестирования (названия на Ваше усмотрения). 

    С помощью ActiveX Control Interface Wizard создадим "болванку", включив всего одно собственное свойство - Caption. Данное свойство будет несколько отличаться от аналогичных у других контролов тем, что оно не будет непосредственно выводить свое значение, а будет являться как бы его хранилищем. (Тип, естественно, String; значение по умолчанию - "SelTextEx").

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

Public Type SText
    Start As Integer
    Font As StdFont
    ForeColor As OLE_COLOR
End Type 

    Все основные "интриги" начинаются с метода, руководящего печатью разноцветной и разнофонтовой надписи на нашем контроле. Назовем его SelectedPart. И в качестве передаваемого параметра используем динамический массив пользовательского типа

Public Sub SelectPart(CountEx() As SText)

Для начала очистим контрол от предыдущей графики методом Cls.

Cls

    А затем в цикле For ... Next произведем все необходимые нам настройки шрифта для каждой из объявленных нами закрашиваемых частей

For i = LBound(CountEx) To UBound(CountEx)

    Здесь мы должны будем высчитать с какой частью слова будем работать и сбросить ее во внутреннюю переменную. Однако перед этим, сделаем "маленькое значение по умолчанию", т.е. если мы прямо не укажем значение Start, то будем считать, что это начало слова, следовательно оно будет равно единице. Длину же выделяемой части будем высчитывать из стартовой позиции следующей выделяемой части. Однако, если эта часть последняя, то присвоим ей длину всего слова (свойства Caption), тем самым страхуя себя на случай, если выделений не будет вовсе.

If CountEx(i).Start = 0 Then CountEx(i).Start = 1
If i = UBound(CountEx) Then
    txt = Mid(m_Caption, CountEx(i).Start, Len(m_Caption))
Else
    txt = Mid(m_Caption, CountEx(i).Start, CountEx(i + 1).Start - CountEx(i).Start)
End If

    Далее займемся шрифтом. Здесь также необходимо сделать проверку на значение по умолчанию. И если мы явно не объявили шрифт, то присвоим его текущим значениям UserControl'а. Ну а дальше инициализируем объект Font.

If CountEx(i).Font Is Nothing Then
    Set CountEx(i).Font = UserControl.Font
End If
Set Font = CountEx(i).Font

NB! Мы можем так же присвоить значение по умолчанию свойству Font, того контейнера, где лежит наш контрол. В этом случае это будет выглядеть так:

Set CountEx(i).Font = Ambient.Font 

NB! Работая с Font, мы объявляем его с ключевым словом Set, т.к. он является объектом.

    Последнее из оставшегося в типе это ForeColor. Значения по умолчанию ему устанавливать не будем, т.к. если мы явно его не укажем, ему будет присвоено значение 0, что всегда соответствует черному цвету.

ForeColor = CountEx(i).ForeColor

Ну а теперь непосредственно печатаем, обработанную нами часть слова

Print txt;

NB! Точка с запятой в конце позволяют "дописывать" в конец напечатанному следующие части слова, а не переносят печать на новую строку.

    Теперь самое время заняться тестированием. Добавьте новый проект (если Вы этого еще не сделали) и разместите на форме наш контрол и 2 кнопки. Первая будет выводить текст, с предварительной инициализацией всех свойств "по полной программе", а вторая - используя только самые необходимые их изменения. При инициализации Font не забудьте использовать ключевое слово Set.

Загрузить пример к статье.

 
     

   
   
     
  VBNet рекомендует