1、对话框中的列表视图控件
在写一些数据库程序的时候经常会用到网格报表类型的列表视图控件。这个控件对于对话框程序来说和使用其它控件并没有多大区别。首先将其View属性设置为Report类型;然后为其关联一个CListCtrl控件类型的成员变量;最后在初始化对话框函数中设置其扩展类型为网格类型,并为其添加列。
但是,对于一个具有一定灵活性的程序来说,往往最初的列表视图控件列并不是一成不变的。我们通常将其封装到不同的函数中,在不同的命令下调用不同的布局函数,然后以不同的列表视图来呈现数据。例如,用户单击“患者信息”的时候,列表视图要以对应患者信息的列来呈现数据;当用户单击“诊疗信息”的时候,列表视图要以对应诊疗信息的列来呈现最近的诊疗情况。
上面两个操作是在一个程序界面下完成的。这就遇到了一个问题:每当我们在列表视图中切换布局的时候,原先已有的列应该怎样处理?查看MSDN中CListCtrl的成员,可以找到CListCtrl::DeleteColumn()成员函数。在该函数下面的Example中,MSDN提供了一个删除所有列的代码。该代码如下所示。
int nColumnCount = m_myListCtrl.GetHeaderCtrl()->GetItemCount(); // Delete all of the columns. for (int i=0; i < nColumnCount; i++) { m_myListCtrl.DeleteColumn(0); }
该代码是显而易见的,首先得到列表视图的列数,然后循环删除各列。要注意,在删除列之前,首先要调用DeleteAllItems()函数删除列表视图中的所有元素。
2、单文档中的列表视图
在对话框程序中固然可以使用列表视图控件,对于文档程序来说当然也能使用,只需在创建程序最后一步将View类的基类改为CFormView即可。但是,我们通常使用CListView作为将要使用列表视图单文档程序的基类。这样,我们就可以吧视图窗口当做列表视图来使用。
利用向导创建好程序后。我们可以在CXXXView::OnInitialUpdate()函数中对视图窗口进行初始化,插入列,并且设置一些扩展类型。一般代码如下所示。
CListCtrl& listCtrl = GetListCtrl(); listCtrl.ModifyStyle(0, LVS_REPORT); listCtrl.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT); // 设置扩展类型为网格和全选类型 listCtrl.InsertColumn(0, _T("姓名"), LVCFMT_CENTER, 100); listCtrl.InsertColumn(1, _T("性别"), LVCFMT_CENTER, 100);
3、单文档程序中删除列表视图中的列
这才是我写这篇文章的重点。如果你想做一个程序,这个程序在工具栏里面有几个按钮,你单击不同的按钮,列表视图中的布局会改变并列出相应的数据。首先,你得把不同的布局封装到不同的函数中;然后,在不同的按钮消息响应函数中调用不同的布局函数。就像第一条中讲的那样,首先得删除原先的列。当然你找到了MSDN中那个CListCtrl::DeleteColumn()方法,并且看到了它下面提供的例子。但是,如果你不加修饰的用了那段代码,你的程序会得到一个内存不能为read。
原因是在调用GetItemCount()上出了问题。意思就是问题处在得到列表视图列数上。是不是在文档程序中就不能得到列表视图的列数了呢?当然不是,可以利用::SendMessage()函数发送LVM_GETITEMCOUNT消息来得到列数,代码如下所示。
CListCtrl& m_myListCtrl = GetListCtrl(); HWND hList = ListView_GetHeader(m_myListCtrl); // 首先利用该宏得到视图表头句柄 int nColumnCount = ::SendMessage(hList, HDM_GETITEMCOUNT, 0, 0);
如果得到了视图的列数nColumnCount,调用第1小节中那段for循环就可以完成删除列的操作。要注意,在删除列之前,首先要调用DeleteAllItems()函数删除列表视图中的所有元素。
不过即使没有得到列数也是可以完成删除列的。可以利用DeleteColumn()方法返回值得特性,利用一个while语句完成所有列的删除。该函数调用成功返回非0,调用失败返回0值。意思就是如果有列就返回非0,如果删除完了就返回0。代码如下所示,ClearList()函数是笔者自己写的删除文档视图列表中列的函数。
void CXXXView::ClearList() { CListCtrl& m_myListCtrl = GetListCtrl(); m_myListCtrl.DeleteAllItems(); // Delete all of the columns. while (m_myListCtrl.DeleteColumn(0)); }