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

C 函数将列表导出到带分隔符的文本文件

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.80/5 (8投票s)

2004年12月8日

GPL3

3分钟阅读

viewsIcon

70949

downloadIcon

709

使用 C 的 Win32 API - 无 MFC。

Sample Image - fexportlistview.png

引言

您可以找到大量 C++ 和/或 MFC 代码来处理您的 ListView 控件,但可能没有足够的纯 C 和 API (SDK) 代码。 这个代码片段仅包含一个 C 函数 (fExportListView),该函数将 ListView 控件的文本内容输出到一个新创建的文本文件(带有分隔字段)。 输出文本文件可以导入到电子表格软件(如 MS Excel)或数据库中。 任何对彻底解释感兴趣的读者(仅限 SDK,无 MFC)都可以阅读 Bengi 撰写的优秀文章(标题为“在 Win32 API 下使用 ListView 控件”)。

这是首次尝试提出 C 和 API 代码 - 也许完全无用? 但是,如果您对简单的“插入 ListView 项目”或“插入 ListView 列”函数感兴趣,请告诉我,如果需要,我也会上传这些函数。

背景

您应该熟悉 C 语言和 C 程序的编译,包括 Win32 API。 无论您是否使用 MFC,您都应该了解 API。 因此,阅读 Charles Petzold 的著作“Programming Windows”(由 Microsoft Press 出版)是强制性的。 顺便说一句,非常感谢您提供的解释和鼓舞人心的例子,Petzold 先生。

使用代码

我假设您已经声明、创建、(重新)调整大小并填充(文本)了 ListView 控件(即,WC_LISTVIEW 类的窗口,具有样式,例如 WS_BORDER | WS_CHILD | WS_VISIBLE | LVS_REPORT)。 请参阅 MSDN 中的 CreateWindowEx 参考,和/或在您的 Visual Studio 项目中包含 ListView

请记住,在 ListView 中,您处理列、项目和子项目。 其中一列仅包含项目(通常是最左边的列),所有其他列仅包含子项目。 因此,对于您的 ListView 中的给定“行”,LVM_GETITEMTEXT 消息将从以下位置复制文本

  1. LVITEM structiSubItem 成员等于零时,复制自项目,或
  2. iSubItem 大于零时,复制自子项目。

请参阅下面的代码并试用一下。

该函数确实很简单,并附带了嵌入式注释,逐步解释了它的作用。 然而,这里有一些元素

该函数的声明

int fExportListView(HWND hwndListView, FILE *filehandle, unsigned char *sFileName, 
               char cSep, long lLines, long lCols);

函数的参数

  • hwndListView 是您的 ListView 子窗口的句柄
  • filehandle 是指向您的 FILE 结构的指针
  • sFileName 是指向您的文件名的“字符串”的指针
  • cSep 是您希望用作字段之间的分隔符的字符
  • lLineslCols 分别是 ListView 中的行数和列数

您可能还需要这些 include

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

C 语言背景sprintf()fprintf()memset()fopen()fclose() 等函数,指针和数组。

API 背景SendMessage()MessageBox() 等函数和一个名为 LVITEMstruct

调用 此函数,例如,像这样

  • fExportListView(hwndLV, f, "fExportListView_tab.txt", 9, 10, 5);
  • fExportListView(hwndLV, f, "fExportListView_pipe.txt", '|', 20, 8);

使用与上面描述的相同类型的参数 - 并在某个地方正确声明。

函数的返回值:如果出现问题或错误,则为 0,如果 OK,则为 1。

这是代码本身

int fExportListView(HWND hwndListView, FILE *filehandle, 
    unsigned char *sFileName, char cSep, long lLines, long lCols)
{
    
    /*********************
    * Local declarations *
    *********************/
    
    // LVITEM struct (see MSDN for content) :
    LVITEM lvi;
    // Max length of string into pszText member of LVITEM struct :
    long lMAX = 5000;
    // String buffer for pszText member of LVITEM struct :
    unsigned char LVtext[lMAX];
    // To appear in the caption of the MessageBox :
    static unsigned char *sYourApplicationsName = 
                    "You fill that in with your app name :)";
    // Error string you can use to 'MessageBox' and/or to 'fprintf'
    // into a logfile - a reasonable thing to do :)
    unsigned char sErrorString[lMAX];
    // Long integers for various tasks :
    long i, j;
    
    
    /*************************
    * Minimum error checking *
    *************************/
    
    // Checking ListView handle :
    if (hwndListView == NULL)
    {
        sprintf(sErrorString, "Handle of ListView NULL (fExportListView)");
        // Your good old Windows message box :
        MessageBox(NULL, (LPSTR) sErrorString, 
                  (LPSTR) sYourApplicationsName, 
                  MB_OK | MB_ICONEXCLAMATION);
        return(0);
    }
    
    // Checking number of lines against parameter value :
    i = SendMessage((HWND) hwndListView, (UINT) LVM_GETITEMCOUNT, 
                                         (WPARAM) 0, (LPARAM) 0);
    if (lLines != i)
    {
        sprintf(sErrorString, "%ld lines in ListView != %ld as" 
                " parameter (fExportListView)", i, lLines);
        MessageBox(NULL, (LPSTR) sErrorString, 
                  (LPSTR) sYourApplicationsName, 
                  MB_OK | MB_ICONEXCLAMATION);
        return(0);
    }
    
    // Checking whether ListView empty :
    if (i == 0)
    {
        sprintf(sErrorString, "ListView empty (fExportListView)");
        MessageBox(NULL, (LPSTR) sErrorString, 
                         (LPSTR) sYourApplicationsName, 
                         MB_OK | MB_ICONEXCLAMATION);
        return(0);
    }
    
    // Opening - rather creating - output file in write mode
    // (caution : overwrites a file with the same 'sFileName') :
    filehandle = fopen(sFileName, "w");
    if (filehandle == NULL)
    {
        sprintf(sErrorString, "Error occurred while creating" 
                " file %s (w mode) (fExportListView)", sFileName);
        MessageBox(NULL, (LPSTR) sErrorString, 
                         (LPSTR) sYourApplicationsName, 
                         MB_OK | MB_ICONEXCLAMATION);
        return(0);
    }
    
    
    /*************************************************************
    * Use a LVITEM struct to collect some text from the ListView *
    *************************************************************/
    
    for (i=0; i<lLines; i++)
    {
        memset(&lvi, 0, sizeof(lvi));  // Clean up before action
        // Fill in the members of the LVITEM struct :
        lvi.mask = LVIF_TEXT;
        // Minimum here to take care of the pszText member
        // - see other LVIF_xxx constants in MSDN

        lvi.state = 0;
        lvi.stateMask = 0;
        // lvi.iSubItem : not here, see 'j' loop below
        lvi.cchTextMax = lMAX - 1;
        // Length of string to be copied into pszText member

        lvi.pszText = LVtext;
        // String buffer for pszText member
        
        // Nota bene : starts at zero (item) and ends at 'lCols' (last subitem) :
        for (j=0; j<=lCols; j++)
        {
            // Important member of LVITEM struct you
            // need to fill in (j=0 : item; j>0 : subitem) :
            lvi.iSubItem = j;
            // Retrieve the text in an item or a subitem of line 'i' :
            SendMessage(hwndListView, LVM_GETITEMTEXT, (WPARAM) i, (LPARAM) &lvi);
            if (filehandle != NULL)
            {
                // No separator at the beginning of a line (here, at item level) ...
                if (j == 0) fprintf(filehandle, "%s", LVtext);
                // ... only between two consecutive fields (here, at subitem level) :
                else fprintf(filehandle, "%c%s", cSep, LVtext);
            }
        }
        // End of line, Windows style i.e. carriage return
        // (implicit) plus new line (explicit) :
        if (filehandle != NULL) fprintf(filehandle, "\n");
    }
    
    /*******************************
    * Close the output text file   *
    * and return from the function *
    *******************************/
    if (filehandle != NULL) fclose(filehandle);
    return(1);
}

历史

  • 2004 年 12 月 8 日:该函数的版本 1。
© . All rights reserved.