Использование пользовательских иконок в Windows Mobile 6.5
Автор оригинального поста: Майк Фрэнсис (Mike Francis)
Оригинальный пост опубликован 11 августа 2009 года.
С 10 августа 2009 года изменились требования иконкам в формате PNG для стартового экрана – ранее приложение должно было содержать три иконки разного размера, теперь требуется только одна иконка в формате PNG размером 90x90 пикселей. Этот блог-пост написан с учетом новых требований. В разделе Статическая установка описано, что нужно сделать, чтобы приложение соответствовало этим требованиям.
Если вы уже видели достаточное количество снимков экрана Windows Mobile 6.5, то, скорей всего, согласитесь с тем, что эта версия операционной системы гораздо симпатичнее предыдущей. Успешной эта «косметическая операция» оказалась благодаря добавленной на стартовый экран Window Mobile 6.5 поддержке PNG-файлов. Формат PNG обеспечивает сжатие изображения без потери качества, и включение в приложение иконки в этом формате гарантирует, что пользователи разных устройств будут наслаждаться красивым интерфейсом.
Если вы планируете распространять свое приложение через Windows Marketplace for Mobile (а я не вижу причин, по которым вам нужно выбрать другой путь), следует ознакомиться с документацией по требованиям к размещению. В соответствии с этими требованиями размер иконки для стартового экрана должен быть 90х90 пикселей. В этом блог-посте объясняется, как в Windows Mobile 6.5 Professional использовать PNG-файлы в качестве иконок для стартового экрана (чтобы узнать, как создавать иконки в формате PNG, читайте мой предыдущий блог-пост Создание пользовательских иконок для Windows Mobile 6.5). Примеры кода, на которые я ссылаюсь в этом посте, вы можете взять тут.
Содержание
Стартовый экран: разрешение экрана, DPI и размер иконки
Стартовый экран: разрешение экрана, DPI и размер иконки
Одно из самых существенных усовершенствований, сделанных в Windows Mobile 6.5 Professional – это стартовый экран, который заменил меню «Пуск» из прошлых версий. На стартовом экране расширены возможности навигации – поддерживаются касания (tap), касание и удерживание (tap and hold), прокрутка (pan) и жесты (flick); кроме этого добавлено множество новых опций для упорядочивания и показа элементов.
Если вы уже разрабатываете приложения для Windows Mobile, то должны знать, что в зависимости от разрешения экрана и количества точек на дюйм (DPI) на конкретном устройстве оболочка извлекает из EXE-файла иконку наиболее подходящего размера и показывает эту иконку на стартовом экране. В Windows Mobile версии 6.5 по-прежнему поддерживается эта функциональность, однако сейчас добавлена поддержка иконок в формате PNG. Оболочка не подбирает размер PNG-файла иконки автоматически с учетом DPI устройства, вместо этого установочная DLL выбирает иконку динамически (подробности описаны чуть ниже, в разделе Динамическая установка). Если же вы не хотите создавать для каждого разрешения отдельный PNG-файл, можно сделать всего одну иконку размером 90 x 90 пикселей (фактически, это требование Marketplace), и оболочка уменьшит эту иконку до нужного размера в зависимости от DPI устройства. В таблице ниже показано, как размер иконок зависит от разрешения экрана и DPI устройства.
Версия платформы Windows Mobile | Разрешение экрана | DPI | Ориентация экрана | Маленькая иконка | Большая иконка | Иконка для меню «Пуск» (PNG-файл в версии 6.5) |
6.x Professional | 240x240 | 96 | Квадратный экран | 16x16 | 32x32 | 45x45 |
6.x Professional | 240x320 | 96 | Книжная и альбомная | 16x16 | 32x32 | 45x45 |
6.x Professional | 240x400 | 96 | Книжная и альбомная | 16x16 | 32x32 | 45x45 |
6.x Professional | 320x320 | 128 | Квадратный экран | 21x21 | 43x43 | 60x60 |
6.x Professional | 480x480 | 192 | Квадратный экран | 32x32 | 64x64 | 90x90 |
6.x Professional | 480x640 | 192 | Книжная и альбомная | 32x32 | 64x64 | 90x90 |
6.x Professional | 480x800 | 192 | Книжная и альбомная | 32x32 | 64x64 | 90x90 |
6.x Professional | 480x864 | 192 | Книжная и альбомная | 32x32 | 64x64 | 90x90 |
6.x Standard | 176x220 | 96 | Книжная | 16x16 | 32x32 | N/A |
6.x Standard | 240x320 | 131 | Книжная и альбомная | 22x22 | 44x44 | N/A |
6.x Standard | 240x240 | 131 | Квадратный экран | 22x22 | 44x44 | N/A |
6.x Standard | 240x400 | 131 | Книжная и альбомная | 22x22 | 44x44 | N/A |
6.x Standard | 440x240 | 131 | Альбомная | 22x22 | 44x44 | N/A |
Ключи реестра
Чтобы указать, что на стартовом экране нужно использовать не иконку из EXE-файла, а PNG-файл, в реестре необходимо прописать следующее:
[HKEY_LOCAL_MACHINE\Security\Shell\StartInfo\Start\Phone.lnk]
"Icon"="\Application Data\My App\newphoneicon.png"
Ниже приведен список параметров элемента стартового экрана:
Имя | Тип | Описание |
Name | REG_SZ | Задает подпись для элемента. Если параметр не указан, будет использовано имя файла без расширения. |
Group | REG_DWORD | Определяет, является ли элемент папкой. Значение может принимать значения TRUE (является папкой) или FALSE (не является папкой). Если параметр не указан, система проверит, есть ли у данного ключа реестра подразделы и на основании этого определит, считать ли элемент папкой или нет. |
Icon | REG_SZ | Задает путь к иконке и имя ее файла. Иконка может быть PNG-файлом или же быть встроена в модуль ресурсов. Если параметр не задан, на стартовом экране будет показана иконка, которую оболочка предоставляет по умолчанию. |
Rank | REG_DWORD | Задает ранг элемента. Элементы с более высоким рангом отображаются раньше, чем элементы с более низким рангом. Если параметр не задан, рангу элемента будет присвоено значение 0. |
Замечание по безопасности
Чтобы выполнить описанное выше, требуется создать ключ реестра в разделе HKLM\Security, а это защищенная область реестра. Для записи в защищенную область реестра необходим подписанный CAB-файл. Для приложений, которые будут загружаться на Marketplace, это не является проблемой, поскольку там CAB-файлы подписаны по определению. Как я уже упоминал, информация в этой статье применима только для устройств, работающих под управлением Windows Mobile Professional, тем не менее, если для версии Standard используется тот же самый CAB-файл, необходимо убедиться, что приложение подписано, в противном случае его установка будет невозможна.
Установка
В следующих двух разделах я вкратце расскажу о двух возможных сценариях развертывания приложения – статическом и динамическом.
Статическая установка
Ключ реестра может быть задан как часть конфигурации CAB-файла. Следуя требованиями Marketplace, я буду использовать в качестве иконки для стартового экрана PNG-файл размером 90x90 пикселей. Для этого я добавил вот такой ключ реестра в свой проект Smart Device CAB:
Замечание
Для этого ключа реестра поддерживаются CE strings и строки .INF-файла. На приведенном выше снимке экрана переменная %InstallDir% ссылается на каталог “ \Program Files\SMS Intercept”.
Мой CAB-файл так же содержит иконку AppIcon.png размером 90x90 пикселей и ярлык, имя которого совпадает с именем ключа реестра, описанного выше (SMS Intercept.lnk).
Динамическая установка
Определение DPI
Второй способ – сконфигурировать иконку для стартового экрана динамически, в процессе установки приложения, т.е. скопировать на устройство PNG-файл, размер которого соответствует DPI этого устройства. Для определения DPI устройства и копирования файла мы будет использовать Setup DLL. Вы, возможно, знаете, что утилита WCELOAD, которая устанавливает приложение на устройство, или DLL, которая загружается в этот процесс, возвратят один и тот же DPI – 96, причем вне зависимости от реального DPI устройства. Чтобы обойти эту проблему, мы запустим маленькую вспомогательную утилиту, у которой даже нет пользовательского интерфейса – она просто возвращает DPI устройства. В SDK есть пример (см. ResDLL), где используется подобная техника. Этот пример показывает, как установить DLL с ресурсами, рассчитанными на определенный DPI.
Код утилиты для определения DPI приведен ниже:
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
HDC hdc = ::GetDC(NULL);
INT ans = ::GetDeviceCaps(hdc, LOGPIXELSX);
::ReleaseDC(NULL, hdc);
return ans;
}
Копирование файлов, созданных под конкретное DPI
В нашем динамическом CAB-файле содержится четыре PNG-файла:
45.png
60.png
90.png
AppIcon.png
Определив DPI, мы возьмем подходящий PNG-файл и скопируем его на устройство как AppIcon.png. Файл AppIcon.png резервный и включен на тот случай, если вдруг определить DPI не удастся. После копирования оставшиеся ненужные файлы и утилита для определения DPI будут удалены.
Вот фрагмент кода из примера установочной DLL (SetupDPI). Этот код запускается после того, как приложение уже установлено на устройство, и реализует все сказанное выше:
wsprintf(szFile,_T("%s\\%s"), pszInstallDir, _T("\\GetRealDPI.EXE"));
// Launch DPI Detector
::CreateProcess(szFile, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, &pi);
::WaitForSingleObject(pi.hProcess, 10000);
// DPI is returned in exit code of detector app
::GetExitCodeProcess(pi.hProcess, &nSystemDPI);
::CloseHandle(pi.hProcess);
::DeleteFile(szFile);
// Based on DPI, copy xx.png to AppIcon.png and delete unused files
wsprintf(szOutFile,_T("%s\\%s"), pszInstallDir, szTargetFilename);
for (INT i=0;i<ARRAYSIZE(DPI_Icon);i++) {
wsprintf(szFile,_T("%s\\%s"), pszInstallDir, DPI_Icon[i].lpstrIconSize);
if (DPI_Icon[i].DPI==nSystemDPI) {
::CopyFile(szFile, szOutFile, FALSE);
}
::DeleteFile(szFile);
}
Создание ярлыка
Как я уже упоминал, мы выполняем пост-обработку файлов уже после того, как приложение уже установлено (этим занимается функция Install_Exit). Поскольку картинка с иконкой для стартового экрана задается при создании ярлыка, необходимо создать ярлык в установочной DLL, а не в CAB-файле, как мы делали при статической инсталляции, в противном случае на стартовый экран попадет не PNG-файл, а иконка из EXE-файла. Ниже приведен фрагмент кода для создания ярлыка. Этот код не зависит от языка операционной системы, работающей на устройстве.
// Build lnk filename
PTCHAR pAppDir = wcsrchr(pszInstallDir, '\\');
TCHAR szShortcutPath[MAX_PATH];
// CSIDL_PROGRAMS == \Windows\Start Menu\Programs
SHGetSpecialFolderPath(hwndParent, szShortcutPath, CSIDL_PROGRAMS , false);
wsprintf(szFile,_T("%s%s%s"), szShortcutPath, pAppDir, _T(".lnk"));
// Build exe filename
// CSIDL_PROGRAM_FILES == \Program Files
SHGetSpecialFolderPath(hwndParent, szShortcutPath, CSIDL_PROGRAM_FILES , false);
wsprintf(szOutFile,_T("\"%s%s%s%s\""),
szShortcutPath, pAppDir, pAppDir, _T(".exe"));
SHCreateShortcut(szFile, szOutFile);
Замечание
Обратите внимание, что пример с динамическим CAB-файлом не содержит инструкций для создания ярлыка, как это было в примере со статическим CAB-файлом.
Обход кэширования иконок
Возможно, в процессе разработки вы захотите посмотреть, как выглядят разные варианты иконок, и для этого подменить PNG-файлы. Имейте в виду, что если вы просто замените PNG-файл, новая иконка на стартовом экране не появится, поскольку после создания ярлыка оболочка для повышения производительности кэширует иконки, и при необходимости достает их из кэша. Кэш же перестраивается при загрузке операционной системы. Существует, однако, обходной путь для решения этой проблемы. Чтобы им воспользоваться, вам нужно:
- Удалить ярлык.
- Переименовать нужный EXE-файл. Например, hello.exe можно переименовать в hello1.exe.
- Создать ярлык, ссылающийся на новый EXE-файл.
Ниже приведен XML-файл, содержащий инструкции для утилиты RapiConfig.exe, который как раз это и делает.
<wap-provisioningdoc>
<characteristic type="FileOperation">
<!-- Delete Shortcut -->
<characteristic type="%CE11%\SMS Intercept.lnk" translation="install">
<characteristic type="Delete">
<parm name="ForceDelete"/>
</characteristic>
</characteristic>
<!-- Copy EXE name to new EXE -->
<characteristic type="%CE1%\sms Intercept\sms Intercept1.exe"
translation="install">
<characteristic type="Copy">
<parm name="Source" value="%CE1%\sms Intercept\sms Intercept.exe"
translation="install"/>
</characteristic>
</characteristic>
<!-- Create new shortcut pointing to new EXE name -->
<characteristic type="%CE11%" translation="install">
<characteristic type="MakeDir" />
<characteristic type="SMS Intercept.lnk" translation="install">
<characteristic type="Shortcut">
<parm name="Source" value="%CE1%\sms Intercept\sms Intercept1.exe"
translation="install" />
</characteristic>
</characteristic>
</characteristic>
</characteristic>
</wap-provisioningdoc>
Ярлыки для папки с играми
Если приложение устанавливается в папку с играми, ключ реестра, указывающий на PNG-файл, будет выглядеть так:
[HKEY_LOCAL_MACHINE\Security\Shell\StartInfo\Start\Games\Phone.lnk]
"Icon"="\Application Data\My App\newphoneicon.png"
У разработчиков игр возник вопрос: «Как создать ключ реестра, содержащий путь к папке с играми, чтобы этот путь не зависел от языка операционной системы?» Оболочка будет искать ярлыки (.lnk-файлы) в папках меню «Пуск», следовательно, нужно, чтобы в ключе было прописано локализованное имя папки Games. Для этого потребуется установочная DLL. Пример кода вы можете взять здесь.
Чтобы ярлык был создан именно в папке с играми, необходимо изменить следующую строку в файле SetupDPI.CPP и пересобрать проект:
// Set this to true to create shortcut and
// registry key in the localized 'Games' Folder
BOOL g_bCreateInGamesFolder=FALSE;
Заключение
Теперь вам должно быть понятно, как включать в CAB-файлы иконки в формате PNG для использования на стартовом экране Windows Mobile 6.5.
По данной теме уже подготовлен список часто задаваемых вопросов, вы можете посмотреть его здесь: Start Screen PNG Icon FAQ.
Перевод: Светлана Шиблева
Comments
- Anonymous
June 22, 2010
This can be performed with wap-provisioning. XML configuration file is be attached to CAB file and will be applied after app installation.