52628.fb2
Устройства под управлением Windows Mobile, к которым относятся КПК и смартфоны, все глубже вторгаются в нашу жизнь. Эти устройства очень быстро эволюционируют, обзаводятся более совершенными экранами, увеличивают размер своей дисковой памяти, снабжаются фотокамерами и получают поддержку новых сетевых технологий. Операционная система Windows Mobile 5.0 сделала еще один шаг в развитии этих маленьких, но умных устройств.
В новой платформе появилась поддержка двухмерных и 3D-изображений, появилось больше возможностей обработки мультимедийных файлов, намного проще стало взаимодействовать с фотокамерами и устройствами позиционирования GPS. Причем эта поддержка осуществлена на программном уровне с помощью новых классов и расширения функциональности старых классов.
Компания Microsoft уделяет большое внимание данной платформе, предоставляя разработчикам подробнейшую документацию, примеры и инструменты разработки. Главная страница для Window Mobile 5.0 находится на сайте Windows Mobile по адресу msdn.microsoft.com/mobility/windowsmobile/default.aspx.
На сайте можно скачать необходимые пакеты SDK, позволяющие работать с устройствами под управлением Windows Mobile 5.0. В этой главе будут рассматриваться новые возможности, заложенные в систему Windows Mobile 5.0, которые будут интересны программистам.
В системе Windows Mobile 5.0 появились нововведения, которые увеличивают продуктивность труда программиста. Основные возможности перечислены в следующем списке.
□ Появились новые API, связанные с отображением графики, управлением контактами и взаимодействием с GPS.
□ Продолжено стирание граней между КПК и мобильными телефонами. Код программы, написанный для КПК, легко портируется на смартфоны.
□ Улучшена и добавлена поддержка технологий передачи данных, в том числе прием и посылка SMS и телефонных звонков.
□ В Visual Studio 2005 добавлена поддержка устройств под управлением новой платформы с помощью SDK. Работа с данными более прозрачна, улучшен отладчик ошибок, изменен дизайн графического интерфейса, который позволяет менять ориентацию экрана и его разрешения.
□ Переработан эмулятор.
Теперь программисты могут использовать классы, взаимодействующие с фотокамерами. Это позволяет расширить область приложения камер и использовать их в работе с изображениями и видеозаписями в приложениях. Разработчики могут использовать возможности музыкального плеера Windows Media Player 10 Mobile в своих приложениях. Технология Direct3D позволяет разработчикам создавать более совершенные игры, а библиотека DirectDraw позволяет работать с графикой на более высоком уровне.
Система Windows Mobile 5.0 обеспечивает первоклассную поддержку программистов, работающих с управляемым кодом. Основные нововведения перечислены в следующем списке.
□ Все устройства под управлением Windows Mobile 5.0 поставляются с исполняемой средой .NET Compact Framework 1.0 Service Pack 3, которая записана в независимую память.
□ При помощи управляемого кода осуществляется работа с SMS-сообщениями, контактами Outlook Mobile и телефонными возможностями устройства.
Система Windows Mobile 5.0 обзавелась новыми функциями API. Программисты получили в свое распоряжение новое пространство имен Microsoft.WindowsMobile
с множеством классов, перечислений и делегатов. Кроме того, появились такие пространства имен, как Configuration
, Forms
, PocketOutlook
, PocketOutlook.MessageInterception
, Status
и Telephony
.
Устройства под управлением Windows Mobile постоянно улучшаются. И разработчики требуют новых возможностей для написания красивых и сложных игр. Поэтому в состав системы включена библиотека Direct3D Mobile. Ее можно считать аналогом библиотеки Direct3D API, которая используется в настольных компьютерах.
Для доступа к памяти, улучшенной работе со сложной графикой и видеоматериалами система Windows Mobile 5.0 предлагает воспользоваться DirectDraw API. Эта библиотека также может быть востребована для разработки игр, она является аналогом библиотеки DirectDraw API настольного компьютера.
Все больше устройств выпускается со встроенными камерами. Разработчики могут воспользоваться библиотекой DirectShow API для доступа к возможностям камеры. С помощью соответствующих функций программист может управлять работой камеры, записывать, а потом отображать и проигрывать картинки и видеоматериалы. Библиотека поддерживает множество форматов и является аналогом DirectShow настольного компьютера.
Кроме того, в устройствах все чаще стали использоваться приемники GPS. Раньше писать приложения, работающие с технологиями GPS, было довольно трудно. Нужно было использовать для работы serial API, что требовало хорошего знания основ сетевого программирования. Система Windows Mobile 5.0 во многом облегчила эту задачу при помощи технологии GPS Intermediate Driver. Эта технология предоставляет набор простых функций для доступа к данным GPS. В следующем списке приведены основные функции для работы с GPS Intermediate Driver:
□ GPSOpenDevice
— соединение с GPS Intermediate Driver;
□ GPSCloseDevice
— разрыв связи от GPS Intermediate Driver;
□ GPSGetPosition
— получение текущих координат;
□ GPSGetDeviceState
— получение информации о текущем состоянии устройства.
Разработчики теперь могут запускать и останавливать процесс синхронизации ActiveSync, используя методы ActiveSyncStart
и ActiveSyncStop
.
После выхода системы Windows Mobile 2005 разработчикам стали доступны многие системные возможности, что намного упростило разработку приложений с использованием передовых технологий.
В этом разделе были упомянуты некоторые новые возможности, которые появились в Windows Mobile 5.0. Но их надо рассмотреть на примерах, чтобы лучше понять преимущества новой платформы.
Прежде чем создавать приложения для устройств под управлением системы Windows Mobile 5.0, нужно установить необходимые пакеты SDK. Компания Microsoft предлагает заказать специальный диск с набором всех необходимых пакетов, сделав заказ на странице их сайта, которая располагается по адресу msdn.microsoft.com/mobility/windowsmobile/howto/resourcekit/default.aspx, или самостоятельно скачать эти пакеты с сайта (рис. 10.1).
Рис. 10.1. Веб-страница Windows Mobile 5.0
Следует обратить внимание на то, что существуют отдельные версии SDK для карманных компьютеров и смартфонов. После завершения установки пакеты автоматически интегрируются в среду разработки Visual Studio 2005. В результате разработчик получает новые эмуляторы под Windows Mobile 5.0, в систему будут добавлены новые классы, а справочная система пополнится новыми статьями и примерами.
Также можно скачать локализованные версии эмуляторов. К примеру, страница для загрузки локализованной версии Windows Mobile 5.0 Pocket PC Emulator Images находится по адресу www.microsoft.com/downloads/details.aspx?familyid=EEC33AE3-C129-4C25-ABAA-18E8E842178F&displaylang=en.
Чтобы воочию увидеть особенности Windows Mobile 5.0, надо разработать соответствующее приложение. Для этого следует запустить среду разработки Visual Studio 2005 и создать новый проект. При этом надо выбрать пункт Smart Device project, чтобы создать приложение для мобильного устройства. Затем надо выбрать платформу Pocket PC под управлением Windows Mobile 5.0 (рис. 10.2). После создания проекта Visual Studio 2005 отобразит пустую форму с установленными реальными размерами устройства.
Рис. 10.2. Выбор типа проекта для Windows Mobile 5.0
Система Windows Mobile 5.0 предоставляет разработчику множество новых пространств имен, классов, свойств и событий, с помощью которых он может получить доступ ко многим возможностям, которые ранее приходилось реализовывать только при помощи очень сложного и громоздкого кода на C++ с применением Windows API. Теперь разработчики могут для этих целей применять управляемый код .NET Compact Framework. Имеет смысл поближе познакомиться с этими возможностями.
С помощью пространства имен Microsoft.WindowsMobile.PocketOutlook
разработчик получает доступ к модели Pocket Outlook Object Model (POOM). А имея доступ к POOM, можно легко получить данные из объектов Контакты, Встречи и Задачи. Также можно получить электронные адреса из адресной книги, номера отправки SMS и сообщения. В следующем списке указаны наиболее часто используемые классы.
□ OutlookSession
— представляет собой объект Pocket Outlook для работы с контактами, встречами и задачами. Также можно получить доступ к учетным записям электронной почты и SMS.
□ Appointment
— класс, отвечающий за работу с назначенными встречами. С помощью данного класса можно редактировать данные записи и тип применяемого сигнала.
□ Contact
— класс для работы с контактами. Данный класс поддерживает более 60 свойств.
□ Task
— класс для работы с задачами.
В следующих разделах применение пространства имен Microsoft.WindowsMobile.PocketOutlook
будет рассматриваться на конкретных примерах.
При помощи объектной модели Pocket Outlook Object Model разработчик может добавить новую запись в список намечаемых встреч. Сначала надо создать тестовый проект. Чтобы получить доступ к объектам Pocket Outlook, нужно добавить ссылку на соответствующие сборки. Для этого следует выполнить команду Project►Add Reference
. В диалоговом окне Add Reference
нужно выбрать строки Microsoft.WindowsMobile.Forms
и Microsoft.WindowsMobile.PocketOutlook
(рис. 10.3).
Рис. 10.3. Подключение к проекту сборок
После нажатия кнопки OK выбранные ссылки должны появиться в списке ссылок Solution Explorer
, как показано на рис. 10.4.
Рис. 10.4. Окно Solution Explorer
Теперь в редакторе кода следует добавить объявления для пространств имен Microsoft.WindowsMobile.Forms
и Microsoft.WindowMobile.PocketOutlook
сразу после существующих объявлений. В этом случае появляется возможность работы с различными классами Pocket Outlook. Например, чтобы получить доступ к настройкам для встреч, используется класс Appointment
, как показано в листинге 10.1.
using Microsoft.WindowsMobile.Forms;
using Microsoft.WindowsMobile.PocketOutlook;
private void button1_Click(object sender, EventArgs e) {
// Создаем встречу и устанавливаем детали
Appointment appt = new Appointment();
// Тема для встречи
appt.Subject = "Встреча с тещей";
// Время встречи - 8 марта 2007 в 22 часа
appt.Start = new DateTime(2007, 03, 08, 22, 00, 00);
// Продолжительность встречи - 3 минуты
appt.Duration = new TimeSpan(00, 03, 00);
// Использовать виброзвонок для напоминания
appt.ReminderVibrate = true;
// Повторять напоминание, пока пользователь не отреагирует
appt.ReminderRepeat = true;
// Создаем сессию Outlook
// добавляем встречу в папку встреч Outlook
using (OutlookSession session = new OutlookSession()) {
session.Appointments.Items.Add(appt);
session.Dispose();
}
}
Нужно запустить программу и нажать кнопку Добавить встречу
. После этого можно закрыть приложение, так как свою работу оно закончило. Теперь следует открыть программу Календарь
, которая встроена в систему. В календаре нужно найти дату, которая использовалась в программе. В текущем примере встреча была запланирована на 8 марта 2007 года. Если все сделано правильно, то в указанной дате должна присутствовать запись о новой встрече (рис. 10.5).
Рис. 10.5. Календарь с установленной записью встречи
В этом разделе будет рассмотрен пример, в котором будет добавлена новая запись в объект Контакты. Для этого надо, как и прежде, добавить в проект ссылки на соответствующие сборки Miсrosoft.WindowsMobile.Forms
и Microsoft.WindowsMobilе.PocketOutlook
. А в редакторе кода надо добавить объявления для пространств имен Microsoft.WindowsMobilе.Forms
и Microsoft.WindowsMobile.PocketOutlook
сразу после существующих объявлений.
Теперь можно обращаться к Контактам через объект OutlookSession
. Чтобы добавить новый контакт в коллекцию Контакты, надо разместить на форме кнопку с именем butAddContact
и написать код, приведенный в листинге 10.2.
private OutlookSession session;
public Form1() {
InitializeComponent();
// Создаем экземпляр сессии Pocket Outlook
session = new OutlookSession();
}
private void butAddContact_Click(object sender, EventArgs e) {
Contact contact = new Contact();
contact.FirstName = "Билл";
contact.LastName = "Гейтс";
contact.Email1Address = "billgates@microsoft.com";
contact.Birthday = new DateTime(1955,10,28);
contact.CompanyName = "Microsoft";
contact.WebPage = new Uri("http://www.microsoft.com");
session.Contacts.Items.Add(contact);
}
Код очень прост и практически не требует комментариев. В начале работы создается переменная contact
, в которой можно задавать самые различные параметры. В этом примере использовались только основные свойства. Были указаны имя, фамилия, электронный адрес, день рождения, имя компании и ее веб-страница. После того как новый контакт будет добавлен в список, нужно закрыть сессию при помощи метода Dispose()
.
После запуска приложения следует нажать кнопку Добавить в Контакты
. В результате этого в списке Контакты
появится новая запись (рис. 10.6)
Рис. 10.6. Просмотр списка контактов
Но разработчик может не только добавлять, но и получать информацию из имеющегося элемента списка. Для этого на форму надо поместить список lstContacts
и кнопку butGetInfo
. Прежде чем получить информацию о нужном нам человеке, нужно сначала получить сам список контактов. И только потом, выбрав из этого списка нужную запись, можно получить дополнительную информацию. Для получения полного списка контактов нужно добавить код в обработчик события Form_Load
, как это показано в листинге 10.3.
private void Form1_Load(object sender, EventArgs e) {
// Получаем список контактов
lstContacts.DataSource = session.Contacts.Items;
}
Теперь при загрузке формы список автоматически будет заполнен. Пользователь может выбрать любую запись и получить дополнительную информацию о выбранном контакте. Для этого в событии butGetInfo_Click
создается код, приведенный в листинге 10.4.
private void butGetInfo_Click(object sender, EventArgs e) {
// Получим информацию о выбранном контакте
session.Contacts.Items[lstContacts.SelectedIndex].ShowDialog();
}
Когда пользователь выделит интересующую его запись и нажмет кнопку Получить информацию, на экран будет выведено стандартное диалоговое окно с информацией о выбранной записи.
Удалить контакт из списка еще проще, чем создать его. На форму надо добавить еще одну кнопку butDelContact
, с которой будет связан код, приведенный в листинге 10.5.
private void butDelContactClick(object sender, EventArgs e) {
// Удаляем выбранный контакт
session.Contacts.Items[lstContacts.SelectedIndex].Delete();
}
Также из приложения можно вызвать стандартное окно выбора контакта, используемое программой Pocket Outlook. Теперь совсем не обязательно закрывать нашу программу и открывать окно контактов, как это было сделано при добавлении новой записи в список контактов.
Стандартное окно имеет некоторые дополнительные возможности, которые могут пригодиться разработчикам. Доступ к данному окну осуществляется через класс ChooseContactDialog
, как показано в листинге 10.6.
private void butShowContactsClick(object sender, EventArgs e) {
ChooseContactDialog contactDialog = new ChooseContactDialog();
// Прячем пункт меню Новый контакт
contactDialog.HideNew = true;
// Выводим диалоговое окна на экран
contactDialog.ShowDialog();
// Показываем выбранный контакт
MessageBox.Show(contactDialog.SelectedContactName, "Выбранный контакт");
}
Кроме получения доступа к списку контактов и добавления новых встреч, разработчик может также отсылать сообщения по электронной почте или через SMS.
Для этих целей используются соответствующие пространства имен Microsoft.WindowsMobile.PocketOutlook.EmailAccount
и Microsoft.WindowsMobile.PocketOutlook.SmsAccount
. Классы из этих пространств имен позволяют легко интегрировать отправку сообщений в ваши приложения. Например, класс EmailAccount
позволяет создавать электронные письма и присоединять к ним файлы.
В следующем примере демонстрируется вызов диалогового окна ChooseContactDialog
для выбора нужного адресата из списка контактов, которому будет отправлено электронное письмо. Приложение создаст сообщение, в коде будет указана и тема письма.
Также в письмо будет добавлен вложенный файл, после чего сообщение будет отправлено выбранному ранее лицу. Все эти действия проиллюстрированы листингом 10.7.
private void butSendEmail_Click(object sender, EventArgs e) {
ChooseContactDialog contactDialog = new ChooseContactDialog();
contactDialog.Title = "Выберите контакт для отправки email";
if (contactDialog.ShowDialog() == DialogResult.OK) {
EmailMessage message = new EmailMessage();
message.To.Add(
new Recipient(contactDialog.SelectedContact.Email1Address));
message.Subject = "С днем рождения";
message.BodyText =
"Уважаемый Владимир Владимирович! Поздравляю вас с днем рождения!
Посылаю вам открытку с видами Петербурга. Ваша Люда.";
message.Attachments.Add(
new Attachment(@"\My Documents\piter.jpg"));
using (OutlookSession session = new OutlookSession()) {
session.EmailAccounts[0].Send(message);
session.Dispose();
}
}
}
После запуска программы и нажатия кнопки Послать письмо
будет открыто стандартное окно Контакты
, где можно выбрать адресата. После выбора получателя по его электронному адресу будет отправлено электронное письмо с заданным содержанием.
Если надо отправить электронное письмо адресату, который не внесен в адресную книгу, то пример надо переработать. Новый код приведен в листинге 10.8.
private void butSendEmail2_Click(object sender, EventArgs e) {
Recipient recipient = new Recipient("alexander.klimoff@gmail.com");
EmailMessage msg = new EmailMessage();
// Кому письмо
msg.To.Add(recipient);
// Тема письма
msg.Subject = "О вашей книге";
// Текст письма
msg.BodyText = "Спасибо за книгу";
msg.Send("ActiveSync");
}
Отправка SMS-сообщения с помощью новых возможностей тоже очень и очень проста. Эти сообщения весьма популярны у владельцев мобильных телефонов. Раньше для отсылки и приема SMS
приходилось использовать неуправляемый код, очень сложный для восприятия неопытным программистом. Теперь создать код, отсылающий сообщение, не сложнее, чем написать само сообщение, что иллюстрирует листинг 10.9.
private void butSendSMS_Click(object sender, EventArgs e) {
ChooseContactDialog contactDialog = new ChooseContactDialog();
contactDialog.Title = "Выберите получателя";
if (contactDialog.ShowDialog() == DialogResult.OK) {
// Создаем SMS-сообщение
SmsMessage message = new SmsMessage(
contactDialog.SelectedContact.MobileTelephoneNumber,
"Купи хлеба. Жена");
message.RequestDeliveryReport = true;
// Посылаем сообщение
message.Send();
}
}
В этом примере SMS-сообщение отсылалось адресату, чья запись уже имелась в адресной книге. Если же требуется отправить сообщение, не используя окно Контакты
, то придется воспользоваться другим кодом.
Здесь я хочу сделать небольшое отступление и открыть вам большой секрет. Разработчик может посылать SMS-сообщения самому себе при помощи эмулятора! Если послать SMS-сообщение из эмулятора на телефонный номер 4250010001, то оно вернется на эмулятор (рис. 10.7).
Итак, необходимо отправить SMS-сообщение человеку, чья учетная запись не отражена в списке Контакты
. Для этого используется код, приведенный в листинге 10.10.
При отладке приложения в эмуляторе надо использовать целевое устройство типа «Phone Edition». Если проверять пример в обычном эмуляторе, то будет отображено сообщение об ошибке «Could not load sms.dll». Впрочем, это не удивительно. Если эмулятор не имеет телефонных функций, то как можно отправлять SMS-сообщение?
private void butSendSMS2_Click(object sender, EventArgs e) {
SmsMessage message = new SmsMessage();
// Номер получателя
message.To.Add(new Recipient("4250010001"));
// Текст сообщения
message.Body = "Позвони домой";
// Посылаем сообщение
message.Send();
}
Результат выполнения этого кода приведен на рис. 10.7.
Рис. 10.7. Прием SMS-сообщения
Итак, мы научились отправлять SMS-сообщения из своей программы. Но было бы неплохо научить приложения принимать подобные сообщения. Для приема сообщений существует пространство имен MessageInterception
, которое находится в сборке Microsoft.WindowsMobilе.PocketOutlook
.
Следует заметить: можно организовать прием сообщений таким образом, что запущенное приложение будет перехватывать нужные сообщения, содержащие ключевые слова. Причем система даже не покажет окно, уведомляющее о прибытии перехваченного события.
С этой возможностью стоит познакомиться ближе. После создания нового проекта InterceptionSMS_CS
, нужно добавить на форму кнопку для отсылки SMS-сообщения, флажок chkAlert
для установки флага срочности и текстовое поле, в котором будет содержаться текст SMS-сообщения. Затем надо задать ссылки на уже применявшиеся ранее сборки Microsoft.WindowsMobile
и Microsoft.WindowsMobile.PocketOutlook
. Код, отвечающий за обработку принятых сообщений, приведен в листинге 10.11
using Microsoft.WindowsMobile;
using Microsoft.WindowsMobile.PocketOutlook;
using Microsoft.WindowsMobile.PocketOutlook.MessageInterception;
// Объявляем переменную
private MessageInterceptor smsInterceptor;
private void smsInterceptor_MessageReceived(object sender,
MessageInterceptorEventArgs e) {
// Обработка входящего сообщения
MessageBox.Show("К вам пришло срочное сообщение");
}
private void butSendSMS_Click(object sender, EventArgs e) {
SmsMessage message = new SmsMessage();
// Номер получателя
message.To.Add(new Recipient("4250010001"));
// Текст сообщения
if (chkAlert.Checked) {
// Если взведен флажок, то добавляем слово Срочно!
message.Body = "Срочно! " + txtSMSText.Text;
} else {
message.Body = txtSMSText.Text;
}
// Посылаем сообщение
message. Send();
}
private void Form1_Load(object sender, EventArgs e) {
smsInterceptor =
new MessageInterceptor(InterceptionAction.NotifyAndDelete, true);
smsInterceptor.MessageCondition =
new MessageCondition(MessageProperty.Body,
MessagePropertyComparisonType.StartsWith, "Срочно", true);
smsInterceptor.MessageReceived +=
new MessageInterceptorEventHandler(smsInterceptorMessageReceived);
}
При помощи ключевого слова using
было объявлено несколько пространств имен, также была добавлена переменная smsInterceptor
, после чего можно было объявлять функцию обработки сообщения smsInterceptor_MessageReceived
. При получении SMS-сообщения с определенным текстом эта функция выводит соответствующую строку.
Но самое интересное происходит в событии Form_Load
. Как только устройство принимает SMS-сообщение, оно перехватывается приложением для дальнейшей обработки. Если сообщение начинается словом «Срочно», то пользователь предупреждается о прибытии важного сообщения, после чего это сообщение удаляется. Подобное поведение обеспечивает параметр NotifyAndDelete
.
После запуска приложения на форме будут отображены текстовое поле и флажок. После ввода текста сообщения нужно нажать кнопку Послать SMS
. Код отправки сообщения позаимствован из предыдущего примера. Система должна отреагировать на прибытие нового сообщения с помощью специального уведомления, которое мы видели при разборе предыдущего примера (см. рис. 10.7).
Теперь следует повторить операцию. Только на этот раз надо взвести флажок Пометить как срочное
. В этом случае при отправке сообщения в начало текста вставляется дополнительное слово «Срочно». После нажатия кнопки приложение должно перехватить прибытие SMS-сообщения, так как теперь оно содержит ключевое слово, которое определялось в параметре StartWith
. Как только это произойдет, сообщение будет удалено, а пользователь получит уведомление о прибытии срочного сообщения (рис. 10.8). Но следует помнить, что для перехвата сообщения приложение должно быть запущено.
Рис. 10.8. Прием срочного сообщения
Данный пример предоставляет разработчику весьма широкие возможности. Представьте себе, что ваша компания рассылает своим сотрудникам особым образом отформатированные сообщения. Программа может обработать эти сообщения и автоматически создать новые записи в списках Контакты или Встречи. И теперь сотруднику достаточно только взглянуть на экран, чтобы увидеть приятную новость, что сегодня компания выдает премию, за которой нужно подъехать в офис.
Для примеров, связанных с SMS-сообщениями, нужно использовать эмуляторы и устройства, имеющие возможность работы с SMS.
Разработчик может использовать возможности телефонии при помощи класса Miсrosoft.WindowsMobile.Telephony.Phone
. Используя метод этого класса Talk
, можно программно набрать нужный телефонный номер. При использовании класса Phone
перед началом работы нужно установить ссылку на сборку Microsoft.WindowsMobile.Telephony
. Пример использования этого метода приведен в листинге 10.12.
using Microsoft.WindowsMobile.Telephony;
// Объявляем переменную Phone
phone = new Phone();
// Набираем номер
// Перед набором запрашиваем подтверждение
phone.Talk("4255551212", true);
Обратите внимание на набираемый номер. С помощью данного номера разработчик может делать звонок на эмуляторе. Эмулятор сначала запросит подтверждение набора номера (рис. 10.9) и затем будет звонить по указанному номеру.
Рис. 10.9. Запрос набора указанного номера
После подтверждения будет установлено соединение с неизвестным абонентом 4255551212 (рис. 10.10).
Рис. 10.10. Соединение с абонентом
В Windows Mobile 5.0 появилась новая технология, получившая название State and Notifications Broker. Использование данной технологии позволяет управлять состоянием устройства. Раньше для доступа к системным настройкам приходилось использовать неуправляемый код. Но теперь можно использовать возможности технологии State and Notification Broker.
При помощи этой технологии можно обрабатывать информацию о различных состояниях устройства и постоянно отслеживать изменения этих состояний. Если будут обнаружены какие-либо изменения, то система сообщит об этом приложению. Использование данных технологий открывает широкие возможности для увеличения функциональности программ. Например, разработчик сможет определять силу сигнала от сотовой станции, значение текущего заряда батареи, узнать, подключен ли крэдл, отслеживать состояние ActiveSync, определять наличие подключаемой клавиатуры, фотокамеры и гарнитуры. Также с помощью этой технологии можно определять число Bluetooth-соединений, отображать список текущих сетевых соединений, получать информацию об ориентации экрана. Разработчик может получать информацию о следующей назначенной встрече (Appointment), обрабатывать информацию о проигрываемом музыкальном файле, получать информацию о контактах и количестве не прочитанных электронных писем, SMS-сообщений и пропущенных телефонных звонков.
Чтобы использовать возможности State and Notifications Broker в приложениях, надо добавить ссылку на сборку Microsoft.WindowsMobile.Status
. Также необходимо добавить ссылку на сборку Microsoft.WindowsMobile
. После этого программа готова использовать классы пространства имен Microsoft.WindowsMobile.Status
.
Конечно, без наглядного примера обойтись просто нельзя. Предположим, что нас интересует информация о владельце устройства и необходимо отслеживать изменение этой информации. Для этого надо создать новый проект и добавить на форму элемент Label
. Этого вполне достаточно для работы примера. Также необходимо добавить ссылки на сборки Microsoft.WindowsMobile
и Microsoft.WindowsMobile.Status
при помощи команды меню Project►Add Reference
. Нас интересует изменение электронного адреса владельца устройства. Для этого используется код, приведенный в листинге 10.13.
using Microsoft.WindowsMobile.Status;
private SystemState sysState;
sysState = new SystemState(SystemProperty.OwnerEmail, true);
sysState.Changed += new ChangeEventHandler(sysStateChanged);
private void sysState_Changed(object sender, ChangeEventArgs args) {
lblOwnerEmail.Text = SystemState.OwnerEmail;
}
Протестируем пример. После запуска приложения с ним не нужно ничего делать. Следует нажать кнопку Пуск
и выбрать пункт меню Настройка
. На вкладке Личные
нужно активировать пиктограмму Данные о владельце
. В соответствующем текстовом поле Эл.почта
следует изменить указанный адрес электронной почты. Если теперь вернуться к приложению, то можно будет увидеть, что изменилось содержимое надписи lblOwnerEmail
. Таким образом, программа автоматически отреагировала на изменение данных в настройках системы. Конечно, можно получать данные об электронном адресе владельца в принудительном порядке. Для этого используется код, приведенный в листинге 10.14.
private void butGetEmail_Click(object sender, EventArgs e) {
//Получим email владельца устройства
lblOwnerEmail.Text = SystemState.OwnerEmail;
}
Да, с помощью этого кода можно получить интересующие данные, но в этом случае нельзя узнать, когда эти данные изменятся. Придется через определенные промежутки времени проверять, не изменился ли адрес у владельца устройства.
Но стоит вернуться к примеру уведомления об изменении электронного адреса владельца устройства. Отслеживанием изменений в системе занимается класс SystemState
. Данный класс содержит множество статичных свойств для получения различных настроек системы. Но кроме этого класс SystemState
содержит очень важное событие Changed
. Для обработки данного события нужно сначала создать экземпляр класса SystemState
и передать ему соответствующее свойство:
sysState = new SystemState(SystemProperty.OwnerEmail, true);
Затем нужно присоединить делегат к новому экземпляру события Changed
:
sysState.Changed += new ChangeEventHandler(sysState_Changed);
А уже после этого можно перехватывать изменение состояния нужных параметров:
private void sysState_Changed(object sender, ChangeEventArgs args) {
lblOwnerEmail.Text = SystemState.OwnerEmail;
}
Пример с электронным адресом был приведен лишь для ознакомления. На самом деле, с помощью соответствующих свойств можно получить доступ более чем к ста системным настройкам. Наиболее внимательные читатели могут заметить, что State и Notifications Broker порой дублируют функциональность, которую можно воспроизвести при помощи других средств. Например, текущую ориентацию экрана можно узнать с помощью функции API GetSystemMetrics
или с помощью вызова Screen.PrimaryScreen.Bounds
. А информацию о заряде батареи можно узнать с помощью функции GetSystemPowerStatusEx
.
Но зачем понадобилось создавать еще одну дополнительную возможность извлечения информации? Причин для такого шага было несколько. Прежде всего, новые возможности удобны и просты. В предыдущем примере было показано, что для получения электронного адреса владельца устройства достаточно вызвать одно соответствующее свойство. Для получения других значений также вызываются соответствующие свойства. Причем названия этих свойств говорят сами за себя и не требуют наличия под рукой справочной литературы.
Для закрепления материала нужно дополнить программу еще несколькими примерами получения различных свойств. Можно добавить отображение уровня заряда батареи, текущего состояния батареи, наличия радиоприемника и фотокамеры, названия сотового оператора и определение текущей ориентации экрана. Все это делает код, приведенный в листинге 10.15.
private void butGetInfo_Click(object sender, EventArgs e) {
lstInfo.Items.Add("Название оператора: " + SystemState.PhoneOperatorName);
lstInfo.Items.Add("Наличие радио: " + SystemState.PhoneRadioPresent);
lstInfo.Items.Add("Наличие камеры: " + SystemState.CameraPresent);
lstInfo.Items.Add("Ориентация экрана " + SystemState.DisplayRotation);
}
private void butBattery_Click(object sender, EventArgs e) {
// Уровень заряда батареи
BatteryLevel batteryLevel = SystemState.PowerBatteryStrength;
BatteryState batteryState = SystemState.PowerBatteryState;
string strBatteryLevel = "Уровень заряда";
switch (batteryLevel) {
case BatteryLevel.VeryLow:
strBatteryLevel = "Уровень заряда: Очень низкий (0-20%)";
break;
case BatteryLevel.Low:
strBatteryLevel = "Уровень заряда: Низкий (21-40%)";
break;
case BatteryLevel.Medium:
strBatteryLevel = "Уровень заряда: Средний (41-60%)";
break:
case BatteryLevel.High:
strBatteryLevel = "Уровень заряда: Высокий (61-80%)";
break;
case BatteryLevel.VeryHigh:
strBatteryLevel = "Уровень заряда: Очень высокий (81-100%)";
break;
}
// Состояние батареи
string strBatteryState = "Состояние батареи: ";
if ((batteryState & BatteryState.Normal) == BatteryState.Normal)
strBatteryState += "Нормальное";
if ((batteryState & BatteryState.NotPresent) == BatteryState.NotPresent)
strBatteryState += "Батарея отсутствует ";
if ((batteryState & BatteryState.Charging) == BatteryState.Charging)
strBatteryState += "Заряжается ";
if ((batteryState & BatteryState.Low) == BatteryState.Low)
strBatteryState += "Низкий заряд ";
if ((batteryState & BatteryState.Critical) == BatteryState.Critical)
strBatteryState += "Критическое";
MessageBox.Show(strBatteryLevel + "\n" + strBatteryState);
}
Система Windows Mobile 5.0 обеспечивает еще более глубокую поддержку мультимедиа, чем предыдущие версии операционных систем. Теперь разработчики имеют возможность напрямую работать с фотокамерой, встраивая в свои программы взаимодействие с камерой и обработку картинок и видеороликов. Технология Microsoft DirectShow дает возможность управлять потоковыми мультимедийными материалами. Программа Microsoft Windows Media Player 10 Mobile позволяет интегрировать функциональность музыкального плеера в собственные приложения. Технология Microsoft DirectDraw предоставляет доступ к графической системе на более высоком уровне, а библиотека Microsoft Direct3D позволяет создавать очень сложные динамические игры, используя управляемый код. Эти возможности стоит рассмотреть подробнее.
В операционной системе Windows Mobile 5.0 стало поразительно легко работать с коллекцией фотографий и рисунков. При помощи стандартного диалогового окна выбора рисунка можно легко выбрать нужный рисунок. Доступ к стандартному окну выбора рисунка осуществляется при помощи класса Microsoft.WindowsMobile.Forms.SelectPictureDialog
.
Но лучше работу с диалоговым окном выбора картинки рассмотреть на примере. На форме надо разместить метку lblSelectedPicture
и графическое поле picSelectImage
. Не забудьте перед началом создания приложения установить ссылку на пространство имен Microsoft.WindowsMobile.Forms
. Соответствующий код приведен в листинге 10.16.
private void butSelectPicture_Click(object sender, EventArgs e) {
SelectPictureDialog selectPictureDialog = new SelectPictureDialog();
// Задаем фильтр
selectPictureDialog.Filter = "Рисунки(*.BMP;*.JPG)|*.BMP;*.JPG";
// Задаем папку для обзора
selectPictureDialog.InitialDirectory = Windows";
// Заголовок для диалогового окна
selectPictureDialog.Title = "Выберите рисунок";
if (selectPictureDialog.ShowDialog() = DialogResult.OK &&
selectPictureDialog.FileName.Length > 0) {
// Получим расширение выбранного файла
string fileExtension = Path.GetExtension(selectPictureDialog.FileName);
// Выводим путь выбранного файла
lblSelectedPicture.Text = "Выбранный файл: " +
selectPictureDialog.FileName;
// Если выбран файл JPG, то выводим на экран
if (fileExtension.ToLower() == ".jpg")
picSelectedImage.Image = new Bitmap(selectPictureDialog.FileName);
}
}
В начале работы создается объект SelectPictureDialog
, а затем для него задаются нужные свойства. С помощью свойства Filter
ограничивается выбор файлов. Пользователь может загружать изображения с расширениями .BMP
и .JPG
. Затем указывается стартовая папка. Строго говоря, в Windows Mobile для хранения картинок используется папка Мои картинки
. Но приложение, работающее с изображениями, может использовать свою собственную папку.
Рис. 10.11. Выбор изображения
Потом в заголовке диалогового окна выводится текст, поясняющий пользователю дальнейшие действия. Это был минимально необходимый при использовании класса SelectPictureDialog
код.
Если пользователь выбрал картинку и нажал на кнопку OK
, то надо распознать выбранный файл. С помощью метода Path.GetExtension
можно получить расширение файла. В текстовой метке lblSelectedPicture
отображается полный путь к выбранному файлу, а в графическом поле picSelectedImage
размещается сама картинка. Но для этого она должна иметь расширение .JPG
(рис. 10.11).
Следует обратить внимание на то, что диалоговое окно выбора рисунка позволяет выбирать картинки из любой папки устройства.
Мобильные устройства все чаще снабжаются фотокамерами. Причем многие пользователи отсутствие камеры на смартфоне считают очень большим недостатком. Система Windows Mobile 5.0 предлагает поддержку работы с камерой, чтобы разработчики могли использовать ее возможности в своих приложениях.
Диалоговое окно захвата изображения позволяет интегрировать фотографии и видеоматериал в приложения. При этом разработчик получает возможность управлять поведением камеры. Доступ к возможностям камеры осуществляется при помощи класса Microsoft.WindowsMobile.Forms.CameraCaptureDialog
. Класс CameraCaptureDialog
очень похож на класс SelectPictureDialog
.
Свойство Mode
позволяет управлять режимом съемки. Камера может работать, как обычный фотоаппарат, что задается значением CameraCaptureMode.Still
, или записывать видеоролик. Диалоговое окно вызывается методом ShowDialog
, который возвращает значение, показывающее, как было закрыто окно. Если пользователь выбрал кнопку OK
, то возвращается значение DialogResult.OK
. Имя выбранной картинки записывается в свойство FileName
. В листинге 10.17 приведен пример работы с фотокамерой.
private void butPhotoMake_Click(object sender, EventArgs e) {
CameraCaptureDialog cameraCaptureDialog = new CameraCaptureDialog();
cameraCaptureDialog.Owner = this;
cameraCaptureDialog.Title = "Фотограф";
cameraCaptureDialog.Mode = CameraCaptureMode.Still;
if (cameraCaptureDialog.ShowDialog() == DialogResult.OK &&
cameraCaptureDialog.FileName.Length > 0) {
PictureBox.Image = new Bitmap(cameraCaptureDialog.FileName);
MessageBox.Show("Снято!");
}
}
Для записи видеоролика используется аналогичный способ, но надо поменять режим съемки. Так, для записи видеоматериала вместе со звуком используется режим VideoWithAudio
. Пример записи видеоролика приведен в листинге 10.18.
private void butCaptureClick(object sender, EventArgs e) {
CameraCaptureDialog cameraCapture = new CameraCaptureDialog();
cameraCapture.Owner = null;
cameraCapture.InitialDirectory = @"\My Documents":
cameraCapture.DefaultFileName = @"test.3gp";
cameraCapture.Title = "Камера - Демонстрация";
cameraCapture.VideoTypes = CameraCaptureVideoTypes.Messaging;
cameraCapture.Resolution = new Size(176, 144);
// Лимит в 10 секунд для видео
cameraCapture.VideoTimeLimit = new TimeSpan(0, 0, 10);
cameraCapture.Mode = CameraCaptureMode.VideoWithAudio;
if (DialogResult.OK == cameraCapture.ShowDialog()) {
MessageBox.Show("Картинка или видео успешно записаны в:\n{0}",
cameraCapture.FileName);
}
}
Легко заметить, что эти два примера практически идентичны. Существует еще режим записи видео без звукового сопровождения. В этом случае для свойства Mode
задается значение CameraCaptureMode.VideoOnly
. Если перед вызовом метода ShowDialog
использовать свойство DefaultFileName
, то указанное имя будет использоваться как имя файла для записи новых фотографий или видеоматериала. Свойство InitialDirectory
позволяет указать папку, в которой будут сохраняться отснятые материалы. Свойство Resolution
позволяет задать разрешение снимаемого материала, что иллюстрирует следующая строка кода:
cameraCaptureDialog.Resolution = new Size(320, 240);
Свойство StillQuality
позволяет установить качество сжатия для фотографий при помощи перечисления CameraCaptureStillQuality
. Используемые значения перечислены в следующем списке:
□ High
— указывает на наилучшее качество картинки с минимальным сжатием;
□ Normal
— среднее качество картинки;
□ Low
— высокая степень сжатия, плохое качество.
Свойство VideoTimeLimit
позволяет установить максимальную продолжительность записи видеоматериала. По умолчанию используется нулевое значение, что означает отсутствие временного ограничения. В этом случае запись съемки будет вестись до тех пор, пока позволяют ресурсы системы. Свойство VideoTypes
позволяет выбрать тип видеоматериала. На устройствах под управлением Windows Mobile 5.0 используется видеоматериал двух типов — Multimedia Messaging Service (MMS) и Windows Media Video (WMV).
Примеры доступа к объектам Pocket Outlook рассматривались применительно к карманным компьютерам. Но теперь надо воссоздать их, опираясь уже на смартфоны. Сам код примеров останется практически неизменным. Но при этом изменится логика управления программой. Как уже говорилось ранее, управление в смартфонах сводится к обработке событий для пунктов меню.
Сначала рассмотрим пример с использованием объекта Pocket Outlook. На этот раз надо получить доступ к списку встреч (Appointment). Перед началом изучения примера вам нужно убедиться, что список событий имеет хотя бы одну запись. Если там ничего нет, то следует создать несколько записей самостоятельно.
После создания нового проекта на форме надо разместить элемент ListView
. Свойство View
должно получить значение Details
. В коллекции Columns
надо задать заголовки Дата
, Время
и Тема
(рис. 10.12). Прежде всего потребуется задать переменную для экземпляра сессии Outlook. Сразу же после вызова метода InitializeComponent
в конструкторе формы объявляем экземпляр для сессии PocketOutlook
, как показано в листинге 10.19.
Рис. 10.12. Внешний вид приложения
private OutlookSession session;
public Form1() {
InitializeComponent();
// Создаем экземпляр сессии Pocket Outlook
session = new OutlookSession();
}
Теперь программист получил доступ к коллекции событий через объект OutlookSession
. Для коллекции Appointment
создается соответствующая переменная, при помощи которой можно получить каждый элемент коллекции, что иллюстрирует код, приведенный в листинге 10.20.
private void menuAppointments_Click(object sender, EventArgs e) {
AppAppts = session.Appointments.Items;
// Проходим через все элементы коллекции
foreach (Appointment appt in AppAppts) {
// Создаем объект ListViewItem
lvItems = new ListViewItem();
// Разделяем полученные результаты по колонкам
lvItems.Text = appt.Start.ToShortDateString();
lvItems.SubItems.Add(appt.Start.ToShortTimeString());
lvItems.SubItems.Add(appt.Subject);
// Добавляем в ListView
lvContacts.Items.Add(lvItems);
}
// He забываем закрыть сессию PocketOutlook
session.Dispose();
}
Также мы можем получить информацию об имеющихся контактах. Но в этом случае рассматривать код не нужно, так как он полностью повторяет пример для КПК.
Рассматриваемый пример покажет, как можно посылать электронное письмо любому человеку, чья запись присутствует в списке Контакты. При этом разработчик может присоединять к отправляемому сообщению файл.
В этом примере будет применен другой подход к дизайну программы. Так как средства навигации в смартфоне довольно скудны, желательно сводить к минимуму число нажатий на клавиши. Например, одна и та же клавиша может запускать разные функции.
После создания нового проекта SendEmailSmartphone_CS
на форме надо разместить текстовое поле txtContact
, в котором будет отображаться выбранный электронный адрес.
Также потребуется изменить код из предыдущего примера. Нужно переместить код из обработчика события menuSoftKey1_Click
в отдельный метод SelectContact()
. Это делается для того, чтобы можно было более гибко настраивать программу под свои нужды. Соответствующий код приведен в листинге 10.21.
private void SelectContact() {
// Создаем экземпляр окна выбора контактов
ChooseContactDialog contactDial = new ChooseContactDialog();
// а также убираем возможность создания новых контактов
contactDial.HideNew = true;
// выводим диалоговое окно на экран
if (contactDial.ShowDialog() == DialogResult.OK) {
selContact = contactDial.SelectedContact;
txtContact.Text = selContact.FileAs;
menuSoftKey1.Text = Послать;
}
}
Следует обратить особое внимание на строку
menuSoftKey1.Text = "Послать";
Когда пользователь выберет пункт Контакты
, а затем нужный контакт, то текст в пункте меню menuSoftKey1
меняется на строчку Послать
. Также надо добавить новый пункт меню для очистки текстовых полей. Это позволит пользователю выбрать новый контакт для отправки письма. Надо открыть файл Form1.cs
в дизайнере формы. На правой стороне меню к уже имеющемуся пункту Выход
следует добавить новый пункт меню Очистить
. Созданный пункт получит имя mnuClear
. Код для метода mnuClear_Click
приведен в листинге 10.22.
private void mnuClear_Click(object sender, EventArgs e) {
txtContact.Text = string.Empty;
menuSoftKey1.Text = "Контакты";
}
Это позволить очистить текстовое поле и в пункте меню menuSoftKey1
отобразить строку Контакты
.
Теперь можно писать функцию, отправляющую электронное письмо. В примере сообщение будет отправляться с вложенными файлами. Для примера можно использовать одну из картинок, входящих в состав Windows Mobile 5.0.
Для отправки письма используется класс EmailMessage
. Чтобы использовать этот класс в нашем примере, надо сначала установить ссылку на пространство имен System.Messaging
, выполнив команду меню Project►Add Referenc
e. После этого можно пользоваться данным пространством имен при помощи ключевого слова using
:
using System.Messaging;
Код метода SendEmail()
, который будет отвечать за отправку письма, приведен в листинге 10.23.
private void SendEmail() {
// Создаем экземпляр класса EmailMessage
EmailMessage message = new EmailMessage();
// Тема письма
message.Subject = "Поздравление";
// Текст письма
message.BodyText = "Поздравляю с Днем Варенья!";
// Выбираем адресата
Recipient client = new Recipient(selContact.Email1Address);
message.To.Add(client);
// добавляем в письмо вложенный файл
Attachment image = new Attachment(@"\My Documents\My Pictures\Flower.jpg");
message.Attachments.Add(image);
message.Send("ActiveSync");
txtContact.Text = string.Empty;
menuSoftKey1.Text = "Контакты";
}
Итак, в методе SendEmail
объявляется и создается экземпляр класса EmailMessage
. В свойствах Subject
и BodyText
задаются тема и текст письма. Электронный адрес из выбранного контакта записывается в свойстве EmailMessage.То
. Для этого создается экземпляр класса Recipient
и передается свойство selContact.Email1Address
.
Теперь можно добавить в письмо вложенный файл. Для этого создается экземпляр класса Attachment
, которому в конструктор передается полное имя выбранного файла. После этого свойству EmailMessage.Attachment
передается значение экземпляра.
Теперь для отправки письма все готово. Следует вызвать метод message.Send
и очистить текстовое поле. Также надо восстановить в меню строку Контакты
. Так как для menuSoftKey1
используются два метода, SendEmail
и SelectContact
, то нужно определиться, когда какой метод следует использовать. Для этого нужно получить значение свойства menuSoftKey1.Text
, как показано в листинге 10.24.
private void menuSoftKey1Click(object sender, EventArgs e) {
if (menuSoftKey1.Text == "Послать")
SendEmail();
else
SelectContact();
}
Настало время проверить нашу программу. После запуска приложения надо выбрать адресата, которому предназначено письмо. Для отображения окна выбора контакта следует нажать кнопку Soft Key 1
. Можно выбрать любой контакт из имеющегося списка. После этого в текстовом поле появится выбранный контакт. При этом пункт меню обретет название Послать
.
Затем надо снова нажать кнопку Soft Key 1
. Кнопка Soft Key 1
примет первоначальный вид, в меню будет отображаться строка Контакт, а текстовое поле будет очищено. Выходим из программы. Но нам надо убедиться, что письмо было отправлено. Поэтому следует перейти на экран Сегодня
и нажать кнопку Пуск
, после чего активировать пиктограмму Сообщения
. В появившемся списке надо выбрать пункт Эл.п. Outlook
, а из пункта Меню
перейти в подменю Папки. Затем осталось перейти в папку Исходящие
. В ней должно находиться новое сообщение.
В блоге blogs.msdn.com/anthonywong/, который ведет Энтони Вонг (Anthony Wong), я нашел несколько интересных заметок, рассказывающих об исправленных ошибках или улучшенных возможностях, которые стали доступны в Windows Mobile 5.0.
На устройствах под управлением Windows СЕ 4.X метод Directory.Exists()
по-разному обрабатывал имена путей, которые заканчивались обратным слэшем. В качестве примера можно рассмотреть следующее выражение:
Directory.Exists("\\temp");
Это выражение возвращает значение True
, если папка temp
существует. Добавим в предыдущее выражение символ обратной черты.
Directory.Exists("\\temp\\")
Теперь данный метод возвратит False
, даже если папка существует. На устройствах под управлением Windows Mobile 5.0 платформа .NET Compact Framework исправила это противоречие, и теперь метод Directory.Exists()
возвращает True
вне зависимости от наличия замыкающего обратного слэша.
На старых устройствах также отсутствовали конвертеры графических изображений, что не позволяло сохранять изображения в форматах GIF, JPG или PNG. Разработчикам приходилось довольствоваться только форматом BMP. Причем при написании программы среда разработки позволяла писать неправильный код, выводя соответствующие подсказки. Однако при вызове этого метода программа выводила сообщение об ошибке. В Windows Mobile 5.0 теперь поддерживаются все четыре формата.