412 000 произведений, 108 200 авторов.

Электронная библиотека книг » Иво Салмре » Программирование мобильных устройств на платформе .NET Compact Framework » Текст книги (страница 36)
Программирование мобильных устройств на платформе .NET Compact Framework
  • Текст добавлен: 18 июля 2025, 02:31

Текст книги "Программирование мобильных устройств на платформе .NET Compact Framework"


Автор книги: Иво Салмре



сообщить о нарушении

Текущая страница: 36 (всего у книги 69 страниц)

Стратегии проектирования высокопроизводительного графического кода

Код, предназначенный для обработки графики, целесообразно рассматривать отдельно от кода высокоуровневого пользовательского интерфейса. Обычно в коде пользовательского интерфейса используются высокоуровневые абстракции, предлагаемые операционной системой или средой программирования. Примерами подобных абстракций могут служить такие понятия, как элементы управления Button, ListBox, ListView, Panel или Grid. На самом нижнем уровне элементы управления реализуются в виде последовательностей инструкций рисования и низкоуровневого взаимодействия с операционной системой и пользователями. Разработчикам приложений почти никогда не приходится иметь дело с элементами управления на этом самом низком уровне абстракции. Обычно, используя элементы управления пользовательского интерфейса, разработчик полагается на уже организованное для него оптимизированное выполнение базовых операций, связанных с рисованием и поддержкой элементов управления; задача разработчика заключается лишь в том, чтобы наиболее эффективным способом использовать эти элементы управления на более высоком уровне абстракции. В отличие от этого, при работе с графикой разработчик должен специально продумать, как должны решаться низкоуровневые задачи рисования и каким образом можно обеспечить их наиболее эффективное выполнение.

С позиций абстрагирования код высокоуровневого пользовательского интерфейса аналогичен организации связи в сети с использованием запросов и ответов по протоколу HTTP; в то же время, графический код аналогичен организации связи на уровне сокетов или же пакетов. Как и в случае сетевых коммуникаций, во всех возможных случаях лучше использовать высокоуровневые абстракции. Высокоуровневые абстракции легко использовать, они эффективны для большинства задач и надежно протестированы. Эффективная работа с низкоуровневыми программными средствами, например, графическими библиотеками, требует более глубокого понимания того, что при этом происходит, и соответствующего активного вмешательства в ход событий, и должна сопровождаться тщательным анализом того, какую пользу с точки зрения эффективности это может принести приложению. Графический код выглядит и работает иначе, чем код пользовательского интерфейса.

Поскольку конечной целью всей низкоуровневой работы с графикой является предоставление отдельных частей многофункционального пользовательского интерфейса, между низкоуровневым графическим кодом и кодом пользовательского интерфейса в какой-то точке должно быть налажено взаимодействие. Можно почти не сомневаться, что создаваемая вами графика будет сосуществовать с такими высокоуровневыми компонентами пользовательского интерфейса, как элементы управления Button, Menu или ListView. Управление всем пользовательским интерфейсом посредством только низкоуровневого графического кода может быть оправданным лишь в самых редких случаях по той простой причине, что приложение ничего не выиграет, если будет самостоятельно прорисовывать элементы управления и обрабатывать низкоуровневое взаимодействие с пользователем. Вместо этого следует прибегать к гораздо более эффективному подходу, в соответствии с которым разработчики используют для обслуживания пользовательского интерфейса готовые библиотеки проверенных на практике функций и привлекают графические функции для управления лишь теми элементами пользовательского интерфейса, которые испытывают в этом крайнюю необходимость. Для этого следует использовать тщательно продуманные модели, описывающие, каким образом код высокоуровневого пользовательского интерфейса и низкоуровневый графический код должны сочетаться друг с другом.

Четырехминутный практикум по работе с графикой в .NET Compact Framework

В документации к .NET Framework и .NET Compact Framework содержится обширная информация по работе с графикой, с которой вам обязательно стоит ознакомиться. Ниже приведены лишь самые основные сведения.

Рабочей лошадкой графики в NET является объект System.Drawing.Graphics. Если вы знакомы с методами разработки приложений в собственных кодах Windows, считайте, что это – объектно-ориентированная версия hDC (Device Context, контекст устройства). Чтобы нарисовать что-либо (например, фигуру, линию, текст, растровое изображение) на поверхности битовой карты, ваш код должен вызвать соответствующий метод объекта Graphics. Не менее важно знать о том, что после того как вы закончите работать с созданным перед этим объектом Graphics, необходимо освободить память от этого объекта при помощи вызова функции Dispose(), иначе он будет занимать драгоценные системные ресурсы. Для того чтобы постоянно держать под рукой какой-либо из объектов Graphics, у вас должны быть веские причины.

Если объект Graphics не создается, а передается, то обычно этот объект вам предоставляет вызывающая функция. В подобных случаях забота о том, чтобы освободить память от этого объекта с помощью метода Dispose(), обычно лежит не на вашем коде; при вызове метода Dispose() объекта, который все еще используется другим кодом, возникают проблемы. Наиболее распространенные ситуации, в которых объект Graphics передается другой функции, возникают, когда вы пишете обработчик Paint для нестандартного элемента управления или подключаетесь к обработчику Paint для формы или стандартного элемента управления. В этих случаях вы выполняете нужные операции рисования при помощи передаваемого вам объекта Graphics.

Перья (Pen), кисти (Brush), шрифты (Font), растровые изображения (Bitmap) также должны создаваться. Эти объекты не принадлежат какому-то одному объекту Graphics; одни и те же объекты могут использоваться различными объектами Graphics. Когда работа с этими объектами в вашем коде закончена, для них также необходимо вызывать метод Dispose(). Тем не менее, в случае мобильных приложений использование глобальных объектов Pen, Brush, Font или Bitmap, если они часто используются, может оказаться полезным и эффективным. Производительность приложения можно значительно повысить, применяя тщательно продуманную стратегию кэширования объектов.

Для указания атрибутов рисования визуализируемых объектов используется класс ImageAttributes. Он передается при помощи перегруженных методов Graphics.DrawImage() и позволяет вашему приложению устанавливать прозрачный цвет для битовых образов, копируемых на другую поверхность. Использование класса ImageAttributes на платформе .NET Compact Framework позволяет вашему приложению назначать один из цветов битового образа в качестве прозрачного; благодаря этому ваш код получает возможность визуализировать на битовых образах объекты, форма которых отличается от прямоугольной. Такая возможность оказывается очень полезной при написании игр. Как и в случае других классов, объекты ImageAttributes по окончании работы должны вызывать метод Dispose().

Способы интеграции графики с кодом пользовательского интерфейса

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

1. Отображение растровых изображений в элементе управления PictureBox.

2. Рисование непосредственно в форме.

3. Реализация пользовательских элементов управления.

Перечисленные способы описываются ниже с использованием иллюстративных примеров их применения.

Отображение растровых изображений в элементе управления PictureBox

Рисование графики на внеэкранных битовых картах и отображение полученных битовых образов в элементе PictureBox на форме является самым простым и наиболее мощным способом работы с пользовательской графикой. В силу своей простоты такой подход великолепно подходит для работы почти с любыми видами деловой графики и даже для многих игр.

Чтобы использовать этот подход, вашему приложению достаточно создать объект Bitmap и соответствующий ему объект Graphics, а затем использовать этот объект Graphics для рисования всего, что необходимо, на битовой карте, прежде чем назначить ее свойству Image элемента управления PictureBox. Элемент управления PictureBox позаботится обо всем остальном. Он проверяет, обновлено ли изображение на экране, и при необходимости перерисовывает его; если элемент управления PictureBox временно перекрывался, частично или полностью, другим элементом управления или окном, PictureBox самостоятельно перерисует его, когда он вновь окажется открытым. PictureBox осуществляет проверку того, что выводимое изображение идентично тому, которое хранится в битовой карте; предусматривать в приложении какую-либо дополнительную логику для этого не требуется.

В силу своей простоты такая методика прекрасно подходит для отображения графических данных, которые не претерпевают ежесекундных изменений. Он также обеспечивает достаточную эффективность, поскольку элементу управления PictureBox известно, когда он должен сам себя перерисовать. Элементы управления PictureBox могут предоставлять также некоторые события (например, Click), к которым ваше приложение может подключаться, что позволяет наделять их некоторой дополнительной интерактивностью, что делает этот подход еще более полезным

На рис. 11.5 представлено приложение, в котором имеются элементы управления Button и PictureBox. В результате нажатия кнопки Button создается внеэкранная битовая карта, на ней рисуется эллипс и некоторый текст к нему, после чего эта карта назначается элементу управления PictureBox. В листинге 11.6 приведен выполняющий описанные операции рисования код, который необходимо вставить в код обработчика события щелчка на кнопке. Для создания и запуска данного приложения необходимо выполнить следующие действия:

Рис. 11.5. Рисование на внеэкранной битовой карте и передача ее в элемент управления PiсtureBох

1. Начните новый проект Smart Device в Visual Studio .NET и выберите в качестве целевой платформы Pocket PC.

2. Добавьте в форму Form в окне конструктора форм элементы управления PictureBox и Button.

3. Дважды щелкните на кнопке Button1 в окне конструктора форм; в результате этого будет создан и подключен к кнопке приведенный ниже обработчик событий button1_Click. Введите приведенный в листинге 11.6 код, который реагирует на это событие.

4. Скомпилируйте пример и запустите его на выполнение. Щелкните на кнопке Button1.

С применения подхода, основанного на элементе управления PictureBox, рекомендуется начинать в тех случаях, когда существует необходимость в отображении графических данных. Если такой подход в состоянии удовлетворить нужды вашего приложения – отлично! Пытаться использовать другие, более сложные подходы имеет смысл лишь в тех случаях, когда только что описанный подход вас не устраивает.

Листинг 11.6. Создание изображения на внеэкранной растровой поверхности и передача его в элемент управления PictureBox

//–

//Создать рисунок на растровой поверхности. Переслать его в PictureBox

//–

private void button1_Click(object sender, System.EventArgs e) {

 //Создать новую битовую карту

 System.Drawing.Bitmap myBitmap;

 myBitmap = new System.Drawing.Bitmap(pictureBox1.Width, pictureBox1.Height);

 //–

 //Создать объект Graphics, чтобы иметь возможность рисовать на битовой карте

 //–

 System.Drawing.Graphics myGfx;

 myGfx = System.Drawing.Graphics.FromImage(myBitmap);

 //Закрасить нашу битовую карту желтым цветом

 myGfx.Clear(System.Drawing.Color.Yellow);

 //Создать перо

 System.Drawing.Pen myPen;

 myPen = new System.Drawing.Pen(System.Drawing.Color.Blue);

 //–

 //Нарисовать эллипс

 //–

 myGfx.DrawEllipse(myPen, 0, 0, myBitmap.Width – 1, myBitmap.Height -1);

 //Создать сплошную кисть

 System.Drawing.Brush myBrush;

 //–

 //Нарисовать текст кистью

 //–

 myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);

 //Примечание: Мы используем объект Font из формы

 myGfx.DrawString("Hello!",this.Font, myBrush, 2, 10);

 //–

 //Важно! Очистить все после себя

 //–

 myGfx.Dispose();

 myPen.Dispose();

 myBrush.Dispose();

 //–

 //Указать объекту pictureBox, на необходимость отображения растрового

 //изображения, которое мы только что создали и нарисовали.

 //–

 pictureBox1.Image = myBitmap;

}

Рисование непосредственно в форме

Для рисования в форме существует два способа:

1. Создайте объект Graphics для формы и используйте этот объект для создания нужных рисунков.

2. Подключитесь к функции OnPaint() для формы и получите объект Graphics, который можно будет использовать для рисования.

Создание объекта Graphics для формы и рисование на нем обычно применяются лишь изредка, поскольку в этом случае любой созданный вами рисунок не существует постоянно. Форма с удовольствием предоставит вашему приложению свою поверхность для рисования всего, что вам заблагорассудится, но не будет запоминать нарисованное. Это означает, что если форма по какой-либо причине будет перерисована, то все, что нарисовал ваш код, исчезнет. Поэтому данный метод не годится для графики, которую вы хотите сохранять на экране в течение длительных периодов времени. Так, описанный способ плохо подходит для вычерчивания диаграмм, которые пользователь будет просматривать на своем мобильном устройстве, поскольку ваше приложение не в состоянии контролировать, когда именно отображаемая картинка будет частично или полностью перекрыта другим изображением. Вместе с тем, данный метод может оказаться полезным в тех случаях, когда все экранное изображение все время полностью перерисовывается, как это происходит, например, в играх. Если изображение перерисовывается несколько раз в секунду, то не имеет никакого значения, является ли оно постоянно существующим или нет.

Эта методика рисования проиллюстрирована в листинге 11.7. Для создания и запуска данного приложения необходимо выполнить следующие действия:

1. Начните новый проект Smart Device в Visual Studio .NET и выберите в качестве целевой платформы Pocket PC.

2. Добавьте в форму Form кнопку Button.

3. Дважды щелкните на кнопке Button1 в окне конструктора форм; в результате этого будет создан и подключен к кнопке приведенный ниже обработчик событий button1_Click. Введите приведенный в листинге 11.7 код, который реагирует на это событие.

4. Скомпилируйте пример и запустите его на выполнение. Щелкните на кнопке Button1.

Листинг 11.7. Создание объекта Graphics для формы

//–

//Создает объект Graphics для формы и осуществляет рисование

//–

private void button1_Click(object sender, System.EventArgs e) {

 //Создать объект Graphics для формы

 System.Drawing.Graphics myGfx;

 myGfx = this.CreateGraphics();

 //Создать кисть

 System.Drawing.Brush myBrush;

 myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.DarkGreen);

 //Заполнить прямоугольник

 myGfx.FillRectangle(myBrush, 4, 2, 60, 20);

 //–

 //Важно: Выполнить очистку!

 //–

 myBrush.Dispose();

 myGfx.Dispose();

}

Подключение к запросам Paint для формы обеспечивает возможность принять активное участие в работе низкоуровневого механизма перерисовки данной формы. Когда операционной системе необходимо содействие в восстановлении внешнего вида пользовательского интерфейса, она требует, чтобы окна и элементы управления были перерисованы. В данном случае операционную систему можно уподобить хранителю музея, который осматривает каждое произведение искусства, созданное вашим приложением.

Простое поддержание экспонатов в нормальном состоянии он может обеспечивать самостоятельно, но в более сложных случаях, когда требуется вернуть картинам их первоначальный вид, он вынужден приглашать художников-специалистов. Решение о том, когда именно ваше приложение должно перерисовать элементы своего интерфейса, принимает операционная система; вместе с тем, вы можете обратить внимание операционной системы на тот факт, что форма или элемент управления нуждаются в перерисовке, вызвав функцию Invalidate().

Функции перерисовки вызываются операционной системой тогда, когда ваше приложение нуждается в "ретушировании". Если у вас имеется более или менее статическое графическое изображение, которое вы хотите перерисовывать только тогда, когда в этом возникает необходимость, то это очень удобно реализовать, подключаясь к функции Paint. В то же время, вы должны проанализировать, не удастся ли вам решить те же задачи, используя элемент управления PictureBox; в этом случае вам вообще не приходится иметь дело с какими бы то ни было низкоуровневыми запросами перерисовки.

В листинге 11.8 приведен пример реализации функции перерисовки экрана, которая при поступлении запроса на перерисовку формы рисует прямоугольник и фрагмент текста. Эту функцию следует поместить в код формы. Выполните следующие три эксперимента с использованием этого кода, которые помогут вам лучше понять, как и когда именно функция рисования вызывается операционной системой:

■ Поместите на форму кнопку, которая выполняет вызов this.Update(). Заметьте, что, как правило, это не приводит к немедленному вызову функции OnPaint. Вызов Update() лишь требует, чтобы форма или элемент управления перерисовывались, если имеются области, ставшие недействительными.

■ Поместите не форму кнопку, которая выполняет вызов this.Invalidate(). В результате этого вызова запросы OnPaint перемещаются в начало очереди и обрабатываются сразу же. как только у операционной системы появляется такая возможность, что обычно наступает очень быстро. Выполнение один за другим вызовов this.Invalidate(); this.Update(); приводит к немедленной перерисовке формы.

■ Поместите на форму кнопку, которая отображает элемент управления MessageBox. Начните перемещать окно сообщений (MessageBox) в разные места формы, наблюдая за тем, когда именно инициируются вызовы OnPaint(). В ходе моих экспериментов помещение элемента управления MessageBox над цветным прямоугольником не приводило к вызову OnPaint() (вероятно, в этом случае операционная система сама заботилась о перерисовке формы, не нуждаясь в помощи со стороны приложения), однако такой вызов осуществлялся, когда окно сообщений помещалось над текстом. Таким образом, можно сделать вывод, что операционная система иногда способна самостоятельно выполнять для вас элементарную перерисовку экрана, не нуждаясь в вызовах OnPaint().

Ключевым обстоятельством, которое должно быть вам абсолютно понятным, если вы используете подключение к функциям Paint, является то, что вы не в состоянии контролировать, когда именно будут вызываться эти функции. Вы можете сделать это принудительно, объявив область экрана недействительной, но не имеете никакой возможности контролировать внешние факторы, которые могут инициировать запросы перерисовки экрана. Поэтому крайне важно, чтобы операции перерисовки осуществлялись как можно быстрее и с малыми накладными расходами. Если перерисовка экрана осуществляется очень медленно, то будет создаваться впечатление, что ваше приложение работает в замедленном режиме.

Листинг 11.8. Подключение к функции Paint формы

//Кисти, которые мы хотим кэшировать, чтобы избавить себя

//от необходимости все время создавать их и уничтожать

System.Drawing.Brush m_brushBlue;

System.Drawing.Brush m_brushYellow;

//Ради интереса подсчитаем, сколько раз осуществлялся вызов

int m_paintCount;

//–

//Мы перекрываем обработчики событий Paint наших базовых классов. Это означает,

//что каждый раз, когда форма вызывается для перерисовки самой себя, будет

//вызываться эта функция.

//–

protected override void OnPaint(PaintEventArgs e) {

 //ВАЖНО: Вызвать базовый класс и дать ему возможность

 //выполнить всю необходимую работу по рисованию

 base.OnPaint(e);

 //Увеличить на 1 значение счетчика вызовов

 m_paintCount = m_paintCount + 1;

 //–

 //Важно:

 //Вместо того чтобы создавать объект Graphics, мы получаем его на время

 //данного вызова. Это означает, что освобождать память путем вызова

 //метода .Dispose() объекта – не наша забота

 //–

 System.Drawing.Graphics myGfx;

 myGfx = e.Graphics;

 //–

 //Поскольку эту операцию рисования необходимо выполнить быстро,

 //кэшируем кисти, чтобы избавить себя от необходимости создавать их и

 //уничтожать при каждом вызове

 //–

 if (m_brushBlue == null) {

  m_brushBlue = new System.Drawing.SolidBrush(System.Drawing.Color.Blue);

 }

 if (m_brushYellow == null) {

  m_brushYellow = new System.Drawing.SolidBrush(System.Drawing.Color.Yellow);

 }

 //–

 //Выполнить рисование

 //–

 myGfx.FillRectangle(m_brushBlue, 2, 2, 100, 100);

 myGfx.DrawString("PaintCount: " + m_paintCount.ToString(), this.Font, mbrushYellow, 3, 3);

 //Выход: Объекты, для которых мы должны были бы вызывать метод

 //.Dispose(), отсутствуют.

}

Обработчики событий или перекрытые функции?

Существует еще один способ подключения к запросам Paint. В приведенном выше примере для этого использовался подход, основанный на механизме наследования. Однако обработку событий Paint можно осуществлять и при помощи обработчика событий. Это выполняется точно так же, как и подключение к обработчику событий Click; для получения запросов событий необходимо зарегистрировать функцию. Если вместо перекрытия метода OnPaint() использовать обработчик событий, то в приведенный выше код необходимо внести три вида изменений:

1. Следует изменить имя и сигнатуру метода таким образом, чтобы они соответствовали тому, что требуется для обработчика событий Paint (например, protected void PaintEventHandler(object sender, PaintEventArgs e) вместо protected override void OnPaint(PaintEventArgs e)).

2. Вызов base.OnPaint (e) необходимо удалить, поскольку осуществление этого вызова не входит в обязанности обработчика событий. В действительности, именно базовая реализация base.OnPaint(e) вызывает любой зарегистрированный обработчик событий.

3. В функцию InitializeComponent формы необходимо добавить код для подключения нового обработчика событий. Например, добавьте такой код:

this.Paint += new System.Windows.Forms.PaintEventHandler(this.PaintEventHandler);

InitializeComponent();

Выбирая между обработчиком событий и механизмом наследования, вы можете руководствоваться собственными соображениями. Что касается меня, то для такой низкоуровневой работы, как подключение к обработке запросов перерисовки экрана (Paint), я предпочитаю использовать подход, основанный на механизме наследования, который мне более понятен. Для высокоуровневых событий, например щелчков (Click), я предпочитаю прибегать к подходу, основанному на использовании обработчиков событий, поскольку этот код автоматически генерируется для меня после двойного щелчка на элементе управления в окне конструктора форм.

Реализация пользовательских элементов управления

Инкапсуляция графического кода в пользовательских элементах управления является неплохим способом упаковки графических функциональных возможностей, который обеспечивает повторное использование графики. Реализация таких пользовательских элементов управления весьма напоминает перекрытие функции Paint формы. Этот низкоуровневый подход предназначен для визуализации и поддержки отдельных компонентов пользовательского интерфейса вручную.

Пользовательские элементы управления оказываются полезными в тех случаях, когда вы хотите расширить интерактивность рабочей среды пользователей, имеющих дело с графическими данными. Если нужна диаграмма, которая динамически изменяется и обновляется при выполнении пользователем щелчков на различных ее участках, или сетка, пересчитывающая данные в процессе работы с ними пользователя, то наилучшим решением может быть пользовательский элемент управления. Если все, что вам надо, – это вывод графических данных, которые пользователь будет только просматривать в режиме чтения, то создание пользовательского элемента управления является излишним усложнением. Как и в случае продемонстрированного выше подключения к функции OnPaint(), прежде чем окунаться в реализацию низкоуровневого пользовательского элемента управления, имеет смысл проанализировать, нельзя ли просто обойтись использованием элемента управления PictureBox. Если перед вами стоит задача создания диаграмм с привлекательным внешним видом, которые будут использоваться только в режиме чтения, то вам вполне хватит элемента PictureBox. Если впоследствии вы решите, что приложение действительно нуждается в интерактивном пользовательском элементе управления, то хорошей стартовой площадкой для этого вам послужит тот же класс, который вы использовали для создания статического изображения диаграммы. Начинайте с самого простого и переходите к низкоуровневым парадигмам лишь тогда, когда высокоуровневые парадигмы не могут обеспечить то, что вам необходимо. Используя такой подход, вы сделаете работу быстрее и без той головной боли, которая всегда сопровождает отладку низкоуровневого кода.

Для создания пользовательских элементов управления бывают веские причины, основной из которых является интерактивность. Для большинства элементов управления предусмотрено событие Click, которое позволяет известить приложение о том, что на элементе управления был выполнен щелчок.

В случае гистограмм для разработчика приложения может оказаться желательным знать не только о самом факте щелчка на гистограмме, но и о том, какой именно из столбцов был выделен пользователем. С этой целью пользовательский элемент управления мог бы предусмотреть событие ColumnClick, которое запускается всякий раз, когда щелчок выполняется на связанном с этим элементом столбце. Это событие может предоставлять разработчику конкретную информацию о столбце гистограммы, на котором был выполнен щелчок, в соответствии с чем и будет работать код, отвечающий на это событие. Этот элемент управления может также обеспечивать обратную связь с пользователем устройства, например, путем подсветки выделенного столбца, извещающей пользователя о том, что его выбор воспринят.

Пользовательские элементы управления являются мощной абстракцией, которую вы можете использовать в своих приложениях, но важно не пытаться применять их искусственно, без всякой на то необходимости. Если требуется обеспечить высокую степень интерактивности при взаимодействии конечного пользователя с приложением и/или для разработчика важно иметь возможность работать с детализированными событиями, то решение, основанное на пользовательских элементах управления, заслуживает рассмотрения. В листингах 11.9 и 11.10 представлена очень простая реализация пользовательского элемента управления в .NET Compact Framework. В листинге 11.9 содержится код, предназначенный для самого элемента управления, тогда как в листинге 11.10 – код, который используется для динамического создания экземпляра элемента управления, помещения его в форму и подключения к нему обработчика события. На рис. 11.6 показано выполняющееся на устройстве Pocket PC приложение, в котором присутствует данный нестандартный элемент управления.

НА ЗАМЕТКУ

Существует возможность сделать пользовательский элемент управления видимым на стадии проектирования!

В данном примере пользовательский элемент управления для простоты создается во время выполнения. Чтобы отобразить его для разработчика на стадии проектирования, в результате чего этот элемент управления будет виден в окне конструктора форм подобно любому другому стандартному элементу управления, в приложение следует кое-что добавить. Обсуждение этого вопроса выходит за рамки данной книги, однако соответствующая информация содержится в документации по .NET Compact Framework.Окно сообщения, появляющееся в ответ на запуск события щелчка на пользовательском элементе управления

Рис. 11.6. Окно сообщения, появляющееся в ответ на запуск события щелчка на пользовательском элементе управления

Для создания и запуска данного приложения потребуется выполнить следующие действия:

1. Начните новый проект Smart Device в Visual Studio NET и выберите в качестве целевой платформы Pocket PC.

2. Добавьте в проект новый класс и назовите его myButton. Перейдя в окно редактора кода класса введите код, представленный в листинге 11.9.

3. Перейдите в окно конструктора форм для формы Form1. Добавьте в форму кнопку. Дважды щелкните на кнопке для перехода в окно редактора кода и введите код, представленный в обработчике события button1_Click в листинге 11.10.

4. Введите за кодом обработчика события button1_Click оставшуюся часть кода, представленного в листинге 11.10.

5. Скомпилируйте пример и запустите его на выполнение. Щелкните на кнопке Button1.

Листинг 11.9. Простой пользовательский элемент управления, который изменяет цвета и запускает событие, определяемое пользователем

//Простейший пользовательский элемент управления

public class myButton : System.Windows.Forms.Control {

 //–

 //Объекты, необходимые нам для рисования

 //–

 System.Drawing.Brush m_RectangleBrush;

 System.Drawing.Brush m_TextBrush;

 System.Drawing.Color m_RectangleColor;

 //–

 //Событие, которое мы хотим предоставить на обработку.

 //Это – общедоступный делегат.

 //–

 public event System.EventHandler EventButtonTurningBlue;

 //Конструктор

 public myButton() : base() {

  //ПРИМЕЧАНИЕ: Мы должны написать функцию Dispose() и

  //деструктор, который освобождает память от этих объектов

  //Создать необходимые кисти

  m_RectangleColor = System.Drawing.Color.Black;

  m_RectangleBrush = new System.Drawing.SolidBrush(m_RectangleColor);

  m_TextBrush = new System.Drawing.SolidBrush(System.Drawing.Color.White);

 }

 //–

 //Внутренним откликом на щелчок является

 //повторение трех различных цветов кнопки в цикле

 //–

 protected override void OnClick(System.EventArgs e) {

  //–

  //Важно: Вызвать базовую реализацию. Это

  //обеспечит возможность вызова любого обработчика событий,

  //подключенного к данному элементу управления

  //–

  base.OnClick(e);

  //–

  //Выбрать цвет новой кисти, исходя из цвета старой кисти

  //–

  if (m_RectangleColor == System.Drawing.Color.Black) {

   m_RectangleColor = System.Drawing.Color.Blue;

   //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

   //Запустить событие                                   !

   //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

   if (EventButtonTurningBlue!= null) {

    //Возбудить событие без передачи аргумента

    EventButtonTurningBlue(this, null);

   }

  }

  else

   if (m_RectangleColor == System.Drawing.Color.Blue) m_RectangleColor = System.Drawing.Color.Red;


    Ваша оценка произведения:

Популярные книги за неделю