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






3.80/5 (8投票s)
使用 C 的 Win32 API - 无 MFC。
引言
您可以找到大量 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
消息将从以下位置复制文本
- 当
LVITEM
struct
的iSubItem
成员等于零时,复制自项目,或 - 当
iSubItem
大于零时,复制自子项目。
请参阅下面的代码并试用一下。
该函数确实很简单,并附带了嵌入式注释,逐步解释了它的作用。 然而,这里有一些元素
该函数的声明
int fExportListView(HWND hwndListView, FILE *filehandle, unsigned char *sFileName, char cSep, long lLines, long lCols);
函数的参数
hwndListView
是您的ListView
子窗口的句柄filehandle
是指向您的FILE
结构的指针sFileName
是指向您的文件名的“字符串”的指针cSep
是您希望用作字段之间的分隔符的字符lLines
和lCols
分别是ListView
中的行数和列数
您可能还需要这些 include
#include <windows.h> #include <stdio.h> #include <commctrl.h> (etc...)
C 语言背景:sprintf()
、fprintf()
、memset()
、fopen()
、fclose()
等函数,指针和数组。
API 背景:SendMessage()
、MessageBox()
等函数和一个名为 LVITEM
的 struct
。
调用 此函数,例如,像这样
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。