Using Custom Icons in Windows Mobile 6.5

Using Custom Icons in Windows Mobile 6.5

  • Comments 26
  • Likes

Update: Updated sample code, you can download it here. Read all about it here.

If you’ve seen the any of the plethora of Windows Mobile 6.5 screen shots, likely you’d agree that it looks much better than previous versions. A component of this ‘face lift’, is support for PNG files in the Window Mobile 6.5 Start screen. Including a nicely rendered PNG file as your application icon is important to ensure the highest quality user experience across different devices.

If you plan to distribute your application via Windows Marketplace for Mobile (and I don’t know why you wouldn’t) the requirements document requires that you use a 90 x 90 Start screen icon for your application. This post will cover how to use PNG files as icons in the Windows Mobile 6.5 Professional Start screen. For information on creating PNG icons, see my previous post on Creating Custom Icons for Windows Mobile 6.5. The sample code I will be referring to in this post can be found here.


Start Screen: Resolution / DPI and Icon Size
Registry Keys
Setup: Static or Dynamic
Cached Icons
Games Shortcuts Folder

Start Screen: Resolution / DPI and Icon Size

The Start Screen is one of the huge improvements in Windows Mobile 6.5 Professional. This replaces the Start Menu in previous versions. The improvements include: enhanced touch screen navigation (tap, tap and hold, pan, and flick) and more options for organizing and presenting Start menu items. image

If you are an experienced Windows Mobile developer, you know that depending on the DPI and resolution of the device, the shell extracts the appropriately sized icon from the EXE for display in the Start screen. Windows Mobile 6.5 still supports this; however now it also supports the display of PNG file icons. The shell does not automatically select the size of the PNG icon based on the device DPI. This dynamic selection of the icon is done in a setup dll. (See dynamic setup below.) However, if you do not want to provide a separate PNG file for each DPI, you can provide one (90x90) and the shell will scale down the icon as necessary, depending on the DPI of the device. (In fact, this is the Marketplace requirement.) The table below illustrates the DPI / resolution and icon size relationship. 


Windows Mobile Platform Resolution DPI Orientation Small Icon Large Icon Start Menu PNG Icon (6.5)
6.x Professional 240x240 96 Square 16x16 32x32 45x45
6.x Professional 240x320 96 Portrait & Landscape 16x16 32x32 45x45
6.x Professional 240x400 96 Portrait & Landscape 16x16 32x32 45x45
6.x Professional 320x320 128 Square 21x21 43x43 60x60
6.x Professional 480x480 192 Square 32x32 64x64 90x90
6.x Professional 480x640 192 Portrait & Landscape 32x32 64x64 90x90
6.x Professional 480x800 192 Portrait & Landscape 32x32 64x64 90x90
6.x Professional 480x864 192 Portrait & Landscape 32x32 64x64 90x90
6.x Standard 176x220 96 Portrait 16x16 32x32 N/A
6.x Standard 240x320 131 Portrait & Landscape 22x22 44x44 N/A
6.x Standard 240x240 131 Square 22x22 44x44 N/A
6.x Standard 240x400 131 Portrait & Landscape 22x22 44x44 N/A
6.x Standard 440x240 131 Landscape 22x22 44x44 N/A

Registry Keys

To have the Start screen use a PNG file instead of an icon embedded in the EXE, you need to provide the following registry entries:

"Icon"="\Application Data\My App\newphoneicon.png"

Here are the definitions of the value pair settings:

Name Type Description
Name REG_SZ Specifies the display name of the item. If the value is not specified, the file name will be displayed without the extension.
Group REG_DWORD Specifies whether the item is a folder. The value can be set to TRUE or FALSE. Set the value to TRUE to indicate that the item is a folder. If the value is not specified, the system will determine the Group value by verifying whether the registry key has any subkeys.
Icon REG_SZ Specifies the path and file name where the icon is located. The icon can consist of a PNG file or an embedded icon resource module. If this value is not specified, the default icon of the shell will be used.
Rank REG_DWORD Specifies the rank of the item. An item that specifies a larger value for Rank will be displayed before items that specify a lower value. If this item is not specified, the Rank will be set to 0.
Security note: This requires creating a registry key underneath HKLM\Security. This is a protected registry location. To write to a protected registry key, the CAB file needs to be signed. This will not be a problem for Marketplace applications, since by definition they are signed. As mentioned, this article only applies to Windows Mobile Professional devices. However, if you use the same CAB for a Standard device installation, you will need to make sure your application is signed privileged, otherwise setup will fail. To avoid having to sign your CAB privileged (and incur the extra Marketplace approval time this requires) you can use the dynamic setup mentioned in this post. Be sure to include in your setup dll, the conditional creating of the StartInfo registry key and copying of the PNG file, and only do these steps if installing on a Professional device.  See the sample code here for an example on how to do this.


In the next two sections, I’ll walk through two deployment scenarios, static and dynamic.

Static Setup:

You can specify the registry key as part of your CAB file configuration. Per the Marketplace requirements, I will use a 90 x 90 PNG file as the Start screen icon. In my Smart Device CAB project, I have added the following registry key:


Note: This registry key supports ‘CE strings’ and .INF file strings. Above %InstallDir% maps to the ‘\Program Files\SMS Intercept’ directory.

My CAB file also includes the (90x90) AppIcon.png and a shortcut of the same name as the registry key above (SMS Intercept.lnk). See below:


Dynamic Setup:

Detecting DPI:

Another way to configure the Start screen icon is dynamically: copying the appropriately sized PNG file based on the DPI of the device. We will use a setup dll to detect the DPI, and copy the appropriate PNG. You may know that WCELOAD (the EXE that process the CAB file) or a DLL that is loaded into its process, will return the same DPI (96) no matter the actual DPI of the device. To workaround this, we launch a very small helper EXE that quickly exits, without UI, and returns the DPI. The SDK sample ResDLL uses this technique as well as demonstrates how to install DPI specific resource DLLs. Here is the code used to detect the 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;
Copy DPI specific files:

Our dynamic CAB file contains four png files:

Based on the DPI detected, we copy the appropriate PNG file to the filename AppIcon.png. AppIcon.png is included in the CAB as a fallback in case our DPI detect logic fails. The unused icons and the DPI detect EXE are deleted.

Here is a code snippet from the sample setup dll (SetupDPI) implementing this:

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);

// 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);

Create Shortcut:

As mentioned, we do the post-processing of the files after the CAB is installed (in the Install_Exit function). That is, because the icon image in the Start screen is created when the shortcut is created (see the cached icons section below), we need to create the shortcut in the setup dll instead of in the CAB file as was done in the static CAB sample. Otherwise, the Start screen will use an icon extracted from the EXE instead of the PNG file. Here is the language independent code that creates the shortcut:

// 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);
     szShortcutPath, pAppDir, pAppDir, _T(".exe"));

SHCreateShortcut(szFile, szOutFile);
Note that the dynamic CAB sample does not not contain the file system declaration that creates a shortcut as the static sample CAB does.

Cached Icons

During development, you will likely want to change the PNG file as you experiment will different artwork. You will notice that if you overwrite the PNG file, the Start screen will not use the new image. This is because when the Start screen shortcut is created, the icon image is cached by the shell. Thereafter for better performance, the shell retrieves the image from the cache. The cache is rebuilt a boot time. Here is one possible workaround:

  1. Delete the shortcut
  2. Rename (or copy) target EXE name. For example, rename hello.exe to hello1.exe
  3. Recreate shortcut pointing to new EXE name.

Here is provisioning XML that does this. You can run this using RapiConfig.exe:

<characteristic type="FileOperation">
<!-- Delete Shortcut -->
<characteristic type="%CE11%\SMS Intercept.lnk" translation="install">
<characteristic type="Delete">
<parm name="ForceDelete"/>

<!-- Copy EXE name to new EXE -->
<characteristic type="%CE1%\sms Intercept\sms Intercept1.exe"
<characteristic type="Copy">
<parm name="Source" value="%CE1%\sms Intercept\sms Intercept.exe"

<!-- 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" />

Games Shortcuts Folder

If we were installing this application into the Games folder, the key pointing to the PNG file would look like this:
"Icon"="\Application Data\My App\newphoneicon.png"

Game developers have raised the question, “How do I create the Games registry key in a language independent way?” Without the Games folder, this key is language independent. However, the shell will look for the shortcut (.lnk) files in the directories below Start, therefore we need to setup this key using the localized name for Games. This requires a Setup DLL. See the sample code for this post here.

To have your shortcut created in the Games folder, you must change the following line in the SetupDPI.CPP and rebuild the project:

// Set this to true to create shortcut and 
// registry key in the localized 'Games' Folder
BOOL g_bCreateInGamesFolder=FALSE;


You should now understand how to configure your CAB file projects to include PNG files as icons in the Windows Mobile 6.5 Start screen.

For a list of frequently asked questions on this topic see here: Start Screen PNG Icon FAQ

You must be logged in to comment. Sign in or Join Now
  • Looking through your code sample I keep coming across this idiom:

    WCHAR buf[sizeof(WCHAR) * 40];

    UINT cBuf = ARRAYSIZE(buf);

    Which makes a buffer 80 characters wide, not 40.

    Is this necessary?

  • jaybo_nomad - Regarding the issue of your PNG not being displayed untill you do a soft reset, see my blog post here on how to resolve it.



  • Two questions:

    1. Using the static version of "SMS Intercept" the .png icon isn't displayed until a soft reset happens.  Is there any way around this problem?

    2. Although I've tried to exactly duplicate the settings in SMS Intercept, my own application never uses the .png icon in a PPC 6.5 emulator (even after a soft reset).  I did get it to work once by using the full path in the Icon registry link (ie. "\Program Files\My Dir\MyApp.png") instead of using the substitution string (ie. "%InstallDir%\MyApp.png"), but this won't be portable.  I've verified that the .inf does correctly define %InstallDir%.  Does it matter if the .CAB is compressed?

  • Yes. In the Smart Device CAB project properties (using Visual Studio) this is set as 'Manufacturer' property. In the .INF file, this maps to 'Provider' and 'Manufacturer'. For example:


    Signature="$Windows NT$"


    CESignature="$Windows CE$"





  • redsolo
    4 Posts

    @mike (and others)

    When you say manufacturer, you mean the Provider key that is set in a cabwiz .inf file.

  • redsolo
    4 Posts

    @mike (and others)

    When you say manufacturer, you mean the Provider key that is set in a cabwiz .inf file.

  • Redsolo-

    Regarding the PNG not appearing in the Start screen after installation, I have seen this if the Manufacturer name in the CAB file contains a space. (See the Manufacturer property in the CAB file Visual Studio project.) For Example: Setting the Manufacturer property to ‘ABC Company’ will reproduce this problem. A workaround is to remove the space. (e.g. ‘ABC_Company ‘). I have not seen this problem if the shortcut is created programmatically in a setup dll.  I would not recommend adding the XML for renaming an EXE to the CAB file. This is only for testing purposes. If you want to try different PNG files for your icon, try uninstalling and then reinstalling with a CAB that contains the new PNG file.



  • redsolo
    4 Posts

    Thanks for (finally) providing this information, but I still have one problem with the solution. Just after I have installed my application using a cab, the icon in the start menu uses the icon from our exe (ie its a 64x64 upscaled). When I reboot the device, the icon will be correctly using thesupplied  png file.

    Is it possible to use the XML as specified in the post, in a cab installation? I have tried to add the provisioning XML to the CAB using "cabwiz ... /postxml", but that does not seem to work. Am I doing it wrong, or is just not possible?

  • Bbj-

    I have updated the blog post and sample code here:

    I included a Games Folder Shortcuts section that describes how to setup the PNG icon in the Games folder in a language independent way. Unfortunately when the .LNK file is moved via the FileOperation CSP, the registry key is recreated (instead of moved). Consequently, the Icon settings do not appear in the new registry location. However, when moving the link via File Explorer it works as expected.

  • bbj
    8 Posts

    Thanks again Mike, were nearly there I think.

    Have continued this in the Windows Marketplace Forum which is probably a more sensible place for this discussion.

    (You already answered the duplicate question - apologies for duplicate but were just getting upto speed with the mixture of online resources available.)

  • mrmckeb -

    See the Static CAB sample project in the attached sample code. This requires no code.



  • mrmckeb
    26 Posts

    Seriously, how do I do this in C#? I'm a novice... but I'm creating an application for 6.5 that I had hoped to get onto the marketplace.

    Can you please explain this Mike?

  • Bbj – You can temporarily create the shortcut in the Programs folder, and have the registry key point to this. Then using the MoveFile API, move the .lnk file to the ‘Games’ (%CE14%) folder. The shell will then detect the move of the shortcut and move the registry key under the Games key.  The PNG icon will display as it should.

  • bbj
    8 Posts


    Thanks for the hints re using XML to create the shortcut, that works fine.

    The next issue we have run into is the following:

    In the original blog it says:

    "Registry Keys

    To have the Start screen use a PNG file instead of an icon embedded in the EXE, you need to provide the following registry entries:

    [HKEY_LOCAL_MACHINE\Security\Shell\StartInfo\Start\Phone.lnk]"Icon"="\Application Data\My App\newphoneicon.png"

    The problem:

    If we have created the .LNK in the Games folder, (as its a game) presumably the registry key needs to be ".....\Startinfo\Start\Games\Appname.lnk"  - which is where for example the Solitaire and Bubble Breaker place their entries - looking at the Registry via the Remote Registry Editor. (I.e. an additional level of folder 'Games' is required).

    The problem arises on say a French machine where the Registry entry needs to use locale specific text. Looking at the Registry for French Emulator + built in games it seems we need to create


    Do you have any suggestions as to how to do this correctly + in a locale independant way?

    Creating Registry entry via the [RegKeys] in the .INF/CAB does not seem viable as there is no %CExx% that only refers to the 'Games' part of a path.

    Creating Registry entries via code in the setupDll does not appear to be very easy as there does not appear to be a mechanism to determine the locale specific 'Games' (Jeux) folder - there is no CSIDL_ to get at the games folder name etc.

    Can you clarify what happens if a user moves the created shortcut file ?. I.e. how does moving the shortcut affect the registry key given they are presumably related.

    I.e. if we create shortcut in Programs folder + reg key .....\Startinfo\Start\Appname.lnk" then user moves the shortcut to the games folder, do the correct icons still get displayed. Testing on emul seems to suggest it does, if so perhaps there is no sigificance in the additional Games folder in the registry key name...

  • Enjoy your video and audio everytime and everywhere

    Do you still not to know how to rip DVD to the formats supported by your portable devices so you can enjoy DVD movies anywhere and at any time?

    Do you still not to know how to convert video from one popular video format to another?

    Now, it’s time to get rid of the problems

    Blu-Ray Ripper can help you solve all this problems

    Rip Blu-Ray and general DVD to almost all the popular video and audio formats with high quality and converting speed.

    This iToolsoft Blu-Ray DVD Ripper helps you share your Blu-Ray and general DVD movie or music on more portable players, like iPod, iPhone, Gphone, Apple TV, PSP/PS3, Xbox, Mobile Phone, Mp3 Player.

    Only get the part you like by setting the begin and end time for the conversion through the preview window and also can capture the beuatilful pictures of movie.

    Key Features:

    1,Rip Blu-ray DVDand general DVD movie to many output formats:Video:AVI, ASF, MPEG, MP4, WMV, MKV, MOV, FLV, SWF, RM, 3GP, etc. Audio: AAC, AC3, MP3, OGG, WAV, WMA, M4A, RA, Aiff, AU.

    2,Rip with high definition and highest rate.

    3,Enjoy Blu-Ray and general DVD on more multimedia devices: Apple TV, iPod, iPhone, GPhone, PSP\PS3, XBox, Mobile Phone, Windows Mobile.□Set detailed parameter to rip your Blu-Ray and general DVD into luxurious visual sumptuous dinner for all

    4,Shutdown PC automatically when conversion is complete.

    5,Preview movie artwork to the fullest.

    6,So if you want to share your Blu-Ray and general DVD movie or music on more portable players and capture the beuatilful pictures of movie, just use this software. What more you can get a discount if you buy it here:   also you can download it here and just enjoy it. Good luck!

  • bbj -

    Unfortunately there is no CSIDL for the Games folder. However there is a CE String:

    %CE14% - resolves to the localized: \Windows\Start Menu\Programs\Games

    To use the CE string, replace the SHCreateShortcut call with a call to DMProcessConfigXML, passing in XML that will create the shortcut in this folder. See the blog post section 'Cached Icons' for sample XML that creates the shortcut.

  • bbj
    8 Posts

    In the dynamic setup version a shortcut is created in the code with:

    // CSIDL_PROGRAMS == \Windows\Start Menu\Programs

    SHGetSpecialFolderPath(hwndParent, szShortcutPath, CSIDL_PROGRAMS , false);

    Thats fine, however this presupposes all shortcuts are to be placed in the 'Start menu\Programs' folder.

    Prior to 6.5 consumers knew that (and I recall it being a general recommendations that) games should place their shortcut in the 'Start Menu\Programs\Games' folder.

    The problem is that we cannot locate any CSIDL that represents the 'Programs\Games' folder + are pretty sure the location varies by locale - so cant reasonably hard code.

    So is there a CSIDL that references 'Start meun\Programs\Games' , if not are there any recommendations as to how to do this in a locale independant way, or do we no longer put games in the 'Games' folder and leave it upto the consumer to move things around ?


  • Thanks for all the feedback. We've complied a FAQ here:

  • >>Wow, a system more complex than the desktop that requires writing to a locked down registry key to have a proper icon in the start menu.  Impressive.<<


    >>Was there some sort of requirement to do this in the most developer-hostile way possible, or was that just a happy accident?<<

    My thoughts exactly -

    An application icon that needs signing and so much fuss to create? Sure, block out hobbyist programmers, why don't you! It's gonna break your neck. Time to look elsewhere too.

  • jstuff
    3 Posts

    Sorry for the repeat comments; but after looking at our setup dll it does indeed always return 96. Our workaround was to read the registry to get the true DPI:

    DWORD dwDPI = 92;

    HKEY hkey;

    if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Drivers\\Display\\GPE"), 0, KEY_ALL_ACCESS, &hkey)) {

    DWORD type = REG_DWORD;

    DWORD size = sizeof(DWORD);

    if (ERROR_SUCCESS != RegQueryValueEx(hkey, _T("LogicalPixelsX"), NULL, &type, (LPBYTE)&dwDPI, &size)) {

    dwDPI = 92;




    This way you don't have to launch a separate executable, and may help C# developers as well.

  • jstuff
    3 Posts

    BTW in our testing WCELOAD is HIDPI-aware and returns the correct DPI, at least on older devices. Seeing this article I'm wondering if that's another thing you broke for WM6.5.

  • jstuff
    3 Posts

    Truly a horrid overly engineered solution. Was it too difficult to be developer-centric and use some convention like any sane person would develop? Such as ShortcutTargetPath\ShortcutTargetExeName.Icon.png? How about smooth scaling a 90x90 PNG down for low-DPI devices so we don't have to write code in our CAB setup? Not to mention the registry location and requiring a privileged cert.

    Not to mention it seems braindead to execute an EXE in code that 'returns' the DPI of the device. Why write CreateProcess/WaitFor/etc when we could just write CreateDC/GetDeviceCaps in the CAB DLL?

  • Was there some sort of requirement to do this in the most developer-hostile way possible, or was that just a happy accident?

    And as mrmckeb asked, what about .NETCF developers? Remember us?

    Let's provide a .png icon for an iPhone application you drop a file called "Icon.png" into your project folder - does it occur to anyone that we might have a problem here?

    Sorry to be sarcastic, but as a C# developer this is yet another slap in the face. Yes you have unique issues with devices  supporting a range of resolutions, but this is a crappy solution.

  • PTesta
    2 Posts

    thanks Mike for the explanation, but you write that:

    To write to a protected registry key, the CAB file needs to be signed.

    That means to test this process in the emulator, we must have a signed CAB?

  • Wow, a system more complex than the desktop that requires writing to a locked down registry key to have a proper icon in the start menu.  Impressive.

    Is there some reason for the PNG icons and not just using ICO files?

  • mrmckeb
    26 Posts

    What about those of us that use C# - how do we do this?