Использование пользовательских иконок в Windows Mobile 6.5

Оригинал: https://windowsteamblog.com/blogs/windowsphone/archive/2009/08/05/using-custom-icons-in-windows-mobile-6-5.aspx

Автор оригинального поста: Майк Фрэнсис (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-файл, новая иконка на стартовом экране не появится, поскольку после создания ярлыка оболочка для повышения производительности кэширует иконки, и при необходимости достает их из кэша. Кэш же перестраивается при загрузке операционной системы. Существует, однако, обходной путь для решения этой проблемы. Чтобы им воспользоваться, вам нужно:

  1. Удалить ярлык.
  2. Переименовать нужный EXE-файл. Например, hello.exe можно переименовать в hello1.exe.
  3. Создать ярлык, ссылающийся на новый 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.

Перевод: Светлана Шиблева