Using List View ControlsUsing List View Controls*
*Contents  *Index  *Topic Contents
*Previous Topic: List View Controls
*Next Topic: List View Updates in Internet Explorer

Using List View Controls


You can create a list view control by calling the CreateWindowEx function, specifying the WC_LISTVIEW window class. This window class is registered when the common controls dynamic-link library (DLL) is loaded. To ensure that this DLL is loaded, use the InitCommonControls function.

An application sends messages to a list view control to add, remove, arrange, and otherwise manipulate items. Each message has a macro that you can use instead of sending the message explicitly.

Like most common controls, a list view control sends notification messages to its parent window in the form of WM_NOTIFY messages. For more information, see List View Notification Messages.

Views and Styles

List view controls can display their contents in four different views. The current view is specified by the control's window style. Additional window styles specify the alignment of items and control-specific functionality of the list view control. The following list contains more information about the four views.

View Name Description
Icon view Specified by the LVS_ICON window style. Each item appears as a full-sized icon with a label below it. The user can drag the items to any location in the list view window.
Small icon view Specified by the LVS_SMALLICON window style. Each item appears as a small icon with the label to the right of it. The user can drag the items to any location.
List view Specified by the LVS_LIST window style. Each item appears as a small icon with a label to the right of it. Items are arranged in columns and cannot be dragged to any arbitrary location by the user.
Report view Specified by the LVS_REPORT window style. Each item appears on its own line with information arranged in columns. The leftmost column contains the small icon and label, and subsequent columns contain subitems as specified by the application. Unless the LVS_NOCOLUMNHEADER window style is also specified, each column has a header.

You can change the view type after a list view control is created. To retrieve and change the window style, use the GetWindowLong and SetWindowLong functions. To determine the window styles that correspond to the current view, use the LVS_TYPEMASK value.

You can control the way items are arranged in icon or small icon view by specifying either the LVS_ALIGNTOP (default) or LVS_ALIGNLEFT window style. You can change the alignment after a list view control is created. To isolate the window styles that specify the alignment of items, use the LVS_ALIGNMASK value.

Additional window styles control other options—for example, whether a user can edit labels in place, whether more than one item can be selected at a time, and so on. For a complete list of the list view window styles, see List view window styles.

The following example creates a list view control and then calls application-defined functions that add image lists, columns, and list view items. The window style specifies the list view control's initial view and other options. This example specifies report view, which enables the user to edit the labels of list view items.

	// CreateListView - creates a list view control. 
	// Returns the handle to the new control if successful, or NULL 
	//     otherwise. 
	// hwndParent - handle to the control's parent window. 
	// pfData - file containing list view items. 
	HWND WINAPI CreateListView(HWND hwndParent, FILE *pfData) 
	{ 
	    HWND hwndLV; 
	 
    // Force the common controls DLL to be loaded. 
    InitCommonControls(); 
 
    // Create the list view window. 
    hwndLV = CreateWindow(WC_LISTVIEW, "", 
        WS_CHILD | LVS_REPORT | LVS_EDITLABELS, 
        0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 
        hwndParent, NULL, g_hinst, NULL); 
    if (hwndLV == NULL) 
        return NULL; 
 
    // Call application-defined functions to initialize the 
    // image lists, add columns, and add some items. 
    if (!InitListViewImageLists(hwndLV) || 
            !InitListViewColumns(hwndLV) || 
            !InitListViewItems(hwndLV, pfData)) { 
        DestroyWindow(hwndLV); 
        return FALSE; 
	    } 
	    return hwndLV;              // return the control's handle 
	} 
 

The following example changes the style bits that govern the view mode.

	// SetView - sets a list view's window style to change the view. 
	// hwndLV - handle to the list view control. 
	// dwView - value specifying a view style. 
	 
	VOID WINAPI SetView(HWND hwndLV, DWORD dwView) 
	{ 
	    // Get the current window style. 
	    DWORD dwStyle = GetWindowLong(hwndLV, GWL_STYLE); 
 
    // Only set the window style if the view bits have changed. 
    if ((dwStyle & LVS_TYPEMASK) != dwView) 
        SetWindowLong(hwndLV, GWL_STYLE, 
            (dwStyle & ~LVS_TYPEMASK) | dwView); 
	} 
 

List View Image Lists

By default, a list view control does not display item images. To display item images, you must create image lists and associate them with the control. A list view control can have three image lists:

For more information about icon view, small icon view, list view, and report view, see Views and Styles.

To assign an image list to a list view control, use the LVM_SETIMAGELIST message, specifying whether the image list contains full-sized icons, small icons, or state images. To retrieve the handle to an image list currently assigned to a list view control, use the LVM_GETIMAGELIST message. You can use the GetSystemMetrics function to determine appropriate dimensions for the full-sized and small icons. Use the ImageList_Create function to create an image list, and use other image list functions to add bitmaps to the image list. For more information, see Image Lists.

You only need to create the image list that the control will use. For example, if the list view control will never be in icon view, you do not need to create and assign a large image list because the large images will never be used. If you create both image lists, they must contain the same images in the same order. This is because a single value is used to identify a list view item's icon in both image lists. You can associate an icon index with an item when you call the ListView_InsertItem or ListView_SetItem macro.

The full-sized and small icon image lists can also contain overlay images, which are designed to be drawn transparently over the item icons.

To use overlay images in a list view control:

  1. Call the ImageList_SetOverlayImage function to assign an overlay image index to an image in the full-sized and small icon image lists. An overlay image is identified by a one-based index.
  2. You can associate an overlay image index with an item when you call the ListView_InsertItem or ListView_SetItem macro. Use the INDEXTOOVERLAYMASK macro to specify an overlay image index in the state member of the item's LVITEM structure. You must also set the LVIS_OVERLAYMASK bits in the stateMask member.

If a state image list is specified, a list view control reserves space to the left of each item's icon for a state image.

To associate a state image with an item, use the INDEXTOSTATEIMAGEMASK macro to specify a state image index in the state member of the LVITEM structure. The index identifies an image in the control's state image list. Although image list indexes are zero-based, the control uses one-based indexes to identify state images. A state image index of zero indicates that an item has no state image.

By default, when a list view control is destroyed, it destroys the image lists assigned to it. However, if a list view control has the LVS_SHAREIMAGELISTS window style, the application is responsible for destroying the image lists when they are no longer in use. You should specify this style if you assign the same image lists to multiple list view controls; otherwise, more than one control might try to destroy the same image list.

The following example demonstrates how to create two image lists, add an icon to each, and assign them to a list view control by using the LVM_SETIMAGELIST message.

	// InitListViewImageLists - creates image lists for a list view. 
	// Returns TRUE if successful, or FALSE otherwise. 
	// hwndLV - handle to the list view control. 
	BOOL WINAPI InitListViewImageLists(HWND hwndLV) 
	{ 
    HICON hiconItem;        // icon for list view items 
    HIMAGELIST himlLarge;   // image list for icon view 
    HIMAGELIST himlSmall;   // image list for other views 
 
    // Create the full-sized and small icon image lists. 
    himlLarge = ImageList_Create(GetSystemMetrics(SM_CXICON), 
        GetSystemMetrics(SM_CYICON), TRUE, 1, 1); 
    himlSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), 
        GetSystemMetrics(SM_CYSMICON), TRUE, 1, 1); 
 
    // Add an icon to each image list. 
    hiconItem = LoadIcon(g_hinst, MAKEINTRESOURCE(IDI_ITEM)); 
    ImageList_AddIcon(himlLarge, hiconItem); 
    ImageList_AddIcon(himlSmall, hiconItem); 
    DeleteObject(hiconItem); 
 
    // Assign the image lists to the list view control. 
    ListView_SetImageList(hwndLV, himlLarge, LVSIL_NORMAL); 
    ListView_SetImageList(hwndLV, himlSmall, LVSIL_SMALL); 
    return TRUE; 
	} 
 

Items and Subitems

Each item in a list view control has an icon, a label, a current state, and an application-defined value. By using list view messages, you can add, modify, and delete items as well as retrieve information about items. You can also find items with specific attributes.

Each item can also have one or more subitems. A subitem is a string that, in report view, is displayed in a column to the right of an item's icon and label. To specify the text of a subitem, use the LVM_SETITEMTEXT or LVM_SETITEM message. All items in a list view control have the same number of subitems. The number of subitems is determined by the number of columns in the list view control. When you add a column to a list view control, you specify its associated subitem index. For more information about list view columns, see Columns.

The LVITEM structure defines a list view item or subitem. The iItem member is the zero-based index of the item. The iSubItem member is the one-based index of a subitem or zero if the structure contains information about an item. Additional members specify the item's text, icon, state, and item data. Item data is an application-defined value associated with a list view item.

To add an item to a list view control, use the LVM_INSERTITEM message, specifying the address of an LVITEM structure. Before adding multiple items, you can send the control an LVM_SETITEMCOUNT message, specifying the number of items the control will ultimately contain. This message enables the list view control to reallocate its internal data structures only once rather than every time you add an item. You can determine the number of items in a list view control by using the LVM_GETITEMCOUNT message.

To change the attributes of a list view item, use the LVM_SETITEM message, specifying the address of an LVITEM structure. The mask member of this structure specifies the item attributes you want to change. To change only the text of an item or subitem, use the LVM_SETITEMTEXT message.

To retrieve information about a list view item, use the LVM_GETITEM message, specifying the address of the LVITEM structure to fill in. The mask member of this structure specifies the item attributes to be retrieved. To retrieve only an item or subitem's text, use the LVM_GETITEMTEXT message.

To delete a list view item, use the LVM_DELETEITEM message. You can delete all items in a list view control by using the LVM_DELETEALLITEMS message.

The example in this section demonstrates how to add a list view item for each line in a text file. A semicolon in the source text separates the item label and the subitem strings that follow it. The example saves each item's label and subitem strings in a structure, which is defined in the application's header file, as follows.

#define C_COLUMNS 6 
 
typedef struct myitem_tag { 
   LPSTR aCols[C_COLUMNS]; 
} MYITEM; 

The application fills in an LVITEM structure and adds a list view item by using the LVM_INSERTITEM message. Because the application saves the item label in its own application-defined MYITEM structure, it specifies the LPSTR_TEXTCALLBACK value for the pszText member of the LVITEM structure. Specifying this value causes the control to send an LVN_GETDISPINFO notification message to its owner window whenever it needs to display the item. The address of the application-defined structure is saved as item data.

	// InitListViewItems - adds items and subitems to a list view. 
	// Returns TRUE if successful, or FALSE otherwise. 
	// hwndLV - handle to the list view control. 
	// pfData - text file containing list view items with columns 
	//          separated by semicolons. 
	BOOL WINAPI InitListViewItems(HWND hwndLV, FILE *pfData) 
	{ 
    extern char g_achTemp[256];         // temporary buffer 
    PSTR pszStart; 
    PSTR pszEnd; 
    int iItem; 
    int iSubItem; 
    LVITEM lvi; 
 
    // Initialize LVITEM members that are common to all items. 
    lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE; 
    lvi.state = 0; 
    lvi.stateMask = 0; 
    lvi.pszText = LPSTR_TEXTCALLBACK;   // app. maintains text 
    lvi.iImage = 0;                     // image list index 
 
    // Read each line in the specified file. 
    for (iItem = 0; 
            fgets(g_achTemp, sizeof(g_achTemp), pfData); 
            iItem++) { 
 
        // Allocate an application-defined structure to store the 
        // item label and the text of each subitem. 
        MYITEM *pItem = LocalAlloc(LPTR, sizeof(MYITEM)); 
 
        // Copy the first string (the label). 
        pszEnd = strchr(g_achTemp, ';'); 
        *pszEnd = '\0'; 
        pItem->aCols[0] = DupString(g_achTemp); 
 
        // Copy subsequent strings (subitems). 
        for (iSubItem = 1; 
                iSubItem < C_COLUMNS && pszEnd != NULL; 
                iSubItem++) { 
            pszStart = pszEnd + 1; 
            if ((pszEnd = strchr(pszStart, ';')) != NULL) 
                *pszEnd = '\0'; 
            pItem->aCols[iSubItem] = DupString(pszStart); 
        } 
 
        // Initialize item-specific LVITEM members. 
        lvi.iItem = iItem; 
        lvi.iSubItem = 0; 
        lvi.lParam = (LPARAM) pItem;    // item data 
 
        // Add the item. 
        ListView_InsertItem(hwndLV, &lvi); 
 
        // There is no need to set the text of the subitems. They 
        // default to LPSTR_TEXTCALLBACK. 
	    } 
	    return TRUE; 
	} 
 
	// DupString - allocates a copy of a string. 
	// lpsz - address of the null-terminated string to copy. 
 
	LPSTR DupString(LPSTR lpsz) 
	{ 
    int cb = lstrlen(lpsz) + 1; 
    LPSTR lpszNew = LocalAlloc(LMEM_FIXED, cb); 
    if (lpszNew != NULL) 
        CopyMemory(lpszNew, lpsz, cb); 
    return lpszNew; 
	} 
 

Item States

An item's state is a value that specifies the item's availability, indicates user actions, or otherwise reflects the item's status. A list view control changes some state bits, such as when the user selects an item. An application might change other state bits to disable or hide the item or to specify an overlay image or state image. For more information about overlay images and state images, see List View Image Lists.

An item's state is specified by the state member of the LVITEM structure. When you specify or change an item's state, the stateMask member specifies which state bits you want to change. You can change an item's state by using the LVM_SETITEMSTATE message. You can specify an item's state when you create it or when you change its attributes by using the LVM_SETITEM message. To determine an item's current state, use the LVM_GETITEMSTATE or LVM_GETITEM message.

To set an item's overlay image, the stateMask member of the LVITEM structure must include the LVIS_OVERLAYMASK value, and the state member must include the one-based index of the overlay image shifted left 8 bits by using the INDEXTOOVERLAYMASK macro. The index can be zero to specify no overlay image.

To set an item's state image, the stateMask member of the LVITEM structure must include the LVIS_STATEIMAGEMASK value, and the state member must include the one-based index of the state image shifted left 12 bits by using the INDEXTOSTATEIMAGEMASK macro. The index can be zero to specify no state image.

Callback Items and the Callback Mask

For each of its items, a list view control typically stores the label text, the image list index of the item's icons, and a set of bit flags for the item's state. You can define callback items or change the control's callback mask to indicate that the application—rather than the control—stores some or all of this information. You may want to use callbacks if your application already stores some of this information.

A callback item in a list view control is an item for which the application stores the text, icon index, or both. You can define callback items when you send the LVM_INSERTITEM message to add an item to the list view control. If the application stores the text for the item or subitem, set the pszText member of the item's LVITEM structure to LPSTR_TEXTCALLBACK. If the application stores the icon index for an item, set the iImage member of the item's LVITEM structure to I_IMAGECALLBACK.

The callback mask of a list view control is a set of bit flags that specify the item states for which the application, rather than the control, stores the current data. The callback mask applies to all of the control's items, unlike the callback item designation, which applies to a specific item. The callback mask is zero by default, meaning that the list view control stores all item state information. After creating a list view control and initializing its items, you can send the LVM_SETCALLBACKMASK message to change the callback mask. To get the current callback mask, send the LVM_GETCALLBACKMASK message.

When a list view control must display or sort a list view item for which the application stores callback information, the control sends the LVN_GETDISPINFO notification message to the control's parent window. This message specifies an NMLVDISPINFO structure that specifies the type of information required and identifies the item or subitem of interest. The parent window must process LVN_GETDISPINFO to provide the requested data.

If the list view control detects a change in an item's callback information (that is, a change in the text, icon, or state information being tracked by the application), the control sends an LVN_SETDISPINFO notification message to notify you of the change.

If you change a callback item's attributes or state bits, you can use the LVM_UPDATE message to force the control to repaint the item. This message also causes the control to arrange its items if it has the LVS_AUTOARRANGE style. You can use the LVM_REDRAWITEMS message to redraw a range of items by invalidating the corresponding portions of the list view control's client area.

By effectively using callback items and the callback mask, you can ensure that each item attribute is maintained in only one place. Doing this can simplify your application, but the only space saved is the memory that would otherwise be required to store item labels and subitem text.

Columns

Columns control the way items and their subitems are displayed in report view. Each column has a title and width and is associated with a specific subitem (subitem zero is the item's icon and label). The attributes of a column are defined by an LVCOLUMN structure.

To add a column to a list view control, use the LVM_INSERTCOLUMN message. To delete a column, use the LVM_DELETECOLUMN message. You can retrieve and change the properties of an existing column by using the LVM_GETCOLUMN and LVM_SETCOLUMN messages.

To retrieve or change a column's width, use the LVM_GETCOLUMNWIDTH and LVM_SETCOLUMNWIDTH messages.

Unless the LVS_NOCOLUMNHEADER window style is specified, column headers appear in report view. The user can click a column header, causing an LVN_COLUMNCLICK notification message to be sent to the parent window. Typically, the parent window sorts the list view control by the specified column when this clicking occurs. The user can also drag the column guides between the headers to size the columns.

The following example adds several columns to a list view control. The column headings are defined as string resources, which are consecutively numbered starting with IDS_FIRSTCOLUMN (defined in the application's header file). The number of columns is defined in the application's header file as C_COLUMNS.

	// InitListViewColumns - adds columns to a list view control. 
	// Returns TRUE if successful, or FALSE otherwise. 
	// hwndLV - handle to the list view control. 
	BOOL WINAPI InitListViewColumns(HWND hwndLV) 
	{ 
    extern char g_achTemp[256];     // temporary buffer 
    LVCOLUMN lvc; 
    int iCol; 
 
    // Initialize the LVCOLUMN structure. 
    lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; 
    lvc.fmt = LVCFMT_LEFT; 
    lvc.cx = 100; 
    lvc.pszText = g_achTemp; 
 
    // Add the columns. 
    for (iCol = 0; iCol < C_COLUMNS; iCol++) { 
        lvc.iSubItem = iCol; 
        LoadString(g_hinst, IDS_FIRSTCOLUMN + iCol, 
                g_achTemp, sizeof(g_achTemp)); 
        if (ListView_InsertColumn(hwndLV, iCol, &lvc) == -1) 
            return FALSE; 
    } 
	    return TRUE; 
	} 
 

Arranging, Sorting, and Finding

You can use list view messages to arrange and sort items and to find items based on their attributes or positions. Arranging repositions items to align on a grid, but the indexes of the items do not change. Sorting changes the sequence of items (and their corresponding indexes) and then repositions them accordingly. You can arrange items only in icon and small icon views, but you can sort items in any view.

To arrange items, use the LVM_ARRANGE message. You can ensure that items are arranged at all times by specifying the LVS_AUTOARRANGE window style.

To sort items, use the LVM_SORTITEMS message. When you sort using this message, you specify an application-defined callback function that the list view control calls to compare the relative order of any two items. The control passes to the comparison function the item data associated with each of the two items. The item data is the value that was specified in the lParam member of the item's LVITEM structure when it was inserted into the list. By specifying the appropriate item data and supplying an appropriate comparison function, you can sort items by their label, by any subitem, or by any other property. Note that sorting items does not reorder the corresponding subitems. Thus, if any subitems are not callback items, you must regenerate the subitems after sorting.

You can ensure that a list view control is always sorted by specifying the LVS_SORTASCENDING or LVS_SORTDESCENDING window style. Controls with these styles use the label text of the items to sort them in ascending or descending order. You cannot supply a comparison function when using these window styles. If a list view control has either of these styles, an LVM_INSERTITEM message will fail if you try to insert an item that has LPSTR_TEXTCALLBACK as the pszText member of its LVITEM structure.

You can find a list view item with specific properties by using the LVM_FINDITEM message. You can find a list view item that is in a specified state and bears a specified geometrical relationship to a given item by using the LVM_GETNEXTITEM message. For example, you can retrieve the next selected item to the right of a specified item.

List View Item Position

Every list view item has a position and size, which you can retrieve and set using messages. You can also determine which item, if any, is at a specified position. The position of list view items is specified in view coordinates, which are client coordinates offset by the scroll position.

To retrieve and set an item's position, use the LVM_GETITEMPOSITION and LVM_SETITEMPOSITION messages. LVM_GETITEMPOSITION works for all views, but LVM_SETITEMPOSITION works only for icon and small icon views.

You can determine which item, if any, is at a particular location by using the LVM_HITTEST message.

To get the bounding rectangle for a list item or for only its icon or label, use the LVM_GETITEMRECT message.

Scroll Position

Unless the LVS_NOSCROLL window style is specified, a list view control can be scrolled to show more items than can fit in the client area of the control. You can get a list view control's scroll position and related information, scroll a list view control by a specified amount, or scroll a list view control so that a specified list item is visible.

In icon view or small icon view, the current scroll position is defined by the view origin. The view origin is the set of coordinates, relative to the visible area of the list view control, that correspond to the view coordinates (0, 0). To get the current view origin, use the LVM_GETORIGIN message. This message should be used only in icon or small icon view; it returns an error in list or report view.

In list or report view, the current scroll position is defined by the top index. The top index is the index of the first visible item in the list view control. To get the current top index, use the LVM_GETTOPINDEX message. This message returns a valid result only in list or report view; it returns zero in icon or small icon view.

You can use the LVM_GETVIEWRECT message to get the bounding rectangle of all items in a list view control, relative to the visible area of the control.

The LVM_GETCOUNTPERPAGE message returns the number of items that fit in one page of the list view control. This message returns a valid result only in list and report views; in icon and small icon views, it returns the total number of items.

To scroll a list view control by a specific amount, use the LVM_SCROLL message. Using the LVM_ENSUREVISIBLE message, you can scroll the list view control, if necessary, to ensure that a specified item is visible.

Label Editing

A list view control that has the LVS_EDITLABELS window style enables a user to edit item labels in place. The user begins editing by clicking the label of an item that has the focus. An application can begin editing automatically by using the LVM_EDITLABEL message. The list view control notifies the parent window when editing begins and when it is canceled or completed. When editing is completed, the parent window is responsible for updating the item's label, if appropriate.

When label editing begins, a list view control sends its parent window an LVN_BEGINLABELEDIT notification message. You can process this message to allow selective editing of specific labels; returning a nonzero value prevents label editing.

When label editing is canceled or completed, a list view control sends its parent window an LVN_ENDLABELEDIT notification message. The lParam parameter is the address of an NMLVDISPINFO structure. The item member of this structure is an LVITEM structure whose iItem member identifies the item. If editing is canceled, the pszText member of the LVITEM structure is NULL; otherwise, pszText is the address of the edited text. The parent window is responsible for updating the item's label if it wishes to keep the new label.

During label editing, you can get the handle to the edit control used for label editing by using the LVM_GETEDITCONTROL message. To limit the amount of text a user can enter, you can send the edit control an EM_LIMITTEXT message. You can even subclass the edit control to intercept and discard invalid characters. The edit control is created after the LVN_BEGINLABELEDIT notification message is sent.

List View Colors

An application can retrieve and set three colors for a list view control. To retrieve and set the text color, use the LVM_GETTEXTCOLOR and LVM_SETTEXTCOLOR messages. To retrieve and set the text background color, use the LVM_GETTEXTBKCOLOR and LVM_SETTEXTBKCOLOR messages. To retrieve and set the window background color, use the LVM_GETBKCOLOR and LVM_SETBKCOLOR messages.

List View Notification Messages

A list view control sends notification messages to its parent window in the form of WM_NOTIFY messages. The following notification messages are sent by a list view control.
Notification message Description
LVN_BEGINDRAG Signals the start of a drag-and-drop operation.
LVN_BEGINLABELEDIT Signals the start of in-place label editing.
LVN_BEGINRDRAG Signals the start of a drag-and-drop operation using the right mouse button.
LVN_COLUMNCLICK Indicates that the user clicked a column header in report view.
LVN_DELETEALLITEMS Signals the deletion of all list view items.
LVN_DELETEITEM Signals the deletion of a specific item.
LVN_ENDLABELEDIT Signals the end of label editing.
LVN_GETDISPINFO Requests information that the list view control requires to display an item.
LVN_INSERTITEM Signals the insertion of a new list view item.
LVN_ITEMCHANGED Indicates that an item has changed.
LVN_ITEMCHANGING Indicates that an item is in the process of changing and enables the parent window to accept or deny the change.
LVN_KEYDOWN Signals a keyboard event.
LVN_SETDISPINFO Notifies a parent window that it must update the information it maintains for an item.

The following example shows the portion of the application's window procedure that processes the WM_NOTIFY message.

	case WM_NOTIFY: 
 
    // Branch depending on the specific notification message. 
    switch (((LPNMHDR) lParam)->code) { 
 
        // Process LVN_GETDISPINFO to supply information about 
        // callback items. 
        case LVN_GETDISPINFO: 
            Main_OnGetDispInfo((LPNMLVDISPINFO) lParam); 
            break; 
 
        // Process LVN_ENDLABELEDIT to change item labels after 
        // in-place editing. 
        case LVN_ENDLABELEDIT: 
            return Main_OnEndLabelEdit( 
                (LPNMLVDISPINFO) lParam 
                ); 
 
        // Process LVN_COLUMNCLICK to sort items by column. 
        case LVN_COLUMNCLICK: 
            #define pnm ((LPNMLISTVIEW) lParam) 
            ListView_SortItems( 
                pnm->hdr.hwndFrom, 
                ListViewCompareFunc, 
                (LPARAM) (pnm->iSubItem) 
                ); 
            #undef pnm 
            break; 
    } 
    break; 

The following example shows the application-defined functions that the window procedure uses to process list view notification messages.

	// Main_OnGetDispInfo - processes the LVN_GETDISPINFO 
	//     notification message. 
	// pnmv - value of lParam (points to an NMLVDISPINFO structure). 
	VOID WINAPI Main_OnGetDispInfo(LPNMLVDISPINFO pnmv) 
	{ 
	    // Provide the item or subitem's text, if requested. 
    if (pnmv->item.mask & LVIF_TEXT) { 
        MYITEM *pItem = (MYITEM *) (pnmv->item.lParam); 
        lstrcpy(pnmv->item.pszText, 
                pItem->aCols[pnmv->item.iSubItem]); 
    } 
	} 
 
	// Main_OnEndLabelEdit - processes the LVN_ENDLABELEDIT 
	//     notification message. 
	// Returns TRUE if the label is changed, or FALSE otherwise. 
	// pnmv - value of lParam (points to an NMLVDISPINFO structure). 
	 
	BOOL Main_OnEndLabelEdit(LPNMLVDISPINFO pnmv) 
	{ 
    MYITEM *pItem; 
 
    // The item is -1 if editing is being canceled. 
    if (pnmv->item.iItem == -1) 
        return FALSE; 
 
    // Copy the new text to the application-defined structure, 
    // a pointer to which is saved as item data. 
    pItem = (MYITEM *) (pnmv->item.lParam); 
    pItem->aCols[0] = (PSTR) LocalReAlloc( 
        (HLOCAL) (pItem->aCols[0]), 
        lstrlen(pnmv->item.pszText) + 1, 
        LMEM_MOVEABLE 
        ); 
    lstrcpy(pItem->aCols[0], pnmv->item.pszText); 
 
    // No need to set the item text because it is a callback item. 
    return TRUE; 
	} 
 
	// ListViewCompareFunc - sorts the list view control. It is a 
	//     comparison function. 
	// Returns a negative value if the first item should precede the 
	//     second item, a positive value if the first item should 
	//     follow the second item, and zero if the items are equivalent. 
	// lParam1 and lParam2 - item data for the two items (in this 
	//     case, pointers to application-defined MYITEM structures). 
	// lParamSort - value specified by the LVM_SORTITEMS message 
	//     (in this case, the index of the column to sort). 
	int CALLBACK ListViewCompareFunc( 
	    LPARAM lParam1, 
	    LPARAM lParam2, 
	    LPARAM lParamSort) 
	{ 
    MYITEM *pItem1 = (MYITEM *) lParam1; 
    MYITEM *pItem2 = (MYITEM *) lParam2; 
 
    // Compare the specified column. 
    int iCmp = lstrcmpi(pItem1->aCols[lParamSort], 
        pItem2->aCols[lParamSort]); 
 
    // Return the result if nonzero, or compare the 
    // first column otherwise. 
    return (iCmp != 0) ? iCmp : 
        lstrcmpi(pItem1->aCols[0], pItem2->aCols[0]); 
	} 

Default List View Message Processing

This section describes the window message processing performed by a list view control. Messages specific to list view controls are discussed in other sections of this document.
Message Processing performed
WM_CHAR Searches for a list view item that begins with the specified character and, if the item is found, selects and sets the focus to the item.

Multiple characters received within a time-out interval are concatenated, and the list view control searches for an item that begins with the resulting string.

WM_COMMAND Processes the EN_UPDATE and EN_KILLFOCUS notification messages and forwards all other edit control notifications to the parent window.
WM_CREATE Performs initialization additional to WM_NCCREATE. If the LVS_SHAREIMAGELISTS window style is not specified, the list view control creates the icon and small icon image lists at this point.
WM_DESTROY Frees resources allocated during WM_CREATE.
WM_ERASEBKGND Erases the window background using the current background color for the list view control. If the background color is the CLR_NONE value, the list view control forwards the message to the parent window.
WM_GETDLGCODE Returns a combination of the DLGC_WANTTAB and DLGC_WANTARROWS values.
WM_GETFONT Returns the handle to the current label font.
WM_HSCROLL Scrolls the list view control horizontally.
WM_KEYDOWN Processes the SPACEBAR, ENTER, and arrow keys and sends an LVN_KEYDOWN notification message to the parent window.
WM_KILLFOCUS Repaints the focused list item, if any, and sends an NM_KILLFOCUS notification message to the parent window.
WM_LBUTTONDBLCLK Sends the parent window an NM_DBLCLK notification message.
WM_LBUTTONDOWN Processed in different ways depending on whether a click or drag operation is being initiated. To determine which operation is involved, the list view control enters a modal message loop until either the button is released or the mouse is moved.

In the case of a click, the list view control may change which item has the focus and which items are selected, taking into account the cursor position, the state of the SHIFT and CTRL keys, and so on. Then the list view control sends its parent window an NM_CLICK notification message.

If dragging begins over an item, the list view control selects and sets the focus to the item. Then it sends an LVN_BEGINDRAG notification message to the parent window. The parent window is responsible for actually carrying out the drag operation.

If dragging begins over the window background, the list view control enters another modal message loop, enabling the user to form a rectangle by dragging the mouse. Items within the rectangle are selected.

WM_NCCREATE Allocates and initializes an internal data structure and then calls the DefWindowProc function.
WM_NCDESTROY Frees resources allocated by the list view control. Unless the LVS_SHAREIMAGELISTS style is used, this includes deleting the full-sized and small image lists.
WM_NOTIFY Processes header control notification messages.
WM_PAINT Displays any items in the update region. For callback items, the control first sends an LVN_GETDISPINFO notification message to the owner window to request display information. If the wParam parameter is non-NULL, the control assumes that the value is an HDC and paints using that device context.
WM_RBUTTONDOWN Processed the same way as the WM_LBUTTONDOWN message, except that the control sends an NM_RCLICK notification message (instead of NM_CLICK) and an LVN_BEGINRDRAG notification message (instead of LVN_BEGINDRAG).
WM_SETFOCUS Repaints the focused list item, if any, and sends an NM_SETFOCUS notification message to the parent window.
WM_SETFONT Saves the specified font handle, forwards the message to the header window, if any, and repaints using the new font.
WM_SETREDRAW Turns redrawing on or off.
WM_TIMER Begins editing of an item label. If the user clicks the label of the focused item, the list view control sets a timer instead of entering edit mode immediately. The timer makes it possible for the list view control to not enter edit mode if the user double-clicks the label.
WM_VSCROLL Scrolls the list view control vertically.
WM_WINDOWPOSCHANGED Updates the window scroll bars. If the current view is icon or small icon view, and the LVS_AUTOARRANGE style is specified, the list view control will also arrange the list items.
WM_WININICHANGE Processes changes to system metrics.


Up Top of Page
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.