Title: Make multi-image icons from files in C#
The post Make multi-image icon files in C# shows how to create several bitmaps at runtime and then used them to create multi-image icons in C#. This example lets you load multiple saved image files and use them to create multi-image icons.
This program displays files in a ListView control named lvwFiles. It stores preview images of the image files that you load in an ImageList component named imlFiles. When the program starts, it uses the following code to set some ListView properties.
private void Form1_Load(object sender, EventArgs e)
lvwFiles.LargeImageList = imlFiles;
lvwFiles.View = View.Tile;
imlFiles.ImageSize = new Size(64, 64);
This code makes the ListView control use the imlFiles ImageList for its large image list. It also sets the ListView control's View property to Tile so the control displays item text with large images.
The code also sets the ImageList component's Size property to 64 pixels by 64 pixels. If you add an image to this control, it will resize the image if necessary so it can store a 64 x 64 pixel image.
You could set all of these properties at design time in the Form Designer. I put the code here to make it more obvious how these properties are set.
When you select the File menu's Open command, the following code executes.
private void mnuFileOpen_Click(object sender, EventArgs e)
if (ofdImages.ShowDialog() == DialogResult.OK)
foreach (string filename in ofdImages.FileNames)
Bitmap bm = new Bitmap(filename);
lvwFiles.Items.Add(filename, imlFiles.Images.Count - 1);
mnuFileSaveAs.Enabled = (lvwFiles.Items.Count > 0);
This code displays the ofdImages Open File Dialog. Note that I set this control's Multiselect property to true at design time so it lets you pick multiple files.
If you use the dialog to select one or more files and then click Open, the code loops through the dialog's FileNames list to see which files you have selected.
For each selected file, the program uses the file to create a Bitmap and adds the Bitmap to the ImageList component. (Remember that the ImageList resizes the Bitmap if necessary so it is 64 x 64 pixels in size.) The code also adds the selected file's name to the lvwFiles ListView control and sets that item's image index to the index of the last image in the ImageList component. That makes the ListView display the file's name (probably truncated) and the image that it contains.
After it has loaded the image files that you selected, the program enables the File menu's Save As command if you have loaded at least one file.
The program lets you remove files from the ListView control in two ways. First, if you select the Items menu's Clear command, the following code executes.
private void mnuItemsClear_Click(object sender, EventArgs e)
mnuFileSaveAs.Enabled = (lvwFiles.Items.Count > 0);
This code clears the ListView control and removes all of the images from the ImageList component. It then disables the File menu's Save As command.
The second way you can remove files is to select one in the ListView control and then press Delete. When you press a key while the ListView has the input focus (and it always does because it's the only control on the form), the following code executes.
private void lvwFiles_KeyDown(object sender, KeyEventArgs e)
if (e.KeyCode == Keys.Delete)
foreach (ListViewItem item in lvwFiles.SelectedItems)
if (lvwFiles.Items.Count == 0)
mnuFileSaveAs.Enabled = false;
If the key you pressed was Delete, the code loops through the ListView control's selected items and removes them.
When it has finished removing items, the code checks whether the ListView is empty. If the ListView contains no items, then the code disables the File menu's Save As command and empties the ImageList.
Notice that the code does not remove any images from the ImageList unless the ListView is completely empty. If you remove an item's image from the list, then the other items' ImageIndex properties are not automatically renumbered so they may point to the wrong images. All of this means that the ImageList may contain images that are no longer used, but that won't be a problem unless you add and then remove a huge number of images. Don't do that.
Saving the Icon File
If you have one or more images loaded and you select the File menu's Save As command, the following code executes.
private void mnuFileSaveAs_Click(object sender, EventArgs e)
if (sfdIcon.ShowDialog() == DialogResult.OK)
List<Bitmap> bitmaps = new List<Bitmap>();
foreach (ListViewItem item in lvwFiles.Items)
bitmaps, sfdIcon.FileName, true);
this.Icon = new Icon(sfdIcon.FileName);
This code displays a Save File Dialog. If you select an icon file and click Save, the program creates a list named bitmaps to hold Bitmap objects.
The program then loops through the items in the ListView control. For each item, the program uses the file name stored in the item to create a Bitmap and adds the Bitmap to the bitmaps list.
Notice that the code does not use the images stored in the ImageList. Remember that the ImageList resizes those images so they are all 64 x 64 pixels. If you put those images in the bitmaps list, then the resulting icon would contain only images with that size.
When it has finished building the bitmaps list, the program calls the IconFactory.SavePngAsIcon method described in the previous post. See that post for details about how the method works.
The event handler finishes by making the program's form use the newly created icon loaded from the icon file. Now Windows will use the images stored in the icon resizing them as needed if a particular size is not contained in the icon. For example, look at the picture at the top of this post. The left end of form's title bar displays a 16 x 16 pixel image. The icon that I created contained 32 x 32, 64 x 64, and 128 x 128 pixel images but no 16 x 16 pixel image. To create the 16 x 16 pixel image that it needed, Windows resized the 32 x 32 pixel image.
If you press Alt+Tab or Win+Tab, Windows will display the appropriate (possibly resized) image from the form's icon.
In this example I used three PNG files that display their sizes so it's easy to tell which image is being displayed. In a real icon file, you would probably want the different image files to contain similar images.
The code shown in the preceding section shows how a program can set a form's icon at runtime. Of course you can also set the form's icon at design time by using the From Designer. However, that doesn't set the application's icon. If you look at the compiled executable in File Explorer, you'll see that it displays a default icon.
To set the application's icon in all but the most recent versions of Visual Studio, open Visual Studio's Project menu and select Properties. On the Application tab, click the ellipses next to the icon file text box as shown in the following picture.
Select the icon file that you want the executable to display and click Open.
In Visual Studio 2022, open the Project menu and select Properties at the bottom as before. Then On the Application tab, go to the Win32 Resources section and set the Icon field.
Now the executable will display images from the file you selected. For example, drag the executable around or use File Explorer's different views to see different icon sizes.
The previous post shows how you can make multi-image icons. This example shows how you can use the methods described in that post to create icons from bitmap files that you can create using MS Paint or any other drawing program.
Download the example to experiment with it and to see additional details.