65.9K
CodeProject 正在变化。 阅读更多。
Home

用于在 ListView 控件中插入列、项目和子项目的 C 函数

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.92/5 (11投票s)

2004年12月24日

GPL3

3分钟阅读

viewsIcon

72867

downloadIcon

875

Win32 API 和 C。

引言

如果您需要在 ListView 控件中插入列和项目,那么您可能已经花了一些时间寻找 SDK 代码。这是一篇简短的文章,其中包含两个随时可用的 C 函数

  • fInsertListViewColumn 用于将带有字符串的列插入 ListView 控件。
  • fInsertListViewItem 用于将带有字符串的项目/子项目插入 ListView 控件。

背景

  • 您应该熟悉使用 Win32 API 进行 C 程序编译。
  • C 语言背景:指针、字符串、函数(例如 sprintfmemset)。
  • API 背景:函数(例如 GetClientRectInvalidateRectMessageBoxSendMessage)和 struct(例如 RECTLVITEMLVCOLUMN)。

使用代码

声明、创建和调整 ListView 控件的大小,即类型为 WC_LISTVIEW 的子窗口,样式例如 WS_BORDER | WS_CHILD | WS_VISIBLE | LVS_REPORT。您可以 CreateWindowEx ListView,和/或将其包含在您的 Visual Studio 项目中。此 ListView 将包含文本。

请记住,在 ListView 中,您处理的是列、项目和子项目。一列仅包含项目(通常是最左边的列),所有其他列仅包含子项目。

在下面的函数中,我们使用关键 API 函数 SendMessage 以及 LVM_INSERTCOLUMNLVM_INSERTITEMLVM_SETITEM 消息来分别插入列、项目和子项目。

这些函数简单易懂,并带有嵌入式注释,逐步解释它们的作用。但是,这里有一些元素

函数的声明

int fInsertListViewColumn(HWND hwndListView, 
    long lCol, int iPercent, unsigned char* text);
int fInsertListViewItem(HWND hwndListView,long lLin, 
    long lCol, int iSubItemYesNo, unsigned char* text);

函数的参数

  • hwndListView 是您的 ListView 控件的句柄。
  • lLinlCol 分别是行和列的从零开始的索引。
  • iPercent 是您要插入到 ListView 控件中的列的宽度百分比。
  • 如果 iSubItemYesNo 等于 0,则插入项目;如果 iSubItemYesNo 等于 1,则插入子项目。
  • textLVITEMLVCOLUMN structpszText 成员将指向的“字符串”。

您可能还需要这些 include

#include <windows.h>
#include <stdio.h>
#include <commctrl.h>
(etc...)

调用函数,例如像这样 - 以下代码将插入 5 列和 8 行(即 5 列,8 个项目和 32 个子项目)

int iColumnsToInsert = 5, iLinesToInsert = 8, i, j;
unsigned char sListViewText[200];
// Remember 65 is ASCII decimal for 'A', 66 is 'B', etc.:
for (i=0; i<iColumnsToInsert; i++)
{
    sprintf(sListViewText, "%c (column)", 65 + i);
    // Columns are labeled 'A', 'B', ... , 'E':
    fInsertListViewColumn(hwndLV, i, 100 / iColumnsToInsert, sListViewText);
}
for (i=0; i<iColumnsToInsert; i++)
{
    for (j=0; j<iLinesToInsert; j++)
    {
        // Items / subitems are labeled 'A1', 'A2', ... , 'E8':
        if (i == 0) sprintf(sListViewText, "%c%d (item)", 65 + i, j + 1);
            else sprintf(sListViewText, "%c%d (subitem)", 65 + i, j + 1);
        // Here iSubItemYesNo=0 if i is 0; iSubItemYesNo=1 otherwise:
        fInsertListViewItem(hwndLV, j, i, i == 0 ? 0 : 1, sListViewText);
    }
}

函数的返回值

  • 0 表示失败。
  • 1 表示正常。

这是第一个函数的代码

int fInsertListViewColumn(HWND hwndListView, long lCol, 
        int iPercent, unsigned char* text)
{
/*********************
* Local declarations *
*********************/

// LVCOLUMN struct (see MSDN for content):
LVCOLUMN lvcolumn;

// RECT struct, used in column width and 
// WM_PAINT jobs:
RECT rect;
// Enter the client area of the ListView 
//into the RECT structure:
GetClientRect(hwndListView, &rect);

// To appear in the caption of the MessageBox:
static unsigned char *sYourApplicationsName = "you name it :)";
// Error 'string' you can use to 'MessageBox' and/or to 
// 'fprintf' into a logfile:
unsigned char sErrorString[5000];

// Value to be returned after the function tried 
// to insert a column:
int iResult;

/*************************
* Minimum error checking *
*************************/

// iPercent adjustement before display, e.g.:
iPercent = iPercent > 10 ? min(iPercent, 90) : 10;

// Column width, with 'rect.right' the x-coordinate of 
// the lower-right corner of the RECT:
int iWidth = (int) (rect.right * (iPercent / 100.0));

// Check ListView handle:
if (hwndListView == NULL)
{
    sprintf(sErrorString, 
        "! Handle of ListView NULL (fInsertListViewColumn)");
    MessageBox(NULL, (LPSTR) sErrorString, 
        (LPSTR) sYourApplicationsName, MB_OK | MB_ICONEXCLAMATION);
    return(0);
}

/***********************************************
* Use a LVCOLUMN struct to describe the column *
* that you want to insert into the ListView    *
***********************************************/

// Initialize the LVCOLUMN struct (see LVCF_xxx and 
// LVCFMT_xxx values in MSDN):
memset(&lvcolumn, 0, sizeof(lvcolumn));
// Necessary mask values for this job:
lvcolumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
// Left-align the text:
lvcolumn.fmt = LVCFMT_LEFT;
// Point to the right address:
lvcolumn.pszText = text;
// Nota bene: you might want to check lCol value first
lvcolumn.iSubItem = lCol;
// Set column width:
lvcolumn.cx = iWidth;

// SendMessage returns the number (zero based) of the 
// column inserted, 
// or -1 if it fails:
if (SendMessage((HWND) hwndListView, (UINT) LVM_INSERTCOLUMN, 
   (WPARAM) (int) lCol, (LPARAM) &lvcolumn) == -1) 
           iResult = 0; else iResult = 1;

// Paints (updates) the client area of the ListView control:
InvalidateRect(hwndListView, &rect, TRUE);

// Returns either 1 (OK) or 0 (failed to insert column - e.g., 
// lCol too big):
return(iResult);
}

这是第二个函数的代码

int fInsertListViewItem(HWND hwndListView, long lLin, 
   long lCol, int iSubItemYesNo, unsigned char* text)
{
/*********************
* Local declarations *
*********************/

// LVITEM struct (see MSDN for content):
LVITEM lvi;

// RECT struct, used in column width and WM_PAINT jobs:
RECT rect;
// Enter the client area of the ListView into
// the RECT structure:
GetClientRect(hwndListView, &rect);

// To appear in the caption of the MessageBox:
static unsigned char *sYourApplicationsName = "you name it :)";
// Error string you can use to 'MessageBox' and/or to 'fprintf' 
// into a logfile:
unsigned char sErrorString[5000];

// Value to be returned after the function tried to insert 
// an item / subitem:
int iResult;

/*************************
* Minimum error checking *
*************************/

// Check ListView handle:
if (hwndListView == NULL)
{
    sprintf(sErrorString, 
        "! Handle of ListView NULL (fInsertListViewItem)");
    MessageBox(NULL, (LPSTR) sErrorString, 
      (LPSTR) sYourApplicationsName, MB_OK | MB_ICONEXCLAMATION);
    return(0);
}

/*****************************************************
* Use a LVITEM struct to describe the item / subitem *
* that you want to insert into the ListView          *
*****************************************************/

// Initialize the LVITEM struct (see LVIF_xxx reference in MSDN):
memset(&lvi, 0, sizeof(lvi));
// Minimum mask value for this job:
lvi.mask = LVIF_TEXT;
lvi.state = 0;
lvi.stateMask = 0;
// Point to the right address:
lvi.pszText = text;
// Nota bene: you might want to check lLin and lCol values first
lvi.iItem = lLin;
lvi.iSubItem = lCol;
    
switch(iSubItemYesNo)
{
    case 0:
        // Send LVM_INSERTITEM message if you want to 
        // insert an item (returns -1 if it fails):
        if (SendMessage((HWND) hwndListView, 
           (UINT) LVM_INSERTITEM, (WPARAM) 0, (LPARAM) &lvi) == -1) 
                       iResult = 0; else iResult = 1;
        break;
    case 1:
        // Send LVM_SETITEM message if you want to insert 
        // a subitem (returns FALSE if it fails):
        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;
}

// Paints (updates) the client area of the ListView control:
InvalidateRect(hwndListView, &rect, TRUE) ;

// Returns either 1 (OK) or 0 (failed to insert an item / subitem):
return(iResult);
}

关注点

  • 在 MSDN 中,关于插入列(标题为“LVCOLUMN Structure (Windows Explorer and Controls)”)

    如果将列添加到索引为 0(最左边的列)且指定了 LVCFMT_RIGHTLVCFMT_CENTER 的列表视图控件,则文本不会右对齐或居中对齐。索引 0 列中的文本是左对齐的。

  • 如果您编写 SDK 程序,请记住 MSDN 关于 GetMessage 函数的警告

    因为返回值可以是非零值、零或 -1,所以要避免像这样的代码

    while (GetMessage( lpMsg, hWnd, 0, 0)) ...

    返回值为 -1 的可能性意味着此类代码可能导致致命的应用程序错误。相反,使用像这样的代码

    BOOL bRet;
    while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
    { 
        if (bRet == -1)
        {
            // handle the error and possibly exit
        }
        else
        {
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        }
    }

参考文献

  • Giannini M., Keogh J. Windows programming - Programmer's notebook. Prentice Hall PTR, 2001, pp. 381-407.
  • Bengi. 使用 Win32 API 下的 ListView 控件(CodeProject 文章)。
  • Petzold C. Programming Windows (fifth edition). Microsoft Press, 1999.
  • MSDN:关键词:CreateWindowEx --> ListView --> listview 样式、消息、通知。

历史

  • 2004 年 12 月 24 日th:版本 1。
© . All rights reserved.