www.larryroof.com
Резюме
Лэрри Руф разработал пошаговое руководство по построению
пользовательских элементов управления, называемых им мутированными
элементами управления, в .NET Compact Framework. Элементы управления,
рассмотренные в этой статье, включают в себя разновидности элемента
управления TextBox, добавляющие свойство Locked и создающие
свойство InputPanel. (12 печатных страниц)
Загрузите Textboxplusdemo.exe.
После выхода последней моей статьи прошло несколько месяцев. Причиной
этому послужило то, что в .NET Compact Framework есть слишком много крутых
вещей, о которых можно писать. Вам известно о кризисе писателя? Этот
кризис для меня не существует, даже наоборот.
Вся проблема возникла потому, что было много работы над следующей
книгой "Полное руководство по .NET Compact Framework" (The Definitive
Guide to the .NET Compact Framework), которая будет опубликована
издательством Apress в начале следующего года. Работая над темами для
книги, я продолжал себе повторять, что "это будет великолепная статья для
книги "Двое на дороге" (Two for the Road). Начав работу над несколькими
статьями, я отвлекся на другую крутую возможность .NET Compact Framework,
на которую я наткнулся.
Невозможно выразить словами, какой это восхитительный продукт. Я уже
немного думал о татуировке "Я люблю (символ сердца) NETCF" на предплечье,
но понял, что она не будет соответствовать двум моим существующим
татуировкам: "Если Вы нашли меня, пожалуйста, верните меня на пляж" и "Вы
сможете вырвать мой Pocket PC из рук только через мой труп".
Перейдем к теме этой статьи: создание пользовательских элементов
управления. Как уже можно было предположить, сейчас я работаю над
следующей главой моей книги о создании элементов управления с помощью .NET
Compact Framework. Как и в каждой предыдущей главе, я думаю, что это -
самая крутая возможность в .NET Compact Framework. Поэтому, пока меня
ничего не отвлекло, перейдем к пошаговому руководству по пользовательским
элементам управления.
Построение пользовательского элемента управления
Одной из первых жалоб разработчиков на .NET Compact Framework было то,
что в их стиле разработки не хватает чего-то важного. Этим чем-то может
быть любая вещь - от чрезвычайно важного элемента, затрагивающего также и
меня, до чего-то земного, иначе говоря, до некоторой возможности, которую
я никогда не предполагал использовать на первом месте. Теперь я могу
сделать вид, что симпатизирую жалующимся личностям - в конце концов, я
имел дело с пользователями в течение многих лет. По моему мнению, в данном
случае фирма Microsoft проделала хорошую работу, создав из продукта (.NET
Framework), похожего на 400-фунтовую гориллу, другой продукт размером с
собаку чау-чау (.NET Compact Framework).
Одна из самых крутых возможностей .NET Compact Framework - это то, как
она позволяет Вам кодировать без ограничений. Рассмотрим, например,
элементы управления. Все элементы управления, поставляемые с .NET Compact
Framework, ограничены по сравнению со своими аналогами в полной версии. У
них отсутствуют некоторые свойства, методы и события. Теперь можно
действовать как пользователь и жаловаться на эти недостатки, или же можно
что-то предпринять. .NET Compact Framework позволяет создавать, как я
нежно их называю, мутированные элементы управления, являющиеся
стандартными элементами управления, которые были настроены и изменены по
потребностям конкретного пользователя. Можно сказать, что в этом случае
программист пробует себя в роли Франкенштейна. Далее в этой статье будет
рассмотрен пошаговый процесс изменения элемента управления для расширения
его функциональных возможностей.
Представление TextBoxPlus
Неудивительно, что один из элементов управления, наиболее часто
используемых разработчиками программного обеспечения для мобильных
устройств, - это обычный TextBox. Исходя из моих потребностей, у элемента
управления TextBox в реализации .NET Compact Framework не хватает
нескольких главных возможностей. Во-первых, хотелось бы иметь возможность
блокировать элемент управления, не допуская ввод любых данных
пользователем. Во-вторых, хотелось бы автоматически отображать Soft Input
Panel (SIP), когда элемент управления TextBox получает фокус. Именно этими
двумя возможностями и обладает созданный мной элемент управления
TextBoxPlus.
TextBoxPlus - это мутированный элемент управления. В стандартном
элементе управления TextBox некоторые возможности были достигнуты, а
некоторые - видоизменены, и далее были получены свойство Locked и
возможность автоматического отображения SIP. Теперь перейдем к более
серьезным вещам: не начинайте резкую критику дискуссии по теории элементов
управления, об этой теории довольно скучно писать, не говоря уже о чтении
этой теории. Вместо этого рассмотрим процесс построения этого элемента
управления, выделяя его ключевые аспекты.
Основа TextBoxPlus
Элемент управления TextBoxPlus построен с помощью стандартного модуля
Class. Теперь модуль Class был добавлен к проекту приложения Pocket PC
(см. пример приложения для этой статьи). В данный момент в "новый" элемент
управления не внесено никаких изменений, кроме базовой структуры класса,
показанной на распечатке 1. Ключевое понятие, на которое здесь необходимо
обратить внимание: было установлено имя класса TextBoxPro,
определяющего имя нового элемента управления.
Распечатка 1. Пустая структура класса
Public Class TextBoxPro
End Class
Как было сказано ранее, элемент управления TextBoxPlus - это, образно
говоря, мутированный элемент управления, который получен из существующего
элемента управления. Для этого к модулю Class необходимо добавить
единственную строку кода, в которой определяется наследование нового
элемента управления от TextBox. На распечатке 2 показан модифицированный
модуль.
Распечатка 2. Наследование от элемента управления TextBox
Public Class TextBoxPlus
Inherits TextBox
End Class
Если в данный момент оставить все как есть, то будет получена точная
копия элемента управления TextBox. Этот новый и нисколько не улучшенный
элемент управления будет работать и отвечать точно также, как и
стандартный элемент управления TextBox. Он будет обладать теми же
свойствами, методами и событиями.
В этом состоит все великолепие разработки мутированных элементов
управления: пользователь получает все функциональные возможности исходного
элемента управления наряду с любыми дополнительными возможностями, из
которых требуется сгенерировать комбинацию.
Добавление свойства Locked
Теперь можно перейти к настройке элемента управления. Первая
возможность, которую необходимо добавить, - это свойство Locked. В
стандартном .NET Compact Framework у элемента управления TextBox это
свойство отсутствует.
Процедура добавления свойства Locked состоит из двух шагов.
Во-первых, необходимо добавить собственно свойство. Во-вторых, этому
свойству необходимо предоставить функциональные возможности, которые не
допускают изменения содержания TextBox пользователем.
Свойства добавляются к элементу управления путем определения процедуры
Property в модуле Class. На распечатке 3 приводится код, требуемый
для этого шага. Необходимо обратить внимание на четыре части этого
определения.
Во-первых, определяется закрытая переменная mLocked. Эта
переменная используется для хранения значения свойства Locked,
которое является внутренним по отношению к данному элементу управления.
Эта переменная определяется как закрытая переменная, потому что ее не
нужно показывать приложению, использующему этот элемент управления.
Во-вторых, свойство Locked определяется с помощью процедуры
Property. Эта процедура определяет имя свойства - Locked, и
его тип - Boolean. Обратите внимание, что эта процедура состоит из
двух разделов - Get и Set. Раздел Get этой процедуры вызывается, когда
вызывающее приложение запрашивает значение свойства. Раздел Set
выполняется, когда вызывающее приложение устанавливает значение свойства.
В-третьих, в разделе Get имеется единственная строка кода, в которую
возвращается текущее значение свойства Locked. Внутренняя
переменная mLocked содержит это значение, поэтому ей необходимо
только возвратить его содержание.
В-четвертых, в разделе Set имеется единственная другая строка кода, в
которой хранится новое значение, предоставленное хост-приложением.
Обратите внимание, что структура Set получает единственный параметр
Value - новую установку свойства. Необходимо лишь сохранить
параметр во внутренней переменной.
Распечатка 3. Добавление свойства Locked
Public Class TextBoxPlus
Inherits TextBox
' Добавление свойства Locked.
Private mLocked As Boolean
Public Property Locked() As Boolean
Get
Locked = mLocked
End Get
Set(ByVal Value As Boolean)
mLocked = Value
End Set
End Property
End Class
Добавление функциональных возможностей Locked
В данный момент элемент управления TextBoxPlus имеет новое свойство
Locked. Значение этого свойства можно было бы установить и получить
из приложения. Единственная проблема состоит в том, что этот элемент
управления еще не может запретить пользователю изменять содержание
элемента управления.
Чтобы ограничить пользовательский ввод, к данному элементу управления
необходимо добавить некоторый код. Для этого нужно обойти три процедуры
обработки событий, которые являются составной частью нижележащего элемента
управления TextBox.
Когда пользователь вводит символ в TextBox, генерируются три события:
- KeyDown;
- KeyPress;
- KeyUp.
С помощью именно этих событий будут реализованы функциональные
возможности для свойства Locked.
Каждое из этих событий получает значение, представляющее символ,
вводимый в качестве параметра. Здесь нужен ловкий прием: необходимо
заставить элемент управления думать, что ничего не было введено. Это можно
достичь с помощью кода, приведенного на распечатке 4.
Были добавлены три процедуры - по одной для каждого из событий клавиш.
Процедура OnKeyDown соответствует событию KeyDown, OnKeyPress
соответствует событию KeyPress, и OnKeyUp обрабатывает событие
KeyUp.
Распечатка 4. Добавление функциональной возможности Locked
' Настройка события OkKeyDown нижележащего элемента управления для обхода
' события при блокировании элемента управления.
Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
If (mLocked = False) Then
MyBase.OnKeyDown(e)
Else
End If
End Sub
' Настройка события OkKeyDown нижележащего элемента управления для обхода
' события и удаления ключевого значения при блокировании элемента управления.
Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)
If (mLocked = False) Then
MyBase.OnKeyPress(e)
Else
e.Handled = True
End If
End Sub
' Настройка события OkKeyUp нижележащего элемента управления для обхода
' события при блокировании элемента управления.
Protected Overrides Sub OnKeyUp(ByVal e As System.Windows.Forms.KeyEventArgs)
If (mLocked = False) Then
MyBase.OnKeyUp(e)
Else
End If
End Sub
В каждом из этих событий проверяется значение свойства Locked.
Не следует забывать, что текущее значение этого свойства хранится в
переменной mLocked. Если свойство Locked установлено в
значение "False", событие передается нижележащему элементу управления
TextBox для обработки. Это выполняется с помощью следующей строки кода:
MyBase.OnKeyPress(e)
Эта строка кода не выполняется, если свойство Locked установлено
в значение "True", которое эффективно не допускает генерации события.
И, наконец, необходимо добавить единственную строку кода в процедуру
OnKeyPress, заставляющую операционную систему игнорировать все, что было
только что введено пользователем, поскольку все это будет обработано самой
процедурой. Для выполнения этой задачи необходимо установить свойство
Handled в значение "True", как показано в следующей строке кода:
e.Handled = True
Все готово. В данный момент у мутированного элемента управления
появилось свойство Locked. Если это свойство установлено,
пользователь не сможет ничего ввести с помощью Soft Input Panel.
Добавление свойства InputPanel
Вторая возможность, которую необходимо добавить в расширенный элемент
управления, - это автоматическое отображение Soft Input Panel (SIP), когда
элемент управления получает фокус. Как и для свойства Locked,
процедура добавления свойства InputPanel состоит из двух частей.
Во-первых, необходимо добавить собственно свойство. Во-вторых, этому
свойству необходимо добавить его функциональные возможности.
На распечатке 5 приводится код, требуемый для определения свойства
InputPanel. Подходы, используемые для реализации этого свойства и
свойства Locked, аналогичны, но имеют несколько основных отличий.
Необходимо обратить особое внимание на следующий факт: если тип свойства
Locked был Boolean, то тип этого свойства -
Microsoft.WindowsCE.Forms.InputPanel. Необходимо создать свойство
InputPanel аналогично свойству ImageList элемента управления
Toolbar. Свойства InputPanel и ImageList используются для
хранения особого типа элементов управления InputPanel и
ImageList (соответственно).
В этой процедуре используются две закрытые переменные. Первая
переменная mInputPanel будет хранить элемент управления
InputPanel. Вторая переменная mSipDefined отмечает, было ли
установлено свойство InputPanel.
Обратите внимание, что использование типов данных совпадает во всей
процедуре. Закрытая переменная mInputPanel, параметр процедуры
Property и параметр процедуры Set имеют тип
Microsoft.WindowsCE.Forms.InputPanel.
Распечатка 5. Добавление свойства InputPanel
' Добавление свойства InputPanel.
Private mInputPanel As Microsoft.WindowsCE.Forms.InputPanel
Private mSipDefined As Boolean
Public Property InputPanel() As Microsoft.WindowsCE.Forms.InputPanel
Get
InputPanel = mInputPanel
End Get
Set(ByVal Value As Microsoft.WindowsCE.Forms.InputPanel)
mInputPanel = Value
mSipDefined = True
End Set
End Property
Добавление функциональных возможностей InputPanel
Как и свойство Locked, в данный момент элемент управления
TextBoxPlus получает новое свойство InputPanel. Как и у ранней
версии свойства Locked, у него фактически отсутствуют
функциональные возможности. SIP не отображается при наведении фокуса на
элемент управления.
Чтобы реализовать эти функциональные возможности, к элементу управления
необходимо добавить еще немного кода. Для свойства Locked мы обошли
три процедуры обработки событий, а здесь вместо этого необходимо расширить
две процедуры обработки событий.
Когда пользователь наводит фокус на элемент управления TextBox,
генерируется событие GotFocus. Когда пользователь убирает фокус с
этого элемента управления, генерируется событие LostFocus. Для добавления
требуемых функциональных возможностей необходимо изменить эти два элемента
управления.
На распечатке 6 приводятся две процедуры OnGotFocus и
OnLostFocus, позволяющие расширить функциональные возможности. Эти
процедуры сгенерируют события, когда элемент управления TextBoxPlus
получает и теряет фокус.
В процедуре OnGotFocus необходимо сначала удостовериться, что элемент
управления TextBoxPlus не блокирован, поскольку нет никакого смысла
отображать SIP, если пользователю запрещено вводить данные. Если элемент
управления не блокирован, необходимо установить свойство Enabled
элемента управления InputPanel в значение "True", что определяет
отображение SIP.
Процедура OnLostFocus аналогична. В ней используется свойство
Enabled элемента управления InputPanel, позволяющее скрыть SIP.
Обратите внимание на одну ключевую особенность: обе процедуры
завершаются вызовом соответствующего события в нижележащем элементе
управления, обеспечивая генерацию событий GotFocus и
LostFocus. Это позволяет разработчику приложения, использующему
данный элемент управления TextBoxPlus, написать код для этих событий.
Распечатка 6. Добавление функциональных возможностей InputPanel
' Расширение события OnGotFocus для включения отображения SIP, если 1) элемент управления
' не заблокирован и 2) элемент управления InputPanel уже определен.
Protected Overrides Sub OnGotFocus(ByVal e As System.EventArgs)
If (mLocked = False) Then
If (mSipDefined) Then
mInputPanel.Enabled = True
End If
End If
MyBase.OnGotFocus(e)
End Sub
' Расширение события OnLostFocus для включения скрытия SIP, если 1) элемент управления
' не заблокирован и 2) элемент управления InputPanel уже определен.
Protected Overrides Sub OnLostFocus(ByVal e As System.EventArgs)
If (mLocked = False) Then
If (mSipDefined) Then
mInputPanel.Enabled = False
End If
End If MyBase.OnLostFocus(e)
End Sub
Проверка элемента управления TextBoxPlus
Теперь, когда работа над элементом управления завершена, его можно
проверить. Для этой цели было создано простое приложение для Pocket PC.
Пример его интерфейса показан на рис. 1.
Рис. 1. Интерфейс тестового приложения
В этом дизайне следует обратить внимание на два ключевых аспекта.
Во-первых, элемент управления TextBoxPlus теперь не виден в форме. При
создании функционального гибридного элемента управления версия времени
разработки этого элемента управления не была создана. Другими словами,
добавить элемент управления в форму во время разработки невозможно. Вместо
этого создадим экземпляр элемента управления из кода.
Во-вторых, обратите внимание на элемент управления InputPanel,
показанный на панели под формой. Элемент управления InputPanel
позволяет управлять SIP. Не следует забывать, что свойство
InputPanel данного элемента управления TextBoxPlus ожидает наличия
InputPanel.
Создание экземпляра элемента управления TextBoxPlus
Первая возможность, которую необходимо проверить в данном элементе
управления, - это его создание и добавление к форме. На распечатке 7
приводится код, используемый для этой цели.
Оператор Dim определяет новый экземпляр элемента управления
TextBoxPlus. Используйте ключевое слово WithEvents, позволяющее
нижележащему объекту генерировать события.
В событии Click кнопки Create содержится код, используемый для
конфигурирования элемента управления. Обратите внимание, что установлено
много свойств, включая свойство Locked. Откуда же возникли все эти
другие свойства? Из элемента управления TextBox, на основе которого был
построен расширенный элемент управления. Раннее упоминалось, что все
свойства, методы и события доступны, как при работе с родным элементом
управления.
Итак, новый экземпляр элемента управления добавлен к форме с помощью
коллекции элементов управления.
Распечатка 7. Добавление элемента управления TextBoxPlus к форме
Dim WithEvents txtDemo As New TextBoxPlus
Private Sub btnCreate_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnCreate.Click
' Создание экземпляра элемента управления TextBoxPlus.
txtDemo.Left = 10
txtDemo.Top = 10
txtDemo.Width = 100
txtDemo.Height = 20
txtDemo.Locked = False
Me.Controls.Add(txtDemo)
' AddHandler txtDemo.KeyDown, AddressOf KeyDownHandler
' Отображение начального состояния свойства Locked.
lblStatus.Text = "locked - " & txtDemo.Locked.ToString
' Выключение кнопки для того, чтобы пользователь не нажал ее снова.
btnCreate.Enabled = False
End Sub
Проверка свойства Locked
Когда элемент управления создается впервые, значение свойства
Locked установлено в "False", т.е. пользователь может ввести данные
в элемент управления. С помощью переключения этого свойства можно получить
возможность разрешать или запрещать ввод в элемент управления TextBoxPlus.
Для этой цели к тестовому приложению была добавлена кнопка. На распечатке
8 приводится простой фоновый код этой кнопки.
Как показывает эта процедура, новое свойство Locked работает как
любое другое свойство. С помощью этой единственной строки кода можно
проверить оба компонента Get и Set данного свойства.
Распечатка 8. Переключение свойства Locked
Private Sub btnLocked_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnLocked.Click
' Переключение свойства Locked элемента управления TextBoxPlus.
txtDemo.Locked = Not txtDemo.Locked
' Обновление отображения.
lblStatus.Text = "locked - " & txtDemo.Locked.ToString
txtDemo.Focus()
End Sub
Проверка свойства InputPanel
Перед проверкой этого свойства сначала необходимо установить его
значение. Как уже было сказано ранее, свойству InputPanel требуется
элемент управления InputPanel. Именно для этой цели элемент
управления InputPanel был добавлен к тестовой форме.
Код, используемый для установки свойства InputPanel, приводится на
распечатке 9.
Распечатка 9. Конфигурирование свойства InputPanel
Private Sub btnAutoSip_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnAutoSip.Click
txtDemo.InputPanel = InputPanel1
btnAutoSip.Enabled = False
End Sub
Если в данный момент элемент управления TextBoxPlus получает или теряет
фокус, SIP будет сначала отображен и затем скрыт. Попробуйте включить
свойство Locked и затем повторить проверку. SIP не должен быть
отображен, когда элемент управления TextBoxPlus получает фокус.
Заключительные слова об элементе управления TextBoxPlus
Очевидно, что этот элемент управления может быть расширен добавлением
интерфейса режима разработки. Однако создание собственного интерфейса
полностью из кода не столь захватывающе, как можно было бы предполагать.
Проблема в том, что Visual Basic®.NET не
может использоваться для создания версии времени разработки элементов
управления .NET Compact Framework. Для решения этой задачи необходимо
использовать C# и Visual Studio® .NET.
Если пользователю необходимо использовать элемент управления
TextBoxPlus со своим приложением, нужно лишь добавить модуль TextBoxPlus
Class к проекту, создать и сконфигурировать его, как было
продемонстрировано в этой статье.
Дополнительная информация
Подробную информацию по созданию пользовательских элементов управления
для .NET Compact Framework можно получить по следующим ссылкам:
Начните разработку с помощью .NET Compact Framework
Хотите научиться работать с .NET Compact Framework через неделю? При
обучении в моем классе это возможно. Предлагаемое мною пятидневное
обучение по NETCF предоставляет все, что необходимо для быстрого начала
работы. На занятиях будет показано, как создать устойчивые мобильные
решения с помощью .NET Compact Framework, SQL Server CE и XML. Подробную
информацию об обучении можно получить по адресу http://www.larryroof.com/.
Снова на дороге
Эта работа на следующий месяц. Здесь, на Среднем Западе, наступает
зима. Если я еще никогда не говорил этого, я ненавижу зиму. Нет, точнее
говоря, я презираю зиму. Тем, кто был введен в заблуждение слезливыми
эпизодами канала Hallmark, лживыми зимними кампаниями Currier и Ives,
позвольте мне сказать прямо, что в зиме нет ничего хорошего или
счастливого. Прошу Вас, во имя любви ко всем хорошим вещам, если Вы это
читаете, переезжайте в местность с теплым климатом (в паре сотен ярдов от
приличного места для серфинга), и Вы можете сказать посетителю, "я не
знаю, четыре или пять месяцев, пишите мне по адресу larry.roof@larryroof.com." А до
тех пор я буду прижиматься к вытяжному вентилятору моего компьютера,
пытаясь не замерзнуть.
Джон Кеннеди - технический писатель/программист в группе Visual
C ++ днем, который ведет тайную жизнь разработчика Pocket PC ночью.
Лэрри Руф возглавляет larryroof.com, фирму, которая
специализируется на консалтинге по мобильным проектам и на обучении
eMbedded Visual Basic, Smart Device Extensions и SQL Server CE.