一、列表控件
先直观的认识下吧:
工具栏里的位置:
拖出来是这个样子:
MFC的所有可见的控件都只是一种窗口,要想操作它们必须通过MFC中和其相关联的类中提供的函数
和列表控件相关的类:
CListCtrl :列表控件,父类是CWnd类,控件类,故常用在对话框程序中。
CListView :列表视图,父类是CCtrlView类,视图类,故常用在文档视图应用程序中。
该类可以通过调用CListView::GetListCtrl()函数,返回相关的列表控件。
列表控件有四种显示方式(样式): ICon (图标)、Small ICon(小图标)、List(列表)、Report(报表)
CListCtrl类的使用:
这里我编写一个显示指定路径下所有文件并且双击列表项目能进入到相应目录,然后重新设置列表控件为选中路径下的文件列表的程序。
新建一个普通的对话框程序,拖放一个List Control控件,然后在其上面放置一个Combo Box控件(添加列表控件的四种显示样式数据)以便后面选择切换不同的样式
为List Control 控件关联名为m_wndListCtrl的控件变量,为Combo Box 关联名为m_wndComboBox的控件变量
为了显示列表控件图标,新建两个位图资源(一套大图标,一套小图标)
添加CImageList成员m_ilNormal、m_ilSmall : 保存图标列表
添加CStringLis成员m_strListPath : 保存列表控件里的路径信息
private:
CStringList m_strListPath;
CImageList m_ilSmall;
CImageList m_ilNormal;
给我们工程的Dlg类添加一个成员函数InitListCtrl用来初始化并显示显示控件,代码如下:
void CCListCtrlDlg::InitListCtrl()
{
// 为保证统一性初始设置组合框为Report
m_wndComboBox.SetCurSel (3);
// 创建图标列表
m_ilNormal.Create (IDB_BITMAP_NORMAL, 32, 1, RGB (255, 255, 255));
m_ilSmall.Create (IDB_BITMAP_SMALL, 16, 1, RGB (255, 255, 255));
// 设置图标列表
m_wndListCtrl.SetImageList (&m_ilNormal, LVSIL_NORMAL);
m_wndListCtrl.SetImageList (&m_ilSmall, LVSIL_SMALL);
// 添加ListCtrl表头
m_wndListCtrl.InsertColumn (0, "Name", LVCFMT_LEFT, 100);
m_wndListCtrl.InsertColumn (1, "Type", LVCFMT_LEFT, 100);
m_wndListCtrl.InsertColumn (2, "Size", LVCFMT_LEFT, 100);
m_wndListCtrl.InsertColumn (3, "LastWriteTime", LVCFMT_LEFT, 150);
// 为ListCtrl设置背景图片,记得先初始化Ole组件,设置字体背景为透明
AfxOleInit ();
m_wndListCtrl.SetTextBkColor (CLR_NONE);
m_wndListCtrl.SetBkImage ("D:/1.jpg");
}
关于List Control 控件的数据的插入(这里以Report样式为列):
1 首先调用CListCtrl::InsertColumn 插入表头信息
2 调用CListCtrl::InsertItem 插入每行的第一列
3 调用CListCtrl::SetItemText 插入每行的其余列数据
另外: 在ClistCtrl::SetBkImage的函数说明中有提到使用该函数必须先初始化
AfxOleInit ();
添加显示指定路径的函数ShowPath (strPath)
void CCListCtrlDlg::ShowPath(CString strPath)
{
// 显示列表控件之前清空控件和控件路径信息m_strListPath
m_wndListCtrl.DeleteAllItems ();
m_strListPath.RemoveAll ();
// 查找strPath(D:)目录下的所有(*.*)文件
strPath += "/*.*";
CFileFind find;
BOOL bRet = find.FindFile (strPath);
if (!bRet)
return;
int nItem = 0;
while (bRet)
{
bRet = find.FindNextFile ();
if (bRet == -1)
return;
if (find.IsDirectory ())
{
m_wndListCtrl.InsertItem (nItem, find.GetFileName(), 1);// Name
m_wndListCtrl.SetItemText (nItem, 1, "Directory");// Type
}
else
{
m_wndListCtrl.InsertItem (nItem, find.GetFileName(), 0);// Name
m_wndListCtrl.SetItemText (nItem, 1, find.GetFileName ().Mid (find.GetFileTitle().GetLength() + 1));// Type
// Size
DWORD dSize = find.GetLength () / 1024;
CString strFileSize;
strFileSize.Format ("%d KB", dSize);
m_wndListCtrl.SetItemText (nItem, 2, strFileSize);
// LastWriteTime
CTime tm;
find.GetLastWriteTime (tm);
CString strLastWriteTime;
strLastWriteTime = tm.Format ("%Y-%m-%d, %H-%M-%S");
m_wndListCtrl.SetItemText (nItem, 3, strLastWriteTime);
}
// 保存路径
m_strListPath.AddTail (find.GetFilePath());
++nItem;
}
}
这里使用CStringList对象保存路径信息,每次显示CListCtrl是都清空一次,这样也具备CListCtrl::SetItemData关联数据的效果还能有效防止内存泄漏
为了能双击进入列表控件选中的目录,为ClistCtrl添加NMDBCLK事件响应函数,编写如下代码:
void CCListCtrlDlg::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
LPNMITEMACTIVATE pItem = (LPNMITEMACTIVATE)pNMHDR;
ShowPath (m_strListPath.GetAt (m_strListPath.FindIndex (pItem->iItem)));
*pResult = 0;
}
最后给组合框控件添加CBN_SELCHANGE消息响应事件,编写如下代码:
void CCListCtrlDlg::OnSelchangeCombo()
{
// TODO: Add your control notification handler code here
int nSel = m_wndComboBox.GetCurSel ();
switch (nSel)
{
case 0:// 图标
m_wndListCtrl.ModifyStyle (LVS_LIST | LVS_REPORT | LVS_SMALLICON, LVS_ICON);
break;
case 1:// 小图标
m_wndListCtrl.ModifyStyle (LVS_ICON | LVS_REPORT | LVS_LIST, LVS_SMALLICON);
break;
case 2:// 列表
m_wndListCtrl.ModifyStyle (LVS_ICON | LVS_SMALLICON | LVS_REPORT, LVS_LIST);
break;
case 3:// 报表
m_wndListCtrl.ModifyStyle (LVS_ICON | LVS_SMALLICON | LVS_LIST, LVS_REPORT);
break;
}
}
这里奇怪的是调用CListCtrl::ModifyStyle如果后列表控件立刻就做响应的改变,推测MFC在该函数内部调用了使列表控件重绘的函数。
程序运行截图:
二、 树控件
和树控件相关的类:
CTreeCtrl :树控件 ,父类是CWnd,故通常在对话框程序中使用
CTreeView :树视图,父类是CCtrlView,故通常在文档视图应用程序中使用, 该类GetTreeCtrl可以获取树控件,把对树视图的操作转化为对树控件的操作
下面介绍CTreeCtrl的使用:
同样创建一个基于对话框的程序,拖放一个Tree Control控件并且为之关联一个控件变量m_wndTreeCtrl
设置控件的样式如下:
这里由于树控件的节点有选中和未选中两种状态,每种状态需设置不同的图标,故新建一个图标资源包含两个图标,为Dlg类添加一个CImageList的成员:m_ilNormal
添加控件初始化函数InitTreeCtrl()函数并在OnInitDialog中调用,InitTreeCtrl()函数如下:
void CMFCTreeDlg::InitTreeCtrl()
{
// 创建图标列表
m_ilNormal.Create (IDB_BITMAP_NORMAL, 32, 1, RGB (255, 255, 255));
// 设置图标列表
m_wndTreeCtrl.SetImageList (&m_ilNormal, TVSIL_NORMAL);
// 设置节点高度
m_wndTreeCtrl.SetItemHeight (36);
// 插入根节点
HTREEITEM hRoot1 = m_wndTreeCtrl.InsertItem ("root1", 0, 1);
// 插入子节点, 其中的0表示未选中的图标序号,1表示选中时的图标序号
HTREEITEM hChild1 = m_wndTreeCtrl.InsertItem ("Child-One", 0, 1, hRoot1);
HTREEITEM hChild2 = m_wndTreeCtrl.InsertItem ("Child-Tow", 0, 1, hRoot1);
HTREEITEM hChild3 = m_wndTreeCtrl.InsertItem ("Child-Three", 0, 1, hRoot1);
HTREEITEM hChild5= m_wndTreeCtrl.InsertItem ("Child-Four", 0, 1, hRoot1);
// 注意这里插入到hChild3之后
HTREEITEM hChild4 = m_wndTreeCtrl.InsertItem ("Child-One", 0, 1, hRoot1, hChild3);
HTREEITEM hRoot2 = m_wndTreeCtrl.InsertItem ("root2", 0, 1);
hChild1 = m_wndTreeCtrl.InsertItem ("Child-One", 0, 1, hRoot2);
hChild2 = m_wndTreeCtrl.InsertItem ("Child-Tow", 0, 1, hRoot2);
hChild3 = m_wndTreeCtrl.InsertItem ("Child-Three", 0, 1, hRoot2);
// 设置展开状态
m_wndTreeCtrl.Expand (hRoot2, TVE_EXPAND);
}
注意其中的CTreeCtrl::InsertItem函数的惨数:
HTREEITEM InsertItem(
PCTSTR lpszItem,//树节点的文本
int nImage,//未选中时图标索引
int nSelectedImage,//选中时的图标索引
HTREEITEM hParent = TVI_ROOT,//如果使用默认值,则插入的节点是根节点;如果指定该参数,该参数作为节点的父节点。
HTREEITEM hInsertAfter = TVI_LAST//在某个节点后插入当前节点。如果不指定该参数,在末尾添加节点
);
程序运行截图: