Introduction
If you need to insert columns and items into a ListView control, well you have probably spent some time looking for the SDK code. Here is a short article that consists of two ready-to-use C functions:
fInsertListViewColumn
to insert columns with strings into a ListView control.
fInsertListViewItem
to insert items / sub items with strings into a ListView control.
Background
- You should be familiar with C program compiling with Win32 API.
- C language background: pointers, strings, functions such as
sprintf
and memset
.
- API background: functions such as
GetClientRect
, InvalidateRect
, MessageBox
, SendMessage
, and struct
s like RECT
, LVITEM
, LVCOLUMN
.
Using the code
Declare, create and resize a ListView control, i.e., a child window of type WC_LISTVIEW
, of style, e.g., WS_BORDER | WS_CHILD | WS_VISIBLE | LVS_REPORT
. You may CreateWindowEx
the ListView, and/or include it in your Visual Studio project. This ListView will contain the text.
Bear in mind that in a ListView, you deal with columns, items and subitems. One column contains only items (usually, the leftmost column), all the other columns contain only subitems.
In the functions below, we use the keystone API function SendMessage
along with LVM_INSERTCOLUMN
, LVM_INSERTITEM
and LVM_SETITEM
messages to insert columns, items and subitems, respectively.
The functions are simple to understand, and come with embedded comments explaining what they do step by step. However, here are some elements:
Declaration of the functions:
int fInsertListViewColumn(HWND hwndListView,
long lCol, int iPercent, unsigned char* text);
int fInsertListViewItem(HWND hwndListView,long lLin,
long lCol, int iSubItemYesNo, unsigned char* text);
The parameters to the functions:
hwndListView
is the handle for your ListView control,
lLin
and lCol
are the zero-based indices of the line and column, respectively,
iPercent
is the width of the column you want to insert into the ListView control,
- an item is inserted if
iSubItemYesNo
equals 0, a subitem if iSubItemYesNo
equals 1,
text
is the 'string' that the pszText
member of the LVITEM
and LVCOLUMN
struct
s will point to.
You might also need these include
s:
#include <windows.h>
#include <stdio.h>
#include <commctrl.h>
(etc...)
Call the functions, e.g., like this - the following code will insert 5 columns and 8 lines (i.e., 5 columns, 8 items and 32 subitems):
int iColumnsToInsert = 5, iLinesToInsert = 8, i, j;
unsigned char sListViewText[200];
for (i=0; i<iColumnsToInsert; i++)
{
sprintf(sListViewText, "%c (column)", 65 + i);
fInsertListViewColumn(hwndLV, i, 100 / iColumnsToInsert, sListViewText);
}
for (i=0; i<iColumnsToInsert; i++)
{
for (j=0; j<iLinesToInsert; j++)
{
if (i == 0) sprintf(sListViewText, "%c%d (item)", 65 + i, j + 1);
else sprintf(sListViewText, "%c%d (subitem)", 65 + i, j + 1);
fInsertListViewItem(hwndLV, j, i, i == 0 ? 0 : 1, sListViewText);
}
}
Return values of the function:
Here is the code for the first function:
int fInsertListViewColumn(HWND hwndListView, long lCol,
int iPercent, unsigned char* text)
{
LVCOLUMN lvcolumn;
RECT rect;
GetClientRect(hwndListView, &rect);
static unsigned char *sYourApplicationsName = "you name it :)";
unsigned char sErrorString[5000];
int iResult;
iPercent = iPercent > 10 ? min(iPercent, 90) : 10;
int iWidth = (int) (rect.right * (iPercent / 100.0));
if (hwndListView == NULL)
{
sprintf(sErrorString,
"! Handle of ListView NULL (fInsertListViewColumn)");
MessageBox(NULL, (LPSTR) sErrorString,
(LPSTR) sYourApplicationsName, MB_OK | MB_ICONEXCLAMATION);
return(0);
}
memset(&lvcolumn, 0, sizeof(lvcolumn));
lvcolumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
lvcolumn.fmt = LVCFMT_LEFT;
lvcolumn.pszText = text;
lvcolumn.iSubItem = lCol;
lvcolumn.cx = iWidth;
if (SendMessage((HWND) hwndListView, (UINT) LVM_INSERTCOLUMN,
(WPARAM) (int) lCol, (LPARAM) &lvcolumn) == -1)
iResult = 0; else iResult = 1;
InvalidateRect(hwndListView, &rect, TRUE);
return(iResult);
}
Here is the code for the second function:
int fInsertListViewItem(HWND hwndListView, long lLin,
long lCol, int iSubItemYesNo, unsigned char* text)
{
LVITEM lvi;
RECT rect;
GetClientRect(hwndListView, &rect);
static unsigned char *sYourApplicationsName = "you name it :)";
unsigned char sErrorString[5000];
int iResult;
if (hwndListView == NULL)
{
sprintf(sErrorString,
"! Handle of ListView NULL (fInsertListViewItem)");
MessageBox(NULL, (LPSTR) sErrorString,
(LPSTR) sYourApplicationsName, MB_OK | MB_ICONEXCLAMATION);
return(0);
}
memset(&lvi, 0, sizeof(lvi));
lvi.mask = LVIF_TEXT;
lvi.state = 0;
lvi.stateMask = 0;
lvi.pszText = text;
lvi.iItem = lLin;
lvi.iSubItem = lCol;
switch(iSubItemYesNo)
{
case 0:
if (SendMessage((HWND) hwndListView,
(UINT) LVM_INSERTITEM, (WPARAM) 0, (LPARAM) &lvi) == -1)
iResult = 0; else iResult = 1;
break;
case 1:
if (SendMessage((HWND) hwndListView,
(UINT) LVM_SETITEM, (WPARAM) 0, (LPARAM) &lvi) == FALSE)
iResult = 0; else iResult = 1;
break;
default:
sprintf(sErrorString,
"! Unexpected iSubItemYesNo value: %d (fInsertListViewItem)",
iSubItemYesNo);
MessageBox(NULL, (LPSTR) sErrorString,
(LPSTR) sYourApplicationsName, MB_OK | MB_ICONEXCLAMATION);
return(0);
break;
}
InvalidateRect(hwndListView, &rect, TRUE) ;
return(iResult);
}
Points of Interest
- In MSDN, about inserting columns (title 'LVCOLUMN Structure (Windows Explorer and Controls)'):
If a column is added to a list-view control with index 0 (the leftmost column) and with LVCFMT_RIGHT
or LVCFMT_CENTER
specified, the text is not right-aligned or centered. The text in the index 0 column is left-aligned.
- If you write SDK programs, remember the MSDN warning about the
GetMessage
function:
Because the return value can be nonzero, zero, or -1, avoid code like this:
while (GetMessage( lpMsg, hWnd, 0, 0)) ...
The possibility of a -1 return value means that such code can lead to fatal application errors. Instead, use the code like this:
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
References
- Giannini M., Keogh J. Windows programming - Programmer's notebook. Prentice Hall PTR, 2001, pp. 381-407.
- Bengi. Using ListView control under Win32 API (CodeProject article).
- Petzold C. Programming Windows (fifth edition). Microsoft Press, 1999.
- MSDN: keywords: CreateWindowEx --> ListView --> listview styles, messages, notifications.
History
- December 24th, 2004: version 1.