Текст книги "Программирование мобильных устройств на платформе .NET Compact Framework"
Автор книги: Иво Салмре
Жанр:
Программирование
сообщить о нарушении
Текущая страница: 66 (всего у книги 69 страниц)
End If
Return s_bluePen
End Get
End Property
'========================================================
'Подход 2:
'Загрузить глобально и кэшировать все
'используемые объекты Pen, ImageAttribute, Font и Brush
'
'Внешний код получает доступ ко всем общедоступным членам,
'так что никакие функции доступа не нужны.
'=========================================================
Public Shared g_blackPen As Pen
Public Shared g_whitePen As Pen
Public Shared g_ImageAttribute As Imaging.ImageAttributes
Private Shared s_alreadyInitialized As Boolean
Public Shared g_boldFont As Font
Public Shared g_smallTextFont As Font
Public Shared g_greenBrush As Brush
Public Shared g_yellowBrush As Brush
Public Shared g_redBrush As Brush
Public Shared g_blackBrush As Brush
'==============================================================
'Эта функция должна быть вызвана до попыток доступа к любому из
'вышеперечисленных глобальных объектов
'==============================================================
Public Shared Sub InitializeGlobals()
If (s_alreadyInitialized = True) Then Return
g_blackPen = New Systera.Drawing.Pen(Color.Black)
g_whitePen = New System.Drawing.Pen(Color.White)
g_ImageAttribute = New _
System.Drawing.Imaging.ImageAttributes
g_ImageAttribute.SetColorKey(Color.White, Color.White)
g_boldFont = New Font(FontFamily.GenericSerif, _
10, FontStyle.Bold)
g_smallTextFont = New Font(FontFamily.GenericSansSerif, _
8, FontStyle.Regular)
g_blackBrush = New SolidBrush(System.Drawing.Color.Black)
g_greenBrush = New SolidBrush(System.Drawing.Color.LightGreen)
g_yellowBrush = New SolidBrush(System.Drawing.Color.Yellow)
g_redBrush = New SolidBrush(System.Drawing.Color.Red)
s_alreadyInitialized = True
End Sub
'====================================================
'Подход 3: Возвратить массив связанных ресурсов.
' Кэшировать ресурсы локально, чтобы при многократных
' запросах не загружались (напрасно) их дубликаты
'====================================================
Private Shared m_CaveMan_Bitmap1 As Bitmap
Private Shared m_CaveMan_Bitmap2 As Bitmap
Private Shared m_CaveMan_Bitmap3 As Bitmap
Private Shared m_CaveMan_Bitmap4 As Bitmap
Private Shared m_colCaveManBitmaps As _
System.Collections.ArrayList
'–
'Создать и загрузить массив изображений для спрайта
'–
Public Shared Function g_CaveManPictureCollection() As _
System.Collections.ArrayList
'Изображения загружаются лишь в том случае, если мы их еще не загрузили
If (m_CaveManBitmap1 Is Nothing) Then
'–
'Загрузить изображения. Эти изображения хранятся в виде
'встроенных ресурсов в нашем двоичном приложении
'
'Загрузка изображений из внешних файлов осуществляется аналогичным
'образом, но выполнить ее проще (нам достаточно лишь указать
'имя файла в конструкторе растровых изображений).
'–
'Получить ссылку на нашу двоичную сборку
dim thisAssembly as System.Reflection.Assembly = _
System.Reflection.Assembly.GetExecutingAssembly()
'Получить имя сборки
Dim thisAssemblyName As System.Reflection.AssemblyName = _
thisAssembly.GetName()
Dim assemblyName As String = thisAssemblyName.Name
'Загрузить изображения в виде двоичных потоков из нашей сборки
m_CaveMan_Bitmap1 = New System.Drawing.Bitmap( _
thisAssembly.GetManifestResourceStream( _
assemblyName + ".Hank_RightRun1.bmp"))
m_CaveMan_Bitmap2 = New System.Drawing.Bitmap( _
thisAssembly.GetManifestResourceStream( _
assemblyName + ".Hank_RightRun2.bmp"))
m_CaveMan_Bitmap3 = New System.Drawing.Bitmap( _
thisAssembly.GetManifestResourceStream( _
assemblyName + ".Hank_LeftRunl.bmp"))
m_CaveMan_Bitmap4 = New System.Drawing.Bitmap( _
thisAssembly.GetManifestResourceStream( _
assemblyName + ".Hank_LeftRun2.bmp"))
'Добавить их в коллекцию
m_colCaveManBitmaps = New System.Collections.ArrayList
m_colCaveManBitmaps.Add(m_CaveMan_Bitmap1)
m_colCaveManBitmaps.Add(m_CaveMan_Bitmap2)
m_colCaveManBitmaps.Add(m_CaveMan_Bitmap3)
m_colCaveManBitmaps.Add(m_CaveMan_Bitmap4)
End If
'Возвратить коллекцию
Return m_colCaveManBitmaps
End Function
End Class
Примеры к главе 13 (проектирование пользовательского интерфейса)
Листинг 13.1. Использование конечного автомата для экспериментов с двумя различными вариантами компоновки пользовательского интерфейса
#Const PLAYFIELD_ON_BOTTOM = 0 'Отобразить ПОЛЕ ИГРЫ под ПИ
'#Const PLAYFIELD_ON_BOTTOM = 1 'Отобразить ПОЛЕ ИГРЫ над ПИ
'–
'ОБРАБОТЧИК СОБЫТИЙ: Вызывается при загрузке формы
'–
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
'Задать совместно используемые свойства нашего визуального интерфейса
SetStartControlPositionAndState()
'Задать динамические свойства, исходя из того, в какое состояние
'игры мы входим
StateChangeForGameUI(GameUIState.startScreen)
End Sub
'–
'Конечный автомат, который управляет отображением кнопок, скрываемых вручную
'–
Private Enum GameUIState
startScreen = 1
waitForNextQuestion = 2
waitForUserToStateKnowledge = 4
waitForUserToAnswerMultipleChoice = 8
End Enum
'Текущее состояние игры
Private m_GameUIState As GameUIState
'==========================================================================
'Конечный автомат, используемый для управления пользовательским интерфейсом
'==========================================================================
Private Sub StateChangeForGameUI(ByVal newGameUIState As _
GameUIState)
m_GameUIState = newGameUIState
Select Case (newGameUIState)
Case GameUIState.startScreen
buttonAskQuestion.Visible = True
buttonAskQuestion.Text = "Start"
'Скрыть текстовое окно
textBoxAskQuestion.Visible = False
SetAnswerButtonVisibility(False)
SetDifficultyButtonVisibility(False)
Case GameUIState.waitForNextQuestion
setQuestionText("List answer details here... " + vbCrLf + _
"Lots of space to write..." + vbCrLf + _
"Waiting for user to select next question...")
textBoxAskQuestion.Visible = True
buttonAskQuestion.Text = "Next"
buttonAskQuestion.Visible = True
'Убедиться в том, что кнопка отображается на переднем плане
buttonAskQuestion.BringToFront()
SetAnswerButtonVisibility(False)
SetDifficultyButtonVisibility(False)
#If PLAYFIELD_ON_BOTTOM <> 0 Then 'ПОЛЕ ИГРЫ располагается под ПИ
textBoxAskQuestion.Height = pictureBoxGameBoard.Top – 2
#Else 'ПОЛЕ ИГРЫ располагается над пользовательскими элементами управления
textBoxAskQuestion.Top = pictureBoxGameBoard.Top + _
pictureBoxGameBoard.Height + 2
textBoxAskQuestion.Height = Me.Height – _
textBoxAskQuestion.Top
#End If
Case GameUIState.waitForUserToStateKnowledge
SetTextForVocabularyQuestion()
textBoxAskQuestion.Visible = True
buttonAskQuestion.Visible = False
SetAnswerButtonVisibility(False)
SetDifficultyButtonVisibility(True)
#If PLAYFIELD_ON_BOTTOM <> 0 Then 'ПОЛЕ ИГРЫ располагается под ПИ
textBoxAskQuestion.Height = _
buttonShowAnswers_AdvancedVersion.Top – 2
#Else 'ПОЛЕ ИГРЫ располагается над пользовательскими элементами управления
textBoxAskQuestion.Top = _
buttonShowAnswers_AdvancedVersion.Top + _
buttonShowAnswers_AdvancedVersion.Height + 2
textBoxAskQuestion.Height = Me.Height – _
textBoxAskQuestion.Top
#End If
Case GameUIState.waitForUserToAnswerMultipleChoice
buttonAskQuestion.Visible = False
SetDifficultyButtonVisibility(False)
'Сделать кнопки доступными, чтобы пользователь мог щелкать на них
SetAnswerButtonEnabled(True)
SetAnswerButtonVisibility(True)
#If PLAYFIELD_ON_BOTTOM <> 0 Then
'ПОЛЕ ИГРЫ располагается под ПИ
textBoxAskQuestion.Height = buttonAnswer0.Top – 2
#Else 'ПОЛЕ ИГРЫ располагается над пользовательскими элементами управления
'Разместить текстовое окно таким образом, чтобы экран использовался
'эффективно
textBoxAskQuestion.Top = buttonAnswer5.Top + _
buttonAnswer5.Height + 2
textBoxAskQuestion.Height = Me.Height – _
textBoxAskQuestion.Top
#End If
End Select
End Sub
'========================================================================
'Задать статическую компоновку нашего пользовательского интерфейса.
'Сюда входят все элементы, позиции которых остаются фиксированными.
'Изменения в остальные свойства внесет конечный автомат пользовательского
'интерфейса
'========================================================================
Private Sub SetStartControlPositionAndState()
pictureBoxGameBoard.Width = 240
pictureBoxGameBoard.Height = 176
'Установить размеры кнопок множественного выбора вариантов ответов
Const answerButtons_dx As Integer = 117
Const answerButtons_dy As Integer = 18
buttonAnswer0.Width = answerButtons_dx
buttonAnswer0.Height = answerButtons_dy
buttonAnswer1.Size = buttonAnswer0.Size
buttonAnswer2.Size = buttonAnswer0.Size
buttonAnswer3.Size = buttonAnswer0.Size
buttonAnswer4.Size = buttonAnswer0.Size
buttonAnswer5.Size = buttonAnswer0.Size
buttonShowAnswers_AdvancedVersion.Width = answerButtons_dx
buttonShowAnswers_AdvancedVersion.Height = 24
buttonShowAnswers_SimpleVersion.Size = _
buttonShowAnswers_AdvancedVersion.Size
'Расстояние (в пикселях) между соседними кнопками
Const dx_betweenButtons As Integer = 3
Const dy betweenButtons As Integer = 2
Const answerbuttons_beginX As Integer = 3
'Создать задний план для нашего изображения, чтобы мы видели
'его в процессе тестирования
Dim gameBoard As System.Drawing.Bitmap
gameBoard = New System.Drawing.Bitmap( _
pictureBoxGameBoard.Width, pictureBoxGameBoard.Height)
Dim gameboard_gfx As System.Drawing.Graphics
gameboard_gfx = System.Drawing.Graphics.FromImage(gameBoard)
gameboard_gfx.Clear(System.Drawing.Color.Yellow)
Dim myPen As System.Drawing.Pen = New System.Drawing.Pen( _
System.Drawing.Color.Blue)
gameboard_gfx.DrawRectangle(myPen, 2, 2, _
gameBoard.Width – 4, gameBoard.Height – 6)
myPen.Dispose()
gameboard_gfx.Dispose()
pictureBoxGameBoard.Image = gameBoard
'Разместить текстовое окно, в котором содержатся задаваемые вопросы,
'а также подробные ответы для пользователей
textBoxAskQuestion.Left = 0
textBoxAskQuestion.Width = 240
buttonAskQuestion.Width = 64
buttonAskQuestion.Height = 20
#If PLAYFIELD_ON_BOTTOM <> 0 Then 'ПОЛЕ ИГРЫ располагается под ПИ
Const answerbuttons_beginY As Integer = 42
Const showanswers_beginY As Integer = 77
'–
'Задать кнопки выбора вариантов "Easy" или "Hard" режима игры
'–
buttonShowAnswers_AdvancedVersion.Top = showanswers_beginY
buttonShowAnswers_SimpleVersion.Top = showanswers_beginY
'–
'Задать набор вариантов ответов
'–
'Задать элемент управления, по которому будут выравниваться
'все остальные элементы управления
buttonAnswer0.Top = answerbuttons_beginY
'Поместить PictureBox под элементами управления
pictureBoxGameBoard.Top = _
(answerButtons dy + dy betweenButtons) * 3 + _
answerbuttons_beginY
buttonAskQuestion.Top = 0
buttonAskQuestion.Left = 174
textBoxAskQuestion.Top = 0
#Else 'ПОЛЕ ИГРЫ располагается над пользовательскими элементами управления
Const answerbuttons_beginY As Integer = 174
'–
'Задать кнопки выбора вариантов "Easy" или "Hard" режима игры
'–
buttonShowAnswers_AdvancedVersion.Top = answerbuttons_beginY
buttonShowAnswers_SimpleVersion.Top = answerbuttons_beginY
'–
'Задать набор вариантов ответа
'–
'Задать элемент управления, по которому будут выравниваться
'все остальные элементы управления
buttonAnswer0.Top = answerbuttons_beginY
pictureBoxGameBoard.Top = 0
buttonAskQuestion.Top = answerbuttons_beginY
buttonAskQuestion.Left = 174
#End If
buttonShowAnswers AdvancedVersion.Left = answerbuttons_beginX
buttonShowAnswers_SimpleVersion.Left = _
buttonShowAnswers_AdvancedVersion.Left + _
answerButtons dx + dx_betweenButtons
pictureBoxGameBoard.Left = 0
pictureBoxGameBoard.Width = 240
pictureBoxGameBoard.Height = 172
buttonAnswer0.Left = answerbuttons_beginX
buttonAnswer1.Left = buttonAnswer0.Left + answerButtons_dx + _
dx_betweenButtons
buttonAnswer1.Top = buttonAnswer0.Top
'Следующий ряд
buttonAnswer2.Left = buttonAnswer0.Left
buttonAnswer2.Top = buttonAnswer0.Top + answerButtons_dy + _
dy_betweenButtons
buttonAnswer3.Left = buttonAnswer2.Left + answerButtons_dx + _
dx_betweenButtons
buttonAnswer3.Top = buttonAnswer2.Top
'Следующий ряд
buttonAnswer4.Left = buttonAnswer2.Left
buttonAnswer4.Top = buttonAnswer2.Top + answerButtons_dy + _
dy_betweenButtons
buttonAnswer5.Left = buttonAnswer4.Left + answerButtons_dx + _
dx_betweenButtons
buttonAnswer5.Top = buttonAnswer4.Top
End Sub
'–
'Вспомогательная функция, которая позволяет задавать состояние видимости
'кнопок, отображающих ответы из словаря
'–
Private Sub SetAnswerButtonVisibility(ByVal visibleState _
As Boolean)
buttonAnswer0.Visible = visibleState
buttonAnswer1.Visible = visibleState
buttonAnswer2.Visible = visibleState
buttonAnswer3.Visible = visibleState
buttonAnswer4.Visible = visibleState
buttonAnswer5.Visible = visibleState
End Sub
'–
'Вспомогательная функция, вызываемая для задания свойств видимости
'некоторых элементов управления
'–
Private Sub SetDifficultyButtonVisibility(ByVal visibleState _
As Boolean)
buttonShowAnswers_AdvancedVersion.Visible = visibleState
buttonShowAnswers_SimpleVersion.Visible = visibleState
End Sub
'–
'Вспомогательная функция, которая позволяет задавать состояние видимости
'кнопок, отображающих ответы из словаря
'–
Private Sub SetAnswerButtonEnabled(ByVal enabledState _
As Boolean)
buttonAnswer0.Enabled = enabledState
buttonAnswer1.Enabled = enabledState
buttonAnswer2.Enabled = enabledState
buttonAnswer3.Enabled = enabledState
buttonAnswer4.Enabled = enabledState
buttonAnswer5.Enabled = enabledState
End Sub
'–
'Задает текст в текстовом окне и кнопках,
'необходимых для формулирования вопросов.
'
'В случае практической реализации эта функция должна просматривать
'вопросы динамически
'–
Private Sub SetTextForVocabularyQuestion()
setQuestionText("What is the English word for 'der Mensch'?")
buttonAnswer0.Text = "Four"
buttonAnswer1.Text = "Person"
buttonAnswer2.Text = "Three"
buttonAnswer3.Text = "To Jump"
buttonAnswer4.Text = "Newspaper"
buttonAnswer5.Text = "Brother"
End Sub
'Вызывается для оценки варианта ответа, выбранного пользователем
Private Sub evaluateMultipleChoiceAnswer(ByVal buttonClicked _
As Button, ByVal selection As Integer)
'Примечание: В практической реализации правильный номер ответа
'определяется динамически и не всегда соответствует "кнопке #1"
'Если выбранный пользователем вариант ответа не является правильным,
'отменить доступ к нажатой кнопке
If (selection <> 1) Then
'Выбранный вариант ответа является неправильным
buttonClicked.Enabled = False
Else
'Пользователь выбрал правильный ответ, продолжить игру
StateChangeForGameUI(GameUIState.waitForNextQuestion)
End If
End Sub
'Абстракция, задающая текст вопросов
Sub setQuestionText(ByVal textIn As String)
textBoxAskQuestion.Text = textIn
End Sub
'–
'ОБРАБОТЧИК СОБЫТИЙ: Пользователь желает увидеть следующий вопрос
'–
Private Sub buttonAskQuestion_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles buttonAskQuestion.Click
SetTextForVocabularyQuestion()
StateChangeForGameUI(GameUIState.waitForUserToStateKnowledge)
End Sub
'–
'ОБРАБОТЧИК СОБЫТИЙ:
'Пользователь желает ответить на отображенный вопрос и сообщить, какой
'наиболее сложный уровень является для него приемлемым
'–
Private Sub buttonShowAnswers AdvancedVersion_Click( _
ByVal sender As Object, ByVal e As System.EventArgs) _
Handles buttonShowAnswers_AdvancedVersion.Click
'Установить состояние игры для отображения вариантов выбора
StateChangeForGameUI( _
GameUIState.waitForUserToAnswerMultipleChoice)
End Sub
'–
'ОБРАБОТЧИК СОБЫТИЙ:
'Пользователь желает ответить на отображенный вопрос и сообщить, какой
'наиболее легкий уровень является для него приемлемым
'–
Private Sub buttonShowAnswers_SimpleVersion_Click( _
ByVal sender As Object, ByVal e As System.EventArgs) _
Handles buttonShowAnswers_SimpleVersion.Click
'Установить состояние игры для отображения вариантов выбора
StateChangeForGameUI( _
GameUIState.waitForUserToAnswerMultipleChoice)
End Sub
'ОБРАБОТЧИК СОБЫТИЙ: Был выполнен щелчок на кнопке выбора варианта ответа
Private Sub buttonAnswer0_Click(ByVal sender As Object, ByVal _
e As System.EventArgs) Handles buttonAnswer0.Click
evaluateMultipleChoiceAnswer(buttonAnswer0, 0)
End Sub
'ОБРАБОТЧИК СОБЫТИЙ: Был выполнен щелчок на кнопке выбора варианта ответа
Private Sub buttonAnswer1_Click(ByVal sender As Object, ByVal _
e As System.EventArgs) Handles buttonAnswer1.Click
evaluateMultipleChoiceAnswer(buttonAnswer1, 1)
End Sub
'ОБРАБОТЧИК СОБЫТИЙ: Был выполнен щелчок на кнопке выбора варианта ответа
Private Sub buttonAnswer2_Click(ByVal sender As Object, ByVal _
e As System.EventArgs) Handles buttonAnswer2.Click
evaluateMultipleChoiceAnswer(buttonAnswer2, 2)
End Sub
'ОБРАБОТЧИК СОБЫТИЙ: Был выполнен щелчок на кнопке выбора варианта ответа
Private Sub buttonAnswer3_Click(ByVal sender As Object, ByVal _
e As System.EventArgs) Handles buttonAnswer3.Click
evaluateMultipleChoiceAnswer(buttonAnswer3, 3)
End Sub
'ОБРАБОТЧИК СОБЫТИЙ: Был выполнен щелчок на кнопке выбора варианта ответа
Private Sub buttonAnswer4_Click(ByVal sender As Object, ByVal _
e As System.EventArgs) Handles buttonAnswer4.Click
evaluateMultipleChoiceAnswer(buttonAnswer4, 4)
End Sub
'ОБРАБОТЧИК СОБЫТИЙ: Был выполнен щелчок на кнопке выбора варианта ответа
Private Sub buttonAnswer5_Click(ByVal sender As Object, ByVal _
e As System.EventArgs) Handles buttonAnswer5.Click
evaluateMultipleChoiceAnswer(buttonAnswer5, 5)
End Sub
Листинг 13.2. Динамическое создание элементов управления на форме во время выполнения
'–
'Счетчик количества создаваемых кнопок
'–
Private m_nextNewButtonIndex As Integer
'–
'ОБРАБОТЧИК СОБЫТИЙ: Обработчик щелчка на кнопке, которая
' имеется на нашей форме.
'
'Эта функция создает новую кнопку, присоединяет ее к нашей форме
'и подключает обработчик события щелчка для нее
'–
Private Sub buttonCreateNewButtons_Click(ByVal sender As _
System.Object, ByVal e As System.EventArgs) _
Handles buttonCreateNewButtons.Click
'Впоследствии мы начнем создавать новые кнопки, начиная
'снизу экрана, поэтому ограничиваем их количество восемью
If (m_nextNewButtonIndex > 8) Then
Return
End If
'–
'Создать кнопку (еще не присоединенную к нашей форме)
'установить ее местоположение, размеры и текст
'–
Const newButtonHeight As Integer = 15
Dim newButton As System.Windows.Forms.Button
newButton = New System.Windows.Forms.Button
newButton.Width = 100
newButton.Height = newButtonHeight
newButton.Left = 2
newButton.Top = (newButtonHeight + 2) * m_nextNewButtonIndex
newButton.Text = "New Button " + _
m_nextNewButtonIndex.ToString()
'–
'Присоединить обработчик к событию щелчка для данного
'элемента управления.
'–
AddHandler newButton.Click, _
AddressOf Me.ClickHandlerForButtons
'–
'Присоединить эту кнопку к форме. По существу,
'это создаст кнопку на форме!
'–
newButton.Parent = Me
'Увеличить счетчик в соответствии с созданием очередной кнопки
m_nextNewButtonIndex = m_nextNewButtonIndex + 1
End Sub
'–
'Обработчик событий, который мы динамически подключаем
'к нашим новым кнопкам
'–
Private Sub ClickHandlerForButtons(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim buttonCausingEvent As Button = _
CType(sender, System.Windows.Forms.Button)
'Вызвать окно сообщений, извещающее о том,
'что мы получили событие
MsgBox("Click event from:" + vbCrLf + buttonCausingEvent.Text)
End Sub
Листинг 13.3. Фильтрующее текстовое окно, принимающее текст в формате ###-##-####
Option Strict On
Imports System
'–
'Этот класс является элементом управления, производным от элемента управления
'TextBox.
'Он наследует все графические свойства TextBox, но добавляет фильтрацию
'содержимого текстового окна, тем самым гарантируя,
'что вводимый текст будет соответствовать формату:
'###-##-####.
'Этот формат соответствует формату номеров карточек социального страхования,
'используемых в США.
'–
Public Class SocialSecurityTextBox
Inherits System.Windows.Forms.TextBox
Private m_inputIsFullValidEntry As Boolean
'–
'Указывает, получен ли
'номер карточки социального страхования полностью
'–
Public ReadOnly Property IsFullValidInput() As Boolean
Get
Return m_inputIsFullValidEntry
End Get
End Property
'Объект StringBuilder, которую мы будем часто использовать
Private m_sb As System.Text.StringBuilder
'Максимальная длина обрабатываемых строк
Const SSNumberLength As Integer = 11
'–
'Конструктор
'–
Public Sub New()
'Распределить память для нашего объекта StringBuilder и предоставить
'место для нескольких дополнительных рабочих символов по умолчанию
m_sb = New System.Text.StringBuilder(SSNumberLength + 5)
m_inputIsFullValidEntry = False
End Sub
'–
'Форматировать поступающий текст с целью установления его соответствия
'нужному формату:
'
' Формат номера карточки социального страхования: ###-##-####
' символы: 01234567890
'
' [in] inString : Текст, который мы хотим форматировать
' [in/out] selectionStart: Текущая точка вставки в тексте;
' она будет смещаться в связи с удалением
' и добавлением нами символов
'–
Private Function formatText_NNN_NN_NNNN(ByVal inString As _
String, ByRef selectionStart As Integer) As String
Const firstDashIndex As Integer = 3
Const secondDashIndex As Integer = 6
'Удалить старые данные и поместить входную строку
'в объект StringBuilder, чтобы мы могли с ней работать.
m_sb.Length = 0
m_sb.Append(inString)
'–
'Просмотреть каждый символ в строке, пока не будет
'достигнута максимальная длина нашего форматированного текста
'–
Dim currentCharIndex As Integer
currentCharIndex = 0
While ((currentCharIndex < m_sb.Length) AndAlso _
(currentCharIndex < SSNumberLength))
Dim currentChar As Char
currentChar = m_sb(currentCharIndex)
If ((currentCharIndex = firstDashIndex) OrElse _
(currentCharIndex = secondDashIndex)) Then
'–
'The character needs to be a "-"
'–
If (currentChar <> "-"c) Then 'Вставить дефис
m_sb.Insert(currentCharIndex, "-")
'Если мы добавили символ перед точкой вставки,
'она должна быть смещена вперед
If (currentCharIndex <= selectionStart) Then
selectionStart = selectionStart + 1
End If
End If
'Этот символ годится, перейти к следующему символу
currentCharIndex = currentCharIndex + 1
Else
'–
'Символ должен быть цифрой
'–
If (System.Char.IsDigit(currentChar) = False) Then
'Удалить символ
m_sb.Remove(currentCharIndex, 1)
'Если мы добавили символ перед точкой вставки,
'она должна быть смещена назад
If (currentCharIndex < selectionStart) Then
selectionStart = selectionStart – 1
End If
'He увеличивать значение счетчика символов, ибо мы должны
'просмотреть символ, занявший место того символа,
'который мы удалили
Else
'Символ является цифрой, все нормально.
currentCharIndex = currentCharIndex + 1
End If
End If
End While
'Если превышена длина строки, усечь ее
If (m_sb.Length > SSNumberLength) Then
m_sb.Length = SSNumberLength
End If
'Возвратить новую строку
Return m_sb.ToString()
End Function
Private m_in_OnChangeFunction As Boolean
Protected Overrides Sub OnTextChanged(ByVal e As EventArgs)
'–
'Если мы изменим свойство .Text, то будет осуществлен повторный
'вход в обработчик. В этом случае мы не хотим предпринимать никаких
'действий и должны просто выйти из функции без передачи события
'куда-то еще.
'–
If (m_in_OnChangeFunction = True) Then
Return
End If
'Заметьте, что сейчас мы находимся в функции OnChanged,
'поэтому мы можем обнаружить повторное вхождение (см. код выше)
m_in_OnChangeFunction = True
'Получить текущее свойство .Text
Dim oldText As String = Me.Text
'Получить текущий индекс SelectionStart
Dim selectionStart As Integer = Me.SelectionStart
'Форматировать строку, чтобы она удовлетворяла нашим потребностям
Dim newText As String = formatText_NNN_NN_NNNN(oldText, _
selectionStart)
'Если текст отличается от исходного, обновить
'свойство .Text
If (oldText <> newText) Then
'Это приведет к повторному вхождению
Me.Text = newText
'Обновить местоположение точки вставки
Me.SelectionStart = selectionStart
End If
'Мы принудительно обеспечили соответствие введенного текста правильному
'формату, поэтому, если длина строки согласуется с длиной номера
'карточки социального страхования, то мы знаем что он имеет
'формат ###-##-####.
If (Me.Text.Length = SSNumberLength) Then
'Да, мы имеем полный номер карточки социального страхования
m_inputIsFullValidEntry = True
Else
'Нет, мы пока не получили полный номер карточки социального страхования
m_inputIsFullValidEntry = False
End If
'Вызвать наш базовый класс и сообщить всем объектам, которых это может
'интересовать, что текст изменился
MyBase.OnTextChanged(e)
'Заметьте, что сейчас мы покидаем наш код и хотим отключить
'проверку повторных вхождений в него.
m_in_OnChangeFunction = False
End Sub
Protected Overrides Sub OnKeyPress( _
ByVal e As System.Windows.Forms.KeyPressEventArgs)
'Поскольку нам известно, что никакие буквы при вводе нам не нужны,
'то просто игнорировать их, если они встречаются.
Dim keyPressed As Char = e.KeyChar
If (System.Char.IsLetter(keyPressed)) Then
'Сообщить системе о том, что событие обработано
e.Handled = True
Return
End If
'Обработать нажатие клавиши обычным способом
MyBase.OnKeyPress(e)
End Sub
End Class
Листинг 13.4. Код формы для создания пользовательского элемента управления TextBox
'–
'Переменная для хранения нашего нового элемента управления TextBox
'–
Private m_filteredTextBox As SocialSecurityTextBox
'–
'ОБРАБОТЧИК СОБЫТИЙ: Создать экземпляр нашего пользовательского элемента
' управления и поместить его в форму
'–
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'Создать, позиционировать и разместить элемент управления
m_filteredTextBox = New SocialSecurityTextBox
m_filteredTextBox.Bounds = _
New System.Drawing.Rectangle(2, 2, 160, 20)
'Подключить обработчик событий
AddHandler m_filteredTextBox.TextChanged, _
AddressOf Me.textBox_TextChanged
'Задать родительский объект
m_filteredTextBox.Parent = Me
'Выделить элемент управления
m_filteredTextBox.Focus()
'Сделать данную кнопку недоступной, чтобы поверх данного объекта
'не был создан второй объект
SocialSecurityTextBox Button1.Enabled = False
End Sub
'–
'ОБРАБОТЧИК СОБЫТИЙ: Этот обработчик подключается динамически при
' создании элемента управления
'–
Private Sub textBox_TextChanged(ByVal sender As Object, _
ByVal e As System.EventArgs)
If (m_filteredTextBox.IsFullValidInput = True) Then
label1.Text = "FULL SOCIAL SECURITY NUMBER!!!"
Else
Label1.Text = "Not full input yet..."
End If
End Sub
Листинг 13.5. код формы, демонстрирующий использование прозрачности '
'–
'Размеры наших битовых образов и экранного изображения PictureBox
'–
Const bitmap_dx As Integer = 200
Const bitmap_dy As Integer = 100
'–
'Создает и прорисовывает изображение заднего плана
'–
Private m_backgroundBitmap As System.Drawing.Bitmap
Sub CreateBackground()
If (m_backgroundBitmap Is Nothing) Then
m_backgroundBitmap = New Bitmap(bitmap_dx, bitmap_dy)
End If
'Делаем битовую карту белой
Dim gfx As System.Drawing.Graphics
gfx = System.Drawing.Graphics.FromImage(m_backgrourdBitmap)
gfx.Clear(System.Drawing.Color.White)
'Рисуем текст черным
Dim myBrush As System.Drawing.Brush
myBrush = New System.Drawing.SolidBrush( _
System.Drawing.Color.Black)
Dim у As Integer
For у = 0 To bitmap_dy Step 15
gfx.DrawString("I am the BACKGROUND IMAGE...hello", Me.Font, myBrush, 0, y)
Next
'Очистить
myBrush.Dispose()
gfx.Dispose()
End Sub
'–
'Создает и прорисовывает изображение заднего плана
'–
Private m_foregroundBitmap As System.Drawing.Bitmap
Sub CreateForeground()
If (m_foregroundBitmap Is Nothing) Then
m_foregroundBitmap = New Bitmap(bitmap_dx, bitmap_dy)
End If
'Делаем всю битовую карту синей
Dim gfx As System.Drawing.Graphics
gfx = System.Drawing.Graphics.FromImage(m_foregroundBitmap)
gfx.Clear(System.Drawing.Color.Blue)
'Рисуем несколько фигур желтым
Dim yellowBrush As System.Drawing.Brush
yellowBrush = New System.Drawing.SolidBrush( _
System.Drawing.Color.Yellow)
gfx.FillEllipse(yellowBrush, 130, 4, 40, 70)
gfx.FillRectangle(yellowBrush, 5, 20, 110, 30)
gfx.FillEllipse(yellowBrush, 60, 75, 130, 20)
'Очистить
yellowBrush.Dispose()
gfx.Dispose()
End Sub
'–
'Устанавливает размеры и местоположение PictureBox с левой стороны
'–
Private Sub SetPictureBoxDimensions()
PictureBox1.Width = bitmap_dx
PictureBox1.Height = bitmap_dy
PictureBox1.Left = 20
End Sub
'–
'ОБРАБОТЧИК СОБЫТИЙ: Отобразить изображение ЗАДНЕГО ПЛАНА в PictureBox
'–
Private Sub buttonDrawBackground_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles buttonDrawBackground.Click
SetPictureBoxDimensions()
CreateBackground()
PictureBox1.Image = m_backgroundBitmap
End Sub
'–
'ОБРАБОТЧИК СОБЫТИЙ: Отобразить изображение ПЕРЕДНЕГО ПЛАНА в PictureBox
'–
Private Sub buttonDrawForeground_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles buttonDrawForeground.Click
SetPictureBoxDimensions()
CreateForeground()
PictureBox1.Image = m_foregroundBitmap
End Sub
'–
'ОБРАБОТЧИК СОБЫТИЙ: Наложить изображение ПЕРЕДНЕГО ПЛАНА на изображение
' ЗАДНЕГО ПЛАНА. Использовать МАСКУ ПРОЗРАЧНОСТИ, чтобы желтый
' цвет в изображении ПЕРЕДНЕГО ПЛАНА стал прозрачным и через
' него можно было видеть содержимое изображения
' ЗАДНЕГО ПЛАНА
'–
Private Sub buttonDrawBackgroundPlusForeground_Click(ByVal _
sender As Object, ByVal e As System.EventArgs) _
Handles buttonDrawBackgroundPlusForeground.Click
SetPictureBoxDimensions()
CreateForeground()
CreateBackground()
'Получить объект Graphics изображения ЗАДНЕГО ПЛАНА, поскольку
'именно поверх него мы собираемся рисовать.
Dim gfx As System.Drawing.Graphics
gfx = System.Drawing.Graphics.FromImage(m_backgroundBitmap)
'–
'Создать класс ImageAttributes. Этот класс позволяет нам
'задать прозрачный цвет на наших операций рисования







