Skip to content

ListView Dialog

A Win32 dialog example that builds a ListView with columns, a small icon image list, ten rows of data, custom text color, and sorting.

Published Mar 22, 1997

A complete tour of the classic Win32 ListView control in report mode: setting extended styles (grid lines, full-row select, checkboxes), creating an ImageList of small icons and attaching it, inserting four columns with LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM, populating ten rows where ListView_InsertItem creates the row plus its first sub-item and ListView_SetItem fills the rest, coloring the text, and finishing with ListView_SortItems. If you are writing any raw-Win32 table UI, this single WM_INITDIALOG block is the reference - every call you need to get from "empty control" to "populated sortable grid" is here.

/////////////////////////////////////////////////////////////////////

LV_COLUMN  LVColumb;
LV_ITEM    LVItem;
HIMAGELIST IListSamllIcon;
HICON      ListIconItem;

BOOL CALLBACK MainDialog(HWND xHandle, UINT xMessage, WPARAM wParam, LPARAM lParam)
{
	static HWND List_hWnd = NULL;

	while(1) // Loop Forever
	{
		if(xMessage == WM_INITDIALOG) // Received A Initilize Dialog Message
		{
			MainDialog_hWnd = xHandle;

			SendMessage(MainDialog_hWnd,(UINT)WM_SETTEXT,(WPARAM)0,(LPARAM)TitleCaption);
			SendMessage(MainDialog_hWnd,WM_SETICON,TRUE,(LPARAM)LoadIcon(MainInstance,MAKEINTRESOURCE(1)));

			List_hWnd = GetDlgItem(MainDialog_hWnd,1000);

            int LVStyle = LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES;
            SendMessage(List_hWnd,(UINT)LVM_SETEXTENDEDLISTVIEWSTYLE,(WPARAM)0,(LPARAM)LVStyle);

//          Create Icon Lists
            IListSamllIcon = ImageList_Create( GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), TRUE, 1, 1 );

            char TempText[25];
            int LocalLoop = 0;

//          Add Icons To List
            while(LocalLoop < 5)
            {
                ListIconItem = LoadIcon(MainInstance, MAKEINTRESOURCE(LocalLoop+2) );
                ImageList_AddIcon( IListSamllIcon, (HICON)ListIconItem );
                DeleteObject( (HICON)ListIconItem );
                LocalLoop++;
            }

            ListView_SetImageList( List_hWnd, IListSamllIcon, LVSIL_SMALL );

//          Create Columbs

            LVColumb.cx        = 100;
            LVColumb.pszText   = "Columb 0";
            LVColumb.iSubItem  = 0;
            LVColumb.mask      = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
            LVColumb.fmt       = LVCFMT_LEFT;
            ListView_InsertColumn(List_hWnd,0,&LVColumb);

            LVColumb.cx        = 100;
            LVColumb.pszText   = "Columb 1";
            LVColumb.iSubItem  = 1;
            LVColumb.mask      = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
            LVColumb.fmt       = LVCFMT_LEFT;
            ListView_InsertColumn(List_hWnd,1,&LVColumb);

            LVColumb.cx        = 100;
            LVColumb.pszText   = "Columb 2";
            LVColumb.iSubItem  = 2;
            LVColumb.mask      = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
            LVColumb.fmt       = LVCFMT_LEFT;
            ListView_InsertColumn(List_hWnd,2,&LVColumb);

            LVColumb.cx        = 100;
            LVColumb.pszText   = "Columb 3";
            LVColumb.iSubItem  = 3;
            LVColumb.mask      = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
            LVColumb.fmt       = LVCFMT_LEFT;
            ListView_InsertColumn(List_hWnd,3,&LVColumb);

            LocalLoop = 0;

//          Add Data To Columbs
            while(LocalLoop < 10)
            {
                sprintf(TempText,"ColA%d",LocalLoop);
                LVItem.pszText  = TempText;
                LVItem.mask     = LVIF_TEXT|LVIF_IMAGE;
                LVItem.iImage = LocalLoop % 5;
                LVItem.iSubItem = 0;
                ListView_InsertItem(List_hWnd,&LVItem);

                sprintf(TempText,"ColB%d",LocalLoop);
                LVItem.pszText  = TempText;
                LVItem.mask     = LVIF_TEXT|LVIF_IMAGE;
                LVItem.iImage = LocalLoop % 5;
                LVItem.iSubItem = 1;
                ListView_SetItem(List_hWnd,&LVItem);

                sprintf(TempText,"ColC%d",LocalLoop);
                LVItem.pszText  = TempText;
                LVItem.mask     = LVIF_TEXT|LVIF_IMAGE;
                LVItem.iImage = LocalLoop % 5;
                LVItem.iSubItem = 2;
                ListView_SetItem(List_hWnd,&LVItem);

                sprintf(TempText,"ColD%d",LocalLoop);
                LVItem.pszText  = TempText;
                LVItem.mask     = LVIF_TEXT|LVIF_IMAGE;
                LVItem.iImage = LocalLoop % 5;
                LVItem.iSubItem = 3;
                ListView_SetItem(List_hWnd,&LVItem);

                LocalLoop++;
            }

//          Set ListView Color
            ListView_SetTextColor(List_hWnd,RGB(0,128,0));
            InvalidateRect(List_hWnd,0,1);

//          Sort ListView Items
            ListView_SortItems(List_hWnd,0,0);

			CenterWindow(MainDialog_hWnd);

			break;
		}

		if(xMessage == WM_COMMAND) // Received A Message
		{
			if(wParam==100) //- Ok (Dialog Command)
			{

			}
			break;
		}

		if(xMessage == WM_SYSCOMMAND) // Received A System Menu Message
		{
			if(LOWORD(wParam)==1000) //- www.NetWorkDLS.Com (SysMenu Command)
			{
				ShellExecute(0,"Open","Http://www.NetWorkDLS.com",NULL,NULL,SW_SHOWNORMAL);
			}

			if(LOWORD(wParam) == 1001) //- Version (SysMenu Command)
			{
				MessageBox(MainDialog_hWnd, FileVersion, TitleCaption, 0 + MB_ICONASTERISK + MB_TASKMODAL);
			}
		}

		if(xMessage == WM_CLOSE)  // Received Close Message
		{
			EndDialog(MainDialog_hWnd,0);
		}

		break;
	}
	return 0;
}

Two details worth stealing: LVItem.iImage cycles through the five loaded icons so each row gets one, and the final ListView_SortItems sorts by column 0 using the default compare. The commented-out large-icon block shows how the same pattern extends to LVSIL_LARGE.

An unhandled error has occurred. Reload 🗙