Display icons next to ListView sub-items in C#

[ListView sub-items]

This example displays icons next to ListView sub-items when the ListView is in Detail View. This requires two steps beyond what is required to make a ListView display item icons: (1) assigning image indices to the sub-items, and (2) making the ListView sub-items display them.

Both of these tasks require using the SendMessage API function. The example uses the following code to declare the API functions and constants that it needs.

[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, uint Msg,
    int wParam, int lParam);

[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, uint Msg,
    int wParam, ref LV_ITEM item_info);

private struct LV_ITEM
{
    public UInt32 uiMask;
    public Int32 iItem;
    public Int32 iSubItem;
    public UInt32 uiState;
    public UInt32 uiStateMask;
    public string pszText;
    public Int32 cchTextMax;
    public Int32 iImage;
    public IntPtr lParam;
};

public const Int32 LVM_FIRST = 0x1000;
public const Int32 LVM_SETITEM = LVM_FIRST + 6;
public const Int32 LVIF_IMAGE = 0x2;

public const int LVW_FIRST = 0x1000;
public const int LVM_SETEXTENDEDLISTVIEWSTYLE = LVW_FIRST + 54;
public const int LVM_GETEXTENDEDLISTVIEWSTYLE = LVW_FIRST + 55;

public const int LVS_EX_SUBITEMIMAGES = 0x2;

This code defines two versions of the SendMessage function, one that takes an integer as its final parameter and another that takes a reference to an LV_ITEM structure as its final parameter.

The code then defines the LV_ITEM structure. This structure contains fields that define the characteristics of a ListView item.

The rest of the code defines some constants that are needed to display icons in ListView sub-items.

The following ListView extension method adds an icon to a sub-item.

// Add an icon to a subitem.
public static void AddIconToSubitem(this ListView lvw,
    int row, int col, int icon_num)
{
    LV_ITEM lvi = new LV_ITEM();
    lvi.iItem = row;           // Row.
    lvi.iSubItem = col;        // Column.
    lvi.uiMask = LVIF_IMAGE;   // We're setting the image.
    lvi.iImage = icon_num;     // The image index in the ImageList.

    // Send the LVM_SETITEM message.
    SendMessage(lvw.Handle, LVM_SETITEM, 0, ref lvi);
}

This method takes as parameters the row and column of the sub-item and the index of its icon in the ListView control’s SmallImageList. (Note that the main item is in column 0, so you don’t need to use this method to set that item’s image index.)

The code creates a LV_ITEM structure and sets its row and column. It sets the uiMask value to LVIF_IMAGE to indicate that the code is setting icons for ListView sub-items. The code then sets the iImage value to the image’s index. It finishes by calling SendMessage to send the ListView control the LVM_SETITEM message.

The following code shows how the program turns the sub-item icons on and off.

// Make the ListView display sub-item icons.
public static void ShowSubItemIcons(this ListView lvw, bool show)
{
    // Get the current style.
    int style = SendMessage(lvw.Handle,
        LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);

    // Show or hide sub-item icons.
    if (show) style |= LVS_EX_SUBITEMIMAGES;
    else style &= (~LVS_EX_SUBITEMIMAGES);

    SendMessage(lvw.Handle,
        LVM_SETEXTENDEDLISTVIEWSTYLE, 0, style);
}

The code first calls SendMessage to send the LVM_GETEXTENDEDLISTVIEWSTYLE message to the ListView control. The result is an integer that represents the control’s current style.

Depending on whether the program’s Sub-item Icons check box is checked, the code sets or clears the LVS_EX_SUBITEMIMAGES style bit, which determines whether the control displays icons in the ListView sub-items.

Finally, the code calls SendMessage again, this time with the LVM_SETEXTENDEDLISTVIEWSTYLE message, to make the ListView use the new style.

Download the example and see the code for code that handles more mundane issues such as creating column headers and making the items.


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in controls and tagged , , , , , , , , , , , , , , , . Bookmark the permalink.

3 Responses to Display icons next to ListView sub-items in C#

  1. Mariano says:

    Congratulations,
    a very well done article with source code readable and understandable. One of the best ever in the whole network. The subject is treated with great skill. All C # programmers should read this article. Congratulations again.
    Sincerely, Mariano

  2. Nikhil says:

    Is there a way to display the image at the center of column instead displaying it as left aligned?

    • RodStephens says:

      I don’t think so. I’m not sure how you would arrange the text in that case, either. The icon and text seem to be centered in the Large Icons view, but in the others the text is beside the icons.

      You could use WPF controls. Its version of ListBox is more flexible, although harder to use.

Leave a Reply

Your email address will not be published. Required fields are marked *