Программирование мобильных устройств на платформе .NET Compact Framework
Шрифт:
Формат GIF (Graphics Interchange Format — формат графического обмена) можно считать предшественником формата PNG. GIF-файлы также предлагают сжатие без потерь, но ограничены использованием 256 цветов. Из-за этого ограничения формат GIF не годится для хранения фотографических изображений. GIF-файлы интенсивно использовались при создании Web-страниц в Internet в первые годы своей популярности и по этой причине продолжают находить широкое применение и в наши дни.
Битовые образы (bitmaps) хранят несжатые данные изображений. Формат сохраняемых в BMP-файлах данных аналогичен формату хранения битовых образов в памяти. Помимо того, что не требуется выполнять дополнительную работу по распаковке файлов, использование BMP-файлов не имеет никаких преимуществ, если не считать их широкой доступности.
В том, что касается разработки приложений для .NET Compact Framework, JPG- файлы больше всего подходят для фотографических изображений, а PNG-файлы — для битовых образов, требующих максимально достоверной передачи изображений. Ситуации, в которых требуется полная, с точностью до пикселя, достоверность передачи изображений, обычно встречаются тогда, когда некоторое изображение будет использоваться с определением одного цвета пикселей в качестве прозрачного. Области прозрачности могут применяться при создании сложных рисунков, когда одни рисунки "просматриваются" через другие,
Как поступать в тех случаях, когда источником изображения с высоким разрешением является само мобильное устройство
Многие современные мобильные телефоны выпускаются с установленными в них цифровыми камерами, позволяющими получать фотографии. При этом размеры некоторых изображений могут превышать 1 мегапиксель (1000×1000 пикселей), и можно не сомневаться, что эта тенденция будет только усиливаться. Как и фотографии, получаемые с помощью цифровых фотокамер, разрешение таких изображений значительно превосходит те пределы, выше которых нормальный вывод изображений на экраны устройств становится невозможным; эти изображения предназначены для просмотра на экранах с большими размерами (настольные компьютеры) или для вывода на печать. Загружать и удерживать в памяти битовые образы таких размеров слишком расточительно, однако из-за проблем задержек и устойчивости связи бессмысленно пытаться отсылать картинку на сервер для ее уменьшения, чтобы получить ее обратно на устройстве в уменьшенном виде. Решение, которое позволяет работать с изображениями, характеризующимися высоким разрешением, и вместе с тем сохраняет возможность эффективного управления памятью устройства, состоит в следующем:
1. Загрузите изображение с высоким разрешением в память. Примечание. Если изображение достаточно велико, то такая загрузка на деле может оказаться невозможной; в этом случае должно быть каким-то образом получено изображение с более низким разрешением, причем это может делаться даже на стадии получения самого изображения. Изображение с более низким разрешением может храниться вместе с полномасштабным изображением.
2. Сразу же создайте в памяти копию изображения, уменьшенного до размеров, с использованием которых оно будет отображаться на экране. Благодаря этому количество пикселей в битовом образе изображения, хранящемся в памяти, значительно уменьшится.
3. При первой же возможности удалите исходное изображение, имеющее высокое разрешение, и освободите занимаемую им память.
Если предоставляемый вашей средой выполнения каркас приложения поддерживает сохранение изображений, то может оказаться целесообразным сохранить и кэшировать уменьшенное изображение для последующего использования, чтобы вашему приложению не пришлось сталкиваться с проблемами вре´менных всплесков используемых объемов памяти и процессорного времени в связи с загрузкой большого изображения. Очень важно свести объем памяти, постоянно используемой вашим приложением, к минимуму, а это означает, что не следует хранить в памяти дополнительные пиксельные данные, которые вы не сможете отобразить. При работе с цифровыми фотографиями это позволит сэкономить мегабайты памяти программы и в случае мобильных устройств заметным образом положительно скажется на производительности вашего приложения.
Существуют два способа интеграции управляемой среды выполнения с графикой и моделью пользовательского интерфейса хоста. Среда выполнения может использовать готовые библиотеки элементов пользовательского интерфейса, поддерживаемые операционной системой, или же привлечь для выполнения этой работы собственные библиотеки.
.NET Compact Framework, выполняющаяся на устройствах, использующих операционные системы Windows СЕ, Pocket PC и Smartphone, предоставляет визуализацию большинства своих элементов управления пользовательского интерфейса и управление ими операционной системе. Под этим подразумевается что элементу управления Window платформы .NET Compact Framework соответствует элемент управления Window операционной системы Windows СЕ, элементу управления ListView платформы .NET Compact Framework — элемент управления ListView операционной системы Windows СЕ, элементу управления Button платформы .NET Compact Framework — элемент управления Button операционной системы Windows СЕ и так далее. Преимущества такого подхода обусловлены несколькими причинами:
1 Производительность. Специалисты по разработке операционных систем затратили много времени на проектирование и настройку элементов управления своих пользовательских интерфейсов. Добиться аналогичной производительности при перерисовке всех окон и элементов управления и обеспечить надлежащее управление их взаимодействием с пользователем путем самостоятельной реализации этих возможностей очень трудно.
2. Внешний вид и нюансы поведения. Элементы управления .NET Compact Framework обладают теми же поведенческими характеристиками, что и элементы управления базовой системы Windows. Реализация пользовательского интерфейса сопряжена с необходимостью принятия множества мелких решений наподобие: "Как именно должны прорисовываться пиксели при визуализации элемента управления? Что должно происходить, если выделить блок текста и нажать клавишу забоя, ввести букву, выполнить двойной щелчок на слове?" Добиться точного воспроизведения внешнего вида и нюансов поведения пользовательского интерфейса очень трудно, а вместе с тем люди очень чувствительны к малейшим отклонениям от того, к чему они привыкли.
3. Размер кода. Повторная реализация кода для перерисовки и манипулирования элементами управления, который уже предусмотрен в операционной системе, приведет к ненужному увеличению размера кода каркаса приложения. Привлечение для этих целей того, что уже имеется в операционной системе, позволяет сэкономить значительный объем рабочего пространства среды выполнения.
Несмотря на то что в .NET Compact Framework, выполняющейся на устройствах с операционными системами Pocket PC, Smartphone или Windows СЕ, реализация большинства элементов пользовательского интерфейса делегируется операционной системе, это вовсе не означает, что вы не имеете возможности создать совершенно новый элемент управления средствами каркаса приложения. В .NET Compact Framework можно создать графический элемент управления с нуля, и это делается в тех случаях, когда в базовой операционной системе аналогичный элемент управления отсутствует. Эту работу может выполнить конечный разработчик, но для таких элементов управления, как GridControl, она была выполнена и в .NET Compact Framework.
Описанный подход применяется не во всех управляемых средах выполнения. Некоторые из них получают от базовой операционной системы лишь пространство для рисования и самостоятельно организуют рисование элементов управления и манипулирование ими. Преимуществом такого подхода является то, что он позволяет обеспечить единообразие внешнего вида и поведения интерфейса на каком бы устройстве приложение ни выполнялось. К недостаткам реализации нестандартных пользовательских интерфейсов относятся увеличение размера приложения и накладных расходов, связанных с необходимостью выполнения дополнительной обработки, а также риск того, что внешний вид и нюансы поведения элементов управления не будут совпадать с аналогичными свойствами элементов управления базовой операционной системы. Суть дела здесь состоит в достижении некоего разумного компромисса.
Если .NET Compact Framework переносится на другую платформу (в процессе ее проектирования такая возможность заранее предполагалась), то она должна будет либо использовать
возможности пользовательского интерфейса базовой операционной системы, либо предоставить свою реализацию этих элементов управления в виде библиотек на основе собственного или управляемого кода. По своим возможностям встроенной поддержки элементов управления пользовательского интерфейса операционные системы различных устройств существенно отличаются друг от друга, так что объем работы, которую при этом придется выполнить, и выбор стратегии проектирования оказываются в высшей степени зависящими от характеристик конкретной целевой операционной системы.Стратегии проектирования высокопроизводительного графического кода
Код, предназначенный для обработки графики, целесообразно рассматривать отдельно от кода высокоуровневого пользовательского интерфейса. Обычно в коде пользовательского интерфейса используются высокоуровневые абстракции, предлагаемые операционной системой или средой программирования. Примерами подобных абстракций могут служить такие понятия, как элементы управления Button, ListBox, ListView, Panel или Grid. На самом нижнем уровне элементы управления реализуются в виде последовательностей инструкций рисования и низкоуровневого взаимодействия с операционной системой и пользователями. Разработчикам приложений почти никогда не приходится иметь дело с элементами управления на этом самом низком уровне абстракции. Обычно, используя элементы управления пользовательского интерфейса, разработчик полагается на уже организованное для него оптимизированное выполнение базовых операций, связанных с рисованием и поддержкой элементов управления; задача разработчика заключается лишь в том, чтобы наиболее эффективным способом использовать эти элементы управления на более высоком уровне абстракции. В отличие от этого, при работе с графикой разработчик должен специально продумать, как должны решаться низкоуровневые задачи рисования и каким образом можно обеспечить их наиболее эффективное выполнение.
С позиций абстрагирования код высокоуровневого пользовательского интерфейса аналогичен организации связи в сети с использованием запросов и ответов по протоколу HTTP; в то же время, графический код аналогичен организации связи на уровне сокетов или же пакетов. Как и в случае сетевых коммуникаций, во всех возможных случаях лучше использовать высокоуровневые абстракции. Высокоуровневые абстракции легко использовать, они эффективны для большинства задач и надежно протестированы. Эффективная работа с низкоуровневыми программными средствами, например, графическими библиотеками, требует более глубокого понимания того, что при этом происходит, и соответствующего активного вмешательства в ход событий, и должна сопровождаться тщательным анализом того, какую пользу с точки зрения эффективности это может принести приложению. Графический код выглядит и работает иначе, чем код пользовательского интерфейса.
Поскольку конечной целью всей низкоуровневой работы с графикой является предоставление отдельных частей многофункционального пользовательского интерфейса, между низкоуровневым графическим кодом и кодом пользовательского интерфейса в какой-то точке должно быть налажено взаимодействие. Можно почти не сомневаться, что создаваемая вами графика будет сосуществовать с такими высокоуровневыми компонентами пользовательского интерфейса, как элементы управления Button, Menu или ListView. Управление всем пользовательским интерфейсом посредством только низкоуровневого графического кода может быть оправданным лишь в самых редких случаях по той простой причине, что приложение ничего не выиграет, если будет самостоятельно прорисовывать элементы управления и обрабатывать низкоуровневое взаимодействие с пользователем. Вместо этого следует прибегать к гораздо более эффективному подходу, в соответствии с которым разработчики используют для обслуживания пользовательского интерфейса готовые библиотеки проверенных на практике функций и привлекают графические функции для управления лишь теми элементами пользовательского интерфейса, которые испытывают в этом крайнюю необходимость. Для этого следует использовать тщательно продуманные модели, описывающие, каким образом код высокоуровневого пользовательского интерфейса и низкоуровневый графический код должны сочетаться друг с другом.
В документации к .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.