MFC中将List Control列表视图控件中的内容写到txt和xls中

10 篇文章 0 订阅

列表视图控件简介
   

 1. 列表视图控件List Control同样比较常见,它能够把任何字符串内容以列表的方式显示出来,这种显示方式的特点是整洁、直观,在实际应用中能为用户带来方便。       列表视图控件是对前面讲到的列表框控件List Box的改进和延伸。列表视图控件的列表项一般有图标(Icon)和标签(Label)两部分。图标是对列表项的图形描述,标签是文字描述。当然列表项可以只包含图标也可以只包含标签。      
 
 2. 列表视图控件有4种风格:Icon、Small Icon、List和Report。下面简单说下4种风格各自的特点:
     Icon大图标风格:列表项的图标通常为32×32像素,在图标的下面显示标签。       
     Small Icon小图标风格:列表项的图标通常为16×16像素,在图标的右面显示标签。      
     List列表风格:与小图标风格类似,图标和文字的对齐方式不同。       
     Report报表风格:列表视图控件可以包含一个列表头来描述各列的含义。每行显示一个列表项,通常可以包含多个列表子项。最左边的列表子项的标签左边可以添加一个图标,而它右边的所有子项则只能显示文字。这种风格的列表视图控件很适合做各种报表。


列表视图控件的通知消息


   通知码为NM_CLICK的通知消息的消息映射入口:      

ON_NOTIFY(NM_CLICK, IDC_PROGRAM_LANG_LIST, &CExample29Dlg::OnNMClickProgramLangList)       还有消息处理函数自动生成时的形式:
   

void CExample29Dlg::OnNMClickProgramLangList(NMHDR *pNMHDR, LRESULT *pResult)     
  {           LPNMITEMACTIVATE pNMItemActivate=reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);          
   // TODO: Add your control notification handler code here           
  *pResult = 0;    
  }


我们看到,上面的代码中将NMHDR指针类型的pNMHDR强制转换为LPNMITEMACTIVATE类型的pNMItemActivate,那么我们就可以在函数中通过pNMHDR来访问NMHDR结构,也可以通过pNMItemActive指针变量来访问第一个元素为NMHDR结构体变量的扩充结构。       当然列表视图控件还有一些自己特有的通知消息,下面就介绍几个其中比较常用的。       

LVN_ITEMCHANGING 和LVN_ITEMCHANGED:当列表视图的状态发生变化时,会发送这两个通知消息。例如,当用户选择了新的列表项时,程序就会收到这两个消息。
消息会附带一个指向NMLISTVIEW 结构的指针,消息处理函数可从该结构中获得状态信息。两个消息的不同之处在于,前者的消息处理函数如果返回TRUE,那么就阻
止选择的改变,如果返回FALSE,则允许改变。       

LVN_KEYDOWN:该消息表明了一个键盘事件。消息会附带一个指向NMLVKEYDOWN结构的指针,通过该结构程序可以获得按键的信息。      
 LVN_BEGINLABELEDIT 和LVN_ENDLABELEDIT:分别在用户开始编辑和结束编辑标题时发送。消息会附带一个指向NMLVDISPINFO结构的指针。在前者的消息处理函数中,可以调用GetEditControl成员函数返回一个指向用于编辑标题的编辑框的指针,如果处理函数返回FALSE,则允许编辑,如果返回TRUE,则禁止编辑。在后者的消息处理函数中,NMLVDISPINFO结构中的item.pszText指向编辑后的新标题,如果pszText 为NULL,那么说明用户放弃了编辑,否则,程序应负责更新表项的标题,这可以由SetItem或SetItemText函数来完成。
 ## 列表视图控件的相关结构体
 下面我们来介绍一下与列表视图控件有关的一些结构体。       
 1. NMHDR结构体

typedef struct tagNMHDR {           
    HWND hwndFrom;     // 控件窗口的句柄            
    UINT_PTR idFrom;   // 控件ID              
    UINT code;         // 控件的通知消息码          
} NMHDR;  


此结构体在很多情况下都是其他扩充结构体的第一个元素,比如上面的NMITEMACTIVATE结构体:

typedef struct tagNMITEMACTIVATE {             
  NMHDR hdr;                
 int iItem;              
 int iSubItem;               
 UINT uNewState;              
 UINT uOldState;                
 UINT uChanged;                 
 POINT ptAction;                 
 LPARAM lParam;                 
 UINT uKeyFlags;           
 } NMITEMACTIVATE, *LPNMITEMACTIVATE; 


  2. LVITEM 结构体       该结构体包含了列表视图控件中列表项或列表子项的各种属性。
  

typedef struct _LVITEM {           
 UINT mask;           // 掩码位的组合(下面有对应掩码的元素都已在括号中标出掩码),表明哪些元素是有效的          
 int iItem;           // 列表项的索引             
int iSubItem;        // 列表子项的索引             
UINT state;          // 状态,下面会列出。(LVIF_STATE)              
UINT stateMask;      // 状态掩码,用来说明要获取或设置哪些状态。下面会列出              
LPTSTR pszText;      // 指向列表项或列表子项的标签字符串。(LVIF_TEXT)           
int cchTextMax;      // pszText指向缓冲区的字符的个数,包括字符串结束符。   (LVIF_TEXT)              
int iImage;          // 图标的索引。(LVIF_IMAGE)               
LPARAM lParam;       // 32位的附加数据。(LVIF_PARAM)          
#if (_WIN32_IE >= 0x0300)                       
   int iIndent;            
#endif             
#if (_WIN32_WINNT >= 0x501)                      
   int iGroupId;                       
   UINT cColumns; // tile view columns                       
   PUINT puColumns;              
#endif             
#if (_WIN32_WINNT >= 0x0600)                      
    int* piColFmt;                     
     int iGroup;             
#endif       } LVITEM, *LPLVITEM;  


3. LVCOLUMN结构体      
 该结构体仅适用于Report报表式列表视图控件。在向列表控件中插入一列时需要用到此结构体。它包含了列表控件某列的各种属性。
 

typedef struct _LVCOLUMN {            
UINT mask;              // 掩码位的组合(下面有对应掩码的元素都已在括号中标出掩码),表明哪些元素是有效的            
int fmt;                    // 该列的表头和列表子项的标签正文显示格式,可以是LVCFMT_CENTER、LVCFMT_LEFT或LVCFMT_RIGHT。(LVCF_FMT)           
int cx;                     // 以像素为单位的列的宽度。(LVCF_FMT)          
LPTSTR pszText;    // 指向列表头标题正文的字符串。(LVCF_TEXT)             
int cchTextMax;     // pszText指向缓冲区的字符的个数,包括字符串结束符。(LVCF_TEXT)              
int iSubItem;          // 该列的索引。(LVCF_SUBITEM)          
#if (_WIN32_IE >= 0x0300)                   
    int iImage;                    
    int iOrder;           
#endif            
#if (_WIN32_WINNT >= 0x0600)                     
    int cxMin;                      
    int cxDefault;                    
    int cxIdeal;            
#endif            
} LVCOLUMN, *LPLVCOLUMN;  

4. NMLISTVIEW结构体       
该结构体存放了列表视图控件通知消息的相关信息。列表视图控件的大部分通知消息都会附带指向该结构体的指针。

typedef struct tagNMLISTVIEW 
{          
 NMHDR hdr;      // 标准的NMHDR 结构              
 int iItem;       // 列表项的索引               
 int iSubItem;    // 列表子项的索引               
 UINT uNewState;  // 列表项或列表子项的新状态               
 UINT uOldState;  // 列表项或列表子项原来的状态              
 UINT uChanged;   // 取值与LVITEM的mask成员相同,用来表明哪些状态发生了变化                    POINT ptAction;  // 事件发生时鼠标的客户区坐标              
 LPARAM lParam;   //32位的附加数据        
 } NMLISTVIEW, *LPNMLISTVIEW;  


列表视图控件的创建       


MFC同样为列表视图控件的操作提供了CListCtrl类。    
   如果我们不想在对话框模板中直接拖入List Control来使用列表视图控件,而是希望动态创建它,则要用到CListCtrl类的成员函数Create函数,原型如下:
   

virtual BOOL Create(  
 DWORD dwStyle,  
 const RECT& rect,  
 CWnd* pParentWnd,  
 UINT nID );


参数rect为列表视图控件的位置和尺寸,pParentWnd为指向父窗口的指针,nID指定列表视图控件的ID,最复杂的一个参数同样还是dwStyle,它用于设定列表视图控件的风格,可以是以下风格的组合:
 LVS_ALIGNLEFT                        
 显示格式是大图标或小图标时,标签放在图标的左边
  LVS_ALIGNTOP                         显示格式是大图标或小图标时,标题放在图标的上边
       LVS_AUTOARRANGE                 显示格式是大图标或小图标时,自动排列控件中的列表项
       LVS_EDITLABELS                      用户可以修改标签文本
       LVS_ICON                                 指定大图标显示格式
       LVS_LIST                                  指定列表显示格式
       LVS_NOCOLUMNHEADER         在报表格式中不显示列的表头
       LVS_NOLABELWRAP                显示格式是大图标时,使标签文本单行显示。默认是多行显示
       LVS_NOSCROLL                       列表视图控件无滚动条,此风格不能与LVS_LIST或LVS_REPORT组合使用
       LVS_NOSORTHEADER              报表格式的列表视图控件的表头不能作为排序按钮使用
       LVS_OWNERDRAWFIXED        由控件的拥有者负责绘制表项
       LVS_REPORT                           指定报表显示格式
       LVS_SHAREIMAGELISTS           使列表视图共享图像序列
       LVS_SHOWSELALWAYS           即使控件失去输入焦点,仍显示出项的选择状态
       LVS_SINGLESEL                       指定只能有一个列表项被选中。默认时可以多项选择
       LVS_SMALLICON                      指定小图标显示格式
       LVS_SORTASCENDING             按升序排列列表项
       LVS_SORTDESCENDING          按降序排列列表项
   与前面的控件一样,除了以上风格一般我们还要为列表视图控件设置WS_CHILD和WS_VISIBLE风格。对于直接在对话框模板中创建的列表视图控件,其属性页中的属性与上述风格是对应的,例如,属性Alignment默认为Left,也就等价于指定了LVS_ALIGNLEFT风格。


CListCtrl类的主要成员函数


   CListCtrl类有很多成员函数,这里就为大家介绍几个常用的主要成员函数。      
    UINT GetSelectedCount( ) const;
      该函数返回列表视图控件中被选择列表项的数量。      

POSITION GetFirstSelectedItemPosition( ) const;   
       获取列表视图控件中第一个被选择项的位置。返回的POSITION值可以用来迭代来获取其他选择项,可以当作参数传入下面的GetNextSelectedItem函数来获得选择项的索引。如果没有被选择项则返回NULL。      
 int GetNextSelectedItem(POSITION& pos) const;      
        该函数获取由pos指定的列表项的索引,然后将pos设置为下一个位置的POSITION值。参数pos为之前调用GetNextSelectedItem或GetFirstSelectedItemPosition
        得到的POSITION值的引用。返回值就是pos指定列表项的索引。        int GetItemCount( ) const;     
        获取列表视图控件中列表项的数量。      
 int InsertColumn(int nCol,const LVCOLUMN* pColumn );
  int InsertColumn(int nCol,LPCTSTR lpszColumnHeading,int nFormat = LVCFMT_LEFT,int nWidth = -1,int nSubItem = -1 );
       这两个函数用于在报表式列表视图控件中插入列。第一个函数中,nCol参数为插入列的索引,pColumn参数指向LVCOLUMN结构,其中包含了插入列的属性。第二个函数中,nCol参数也是插入列的索引,lpszColumnHeading参数为列标题字符串,nFormat参数为列中文本的对齐方式,可以是LVCFMT_LEFT、LVCFMT_RIGHT或LVCFMT_CENTER,nWidth参数为列宽,nSubItem为插入列对应列表子项的索引。两个函数在成功时都返回新列的索引,失败都返回-1。    
 BOOL DeleteColumn(int nCol);    
     该函数用于删除列表视图控件中的某列。参数nCol为删除列的索引。删除成功则返回TRUE,失败返回FALSE。       
 int InsertItem(int nItem,LPCTSTR lpszItem);     
      向列表视图控件中插入新的列表项。参数nItem为要插入项的索引,参数lpszItem为要插入项的标签字符串。如果插入成功则返回新列表项的索引,否则返回-1。       
 BOOL DeleteItem(int nItem);  
     从列表视图控件中删除某个列表项。参数nItem指定了要删除的列表项的索引。删除成功则返回TRUE,否则返回FALSE。       
 CString GetItemText(int nItem,int nSubItem) const;    
      获取指定列表项或列表子项的显示文本。参数nItem指定了列表项的索引,参数nSubItem指定了列表子项的索引。       
 BOOL SetItemText(int nItem,int nSubItem,LPCTSTR lpszText); 
       设置指定列表项或列表子项的显示文本。参数nItem和nSubItem同GetItemText。参数lpszText为要设置的显示文本字符串。如果设置成功则返回TRUE,否则返回FALSE。    

 DWORD_PTR GetItemData(int nItem) const;   
        该函数用于获取指定列表项的附加32位数据。参数nItem为列表项的索引。返回值就是由nItem指定列表项的附加32位数据。       
 BOOL SetItemData(int nItem,DWORD_PTR dwData);    
        该函数用于为指定列表项设置附加32位是数据。参数nItem为列表项的索引,参数dwData为列表项的附加32位数据。
  
今天来说一下如何将List Control列表视图控件中的内容写到txt和xls中去。
首先在对话框窗口中插入一个按钮或者单选按钮(Radio Button),然后右键选择“添加事件处理程序”,在其中添加如下代码:

​​

if (m_list.GetItemCount() <= 0)   
	{
		AfxMessageBox(_T("列表中没有记录需要保存"));
		return;
	}
	char szFilters[] = _T("txt文件(*.txt)|*.txt|xls文件(*.xls)|*.xls|所有文件(*.*)|*.*||");
	CFileDialog dlg(FALSE, _T("txt"), _T("Save Data"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilters, this);
	if (dlg.DoModal() != IDOK)
		return;
	CString strFilePath;
	strFilePath = dlg.GetPathName();//获得文件路径名
	DWORD dwRe = GetFileAttributes(strFilePath);
	if (dwRe != (DWORD)-1)
	{
		DeleteFile(strFilePath);
	}
	//保存文件数据
	FILE*fp;
	fopen_s(&fp, strFilePath, "w");
	char str[1024];
	if (fp == NULL)
	{
		printf("save file error\n");
		return;
	}
	//得到listctrl的所有列的header字符串内容
        int nHeadNum = m_list.GetHeaderCtrl()->GetItemCount();
	LVCOLUMN lvcol;
	char str_out[256];
	int nColNum;
	nColNum = 1;
	lvcol.mask = LVCF_TEXT;
	lvcol.pszText = str_out;
	lvcol.cchTextMax = 256;
	while (m_list.GetColumn(nColNum, &lvcol))
	{
		nColNum++;
		fprintf_s(fp, "%s\t", lvcol.pszText);
	}
	fprintf_s(fp, "\n", lvcol.pszText);

	//读取listctrl数据

	int nRow = m_list.GetItemCount();
	for (int i = 0; i < nRow; i++)
         {       
                for(int j=1;j<nColNum;j++)

		{
			CString str_data = m_list.GetItemText(i,j);//获取指定列
			fprintf_s(fp, "%s\t", str_data);  // \t为水平制表符
		}
		fprintf_s(fp, "\n");
         }
	fclose(fp);


通过这样就可以把 List Control 中的所有内容(包括标题)都写到了txt或者xls表格中。

如果只想输出某一列内容只需修改最后读取listctrl数据代码即可,将第二个for循环去掉,里面的代码修改为

CString str_data = m_list.GetItemText(i, 6);//获取指定的第六列数据

这样最后只存储了第六列数据了。

如果不想将Column表头写到txt中,只需删除所有列的header字符串代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值