Tree Control 控件
List Control 控件
(本章节中例子都是用 VS2005 编译调试的)
说明:
树形控件是用于构造树形的结构,其中有一个根接点(Root)然后下面有许多子结点,而每个子结点上有允许有一个或多个或没有子结点.在树形控件中每一个结点都有一个句柄(HTREEITEM),同时添加结点时必须提供该结点的父结点句柄(其中根Root结点只有一个,既不可以添加也不可以删除), MFC 中使用 CTreeCtrl 类来封装树形控件的各种操作.树形控件的消息映射使用 ON_NOTIFY 宏.
三个重要结构:
TVINSERTSTRUCT(MSDN 链接)
作用: 这个结构体包含了在树形图控件添加子节点时需要的相关信息
结构体定义:
typedef struct _TV_INSERTSTRUCT { HTREEITEM hParent; // Handle to the parent item HTREEITEM hInsertAfter; // Handle to the item after which the new item is to be inserted TV_ITEM item; // TV_ITEM structure that contains information about the item to add } TV_INSERTSTRUCT, FAR *LPTV_INSERTSTRUCT;
TVITEM(MSDN 链接)
作用: 记录着被添加的数的节点的信息
结构体定义:
typedef struct _TV_ITEM { //tvi UINT mask; // ndicates which of the other structure members contain valid data HTREEITEM hItem; // Handle to the item to which this structure refers UINT state; // Set of bit flags and image list indexes that indicate the item's state UINT stateMask; // Bits of the state member that are valid LPSTR pszText; // Pointer to a null-terminated string that contains the item text int cchTextMax; // Size of the buffer pointed to by the pszText member int iImage; // Index in the tree view control's image list of the icon image to use when the item is in the nonselected state int iSelectedImage; //Index in the tree view control's image list of the icon image to use when the item is in the selected state. int cChildren; // Indicates whether the item has associated child items LPARAM lParam; // Specifies a 32-bit value to associate with the item. }TV_ITEM, FAR *LPTV_ITEM;
NMTREEVIEW(MSDN 链接)
作用: 包含关于树形视通知消息的信息
结构体定义:
typedef struct _NM_TREEVIEW { NMHDR hdr; // NMHDR structure that contains information about this message UINT action; // Notification-specific action flag TV_ITEM itemOld; // TV_ITEM structure that contains information about the old item state TV_ITEM itemNew; // TV_ITEM structure that contains information about the new item state. POINT ptDrag; // POINTstructure that contains the client coordinates of the mouse at the time the event occurred that caused the message to be sent } NM_TREEVIEW; typedef NM_TREEVIEW FAR* LPNM_TREEVIEW;
CTreeCtrl 常用函数(单击函数链接至MSDN):
在 Create 中 dwStyle 中可以使用以下一些树形控件的专用风格:
TVS_HASLINES 在父/子结点之间绘制连线
TVS_LINESATROOT 在根/子结点之间绘制连线
TVS_HASBUTTONS 在每一个结点前添加一个按钮,用于表示当前结点是否已被展开
TVS_EDITLABELS 结点的显示字符可以被编辑
TVS_SHOWSELALWAYS 在失去焦点时也显示当前选中的结点
TVS_DISABLEDRAGDROP 不允许Drag/Drop
TVS_NOTOOLTIPS 不使用ToolTip显示结点的显示字符
代码示例:
先在主对话框中拖入一个 Tree Control 控件,,然后为这个控件添加控制变量其变量类型为 CTreeCtrl 类和名为 m_tc.资源视图如下:
为这个控件添加子节点,节点结构为如下所示:
+--- Parent1
+--- Child1_1
+--- Child1_2
+--- Parent2
+--- Child2_1
在对话框的初始化函数(即 OnInitDialog 函数)添加相关的实现代码,如下:
//声明指向节点的句柄 HTREEITEM hItem,hSubItem; //插入节点 //在根结点上添加 Parent1 hItem = m_tc.InsertItem(L"Parent1",TVI_ROOT); //在 Parent1 上添加一个子结点 Child1_1 hSubItem = m_tc.InsertItem(L"Child1_1",hItem); // 在 Parent1 上添加一个子结点Child1_2,排在 Child1_1 后面 hSubItem = m_tc.InsertItem(L"Child1_2",hItem,hSubItem); //在根结点上添加 Parent2 hItem = m_tc.InsertItem(L"Parent2",TVI_ROOT,hItem); //在 Parent2 上添加一个子结点 Child2_1 m_tc.InsertItem(L"Child2_1",hItem);
运行结果:
若将控件 Tree Control 的 Has Buttons , Has Lines 和 Lines At Root 设置为 true,则控件效果为如下所示:
先在主对话框中拖入一个 Tree Control 控件,然后为这个控件添加控制变量其变量类型为 CTreeCtrl 类和名为 m_tc.和两个图标资源(IDI_ICON1 和 IDI_ICON2)资源视图如下:
然后将控件 Tree Control 的 Has Buttons , Has Lines 和 Lines At Root 设置为 true. 并为这个控件添加子节点,节点结构为如下所示:
+--- Parent1
+--- Child1_1
+--- Child1_2
+--- Parent2
+--- Child2_1
在对话框的初始化函数(即 OnInitDialog 函数)添加相关的实现代码,如下:
//载入图标 HICON icon[2]; icon[0]=AfxGetApp()->LoadIcon (IDI_ICON1); icon[1]=AfxGetApp()->LoadIcon (IDI_ICON2); //创建图像列表控件 CImageList *imagelist=new CImageList; imagelist->Create(16,16,0,7,7); imagelist->SetBkColor (RGB(255,255,255)); for(int n=0;n<2;n++) { //把图标载入图像列表控件 imagelist->Add(icon[n]); } //为 m_tc 设置一个图像列表,使 Tree Control 控件的节点显示不同的图标 m_tc.SetImageList(imagelist,TVSIL_NORMAL); //声明指向节点的句柄 HTREEITEM hItem,hSubItem; //插入节点 //在根结点上添加 Parent1 hItem = m_tc.InsertItem(L"Parent1",TVI_ROOT); //在 Parent1 上添加一个子结点 Child1_1 hSubItem = m_tc.InsertItem(L"Child1_1",hItem); // 在 Parent1 上添加一个子结点Child1_2,排在 Child1_1 后面 hSubItem = m_tc.InsertItem(L"Child1_2",hItem,hSubItem); //在根结点上添加 Parent2 hItem = m_tc.InsertItem(L"Parent2",TVI_ROOT,hItem); //在 Parent2 上添加一个子结点 Child2_1 m_tc.InsertItem(L"Child2_1",hItem);
运行结果:
相关文章:
两个重要结构:
LVCOLUMN(MSDN 链接)
作用: 这个结构体记录了列的相关信息
结构体定义:
typedef struct _LVCOLUMN { UINT mask; // Variable specifying which members contain valid information int fmt; // Alignment of the column header and the subitem text in the column int cx; // Width of the column, in pixels LPTSTR pszText; // contains the column header text. int cchTextMax; // Size in TCHARs of the buffer pointed to by the pszText member int iSubItem; // Index of subitem associated with the column. #if (_WIN32_IE >= 0x0300) int iImage; // Zero-based index of an image within the image list. The specified image will appear within the column. int iOrder; // Zero-based column offset. Column offset is in left-to-right order. For example, zero indicates the leftmost column. #endif #if (_WIN32_WINNT >= 0x0600) int cxMin; // Minimum width of the column in pixels. int cxDefault; // Application-defined value typically used to store the default width of the column. This member is ignored by the list-view control. int cxIdeal; // Read-only. The ideal width of the column in pixels, as the column may currently be autosized to a lesser width. #endif } LVCOLUMN, *LPLVCOLUMN;
LVITEM(MSDN 链接)
作用: 这个结构体记录了行的相关信息
结构体定义:
typedef struct { UINT mask; // Set of flags that specify which members of this structure contain data to be set or which members are being requested int iItem; // Zero-based index of the item to which this structure refers int iSubItem; // One-based index of the subitem to which this structure refers, or zero if this structure refers to an item rather than a subitem UINT state; // Indicates the item's state, state image, and overlay image UINT stateMask; // Value specifying which bits of the state member will be retrieved or modified LPTSTR pszText; // containing the item text int cchTextMax; // Number of TCHARs in the buffer pointed to by pszText, including the terminating NULL. int iImage; // Index of the item's icon in the control's image list. LPARAM lParam; // Value specific to the item. If you use the LVM_SORTITEMS message, the list-view control passes this value to the application-defined comparison function. #if (_WIN32_IE >= 0x0300) int iIndent; // Number of image widths to indent the item. A single indentation equals the width of an item image #endif #if (_WIN32_WINNT >= 0x0501) int iGroupId; // Identifier of the group that the item belongs to, or one of the following values. UINT cColumns; // Number of data columns (subitems) to display for this item in tile view. UINT puColumns; // A pointer to an array of column indices, specifying which columns are displayed for this item, and the order of those columns. #endif #if (_WIN32_WINNT >= 0x0600) int piColFmt; // A pointer to an array of the following flags (alone or in combination), specifying the format of each subitem in extended tile view. int iGroup; // Group index of the item. #endif } LVITEM, *LPLVITEM;
CListCtrl 常用函数(单击函数链接至MSDN):
代码样例:
[插入行][插入带图标的行][在 View 值为 Report 下设置多列样式][设置控件样式][使控件在失去焦点时候依旧高亮显示]
先在主对话框中拖入一个 List Control 控件(View 属性为 Icon),然后为这个控件添加控制变量其变量类型为 CListCtrl 类和名为 m_lc.资源视图如下:
然后,在对话框初始化函数(即函数 OnInitDialog 中)向控件中插入"T_1","T_2","T_3","T_4","T_5","T_6","T_7","T_8","T_9","T_0" 10 行数据,具体代码如下:
//插入列,列属性只对 View 属性值为 Report 时才起作用 //并且在 Report 下不能不插入列,不然显示不出任何东西 m_lc.InsertColumn(0, L"ColumnName",LVCFMT_LEFT,100); //插入行 m_lc.InsertItem(0, L"T_1"); m_lc.InsertItem(1, L"T_2"); m_lc.InsertItem(2, L"T_3"); m_lc.InsertItem(3, L"T_4"); m_lc.InsertItem(4, L"T_5"); m_lc.InsertItem(5, L"T_6"); m_lc.InsertItem(6, L"T_7"); m_lc.InsertItem(7, L"T_8"); m_lc.InsertItem(8, L"T_9"); m_lc.InsertItem(9, L"T_0");
运行结果:
若将控件的 View 属性设置 Small Icon,List 或 Report 时的效果如下:
先在主对话框中拖入一个 List Control 控件(View 属性为 Icon,若为其他图标则显示不出来),然后为这个控件添加控制变量其变量类型为 CListCtrl 类和名为 m_lc.和两个图标资源(IDI_ICON1 和 IDI_ICON2)资源视图如下:
然后为在对话框初始化函数(即函数 OnInitDialog 中)向控件中插入"T_1","T_2" 2行带有图标的数据,具体代码如下:
//载入图标 HICON icon[2]; icon[0]=AfxGetApp()->LoadIcon (IDI_ICON1); icon[1]=AfxGetApp()->LoadIcon (IDI_ICON2); //创建图像列表控件 CImageList *imagelist=new CImageList; imagelist->Create(16,16,0,7,7); imagelist->SetBkColor (RGB(255,255,255)); for(int n=0;n<2;n++) { //把图标载入图像列表控件 imagelist->Add(icon[n]); } //为 m_lc 置一个图像列表,使 List Control 的行显示不同的图标 m_lc.SetImageList(imagelist,TVSIL_NORMAL); // 插入行 m_lc.InsertItem(0, L"T_1",0); m_lc.InsertItem(1, L"T_2",1);
运行结果:
在插入数据前大致步骤如上,只需把对话框的 View 属性设置为 Report 然后,先添对列进行添加操作(即插入列)后等列都设置好了后,再进行行插入,实现代码依旧是在初始对话框的函数中(即函数 OnInitDialog 中),具体代码如下:
//插入列,列属性只对 View 属性值为 Report 时才起作用 //并且在 Report 下不能不插入列,不然显示不出任何东西 m_lc.InsertColumn(0, L"ColumnName",LVCFMT_LEFT,100); m_lc.InsertColumn(1,L"ColumnValue",LVCFMT_LEFT,100); /* 插入行 **************************************************/ int i = m_lc.InsertItem(0, L"T_1"); //在非 Report 下这个文本数据是不显示的 //设置第二列数据 m_lc.SetItemText(i,1,L"One"); i = m_lc.InsertItem(1, L"T_2"); m_lc.SetItemText(i,1,L"Two"); i = m_lc.InsertItem(2, L"T_3"); m_lc.SetItemText(i,1,L"Three"); i = m_lc.InsertItem(3, L"T_4"); m_lc.SetItemText(i,1,L"Four"); i = m_lc.InsertItem(4, L"T_5"); m_lc.SetItemText(i,1,L"Five"); i = m_lc.InsertItem(5, L"T_6"); m_lc.SetItemText(i,1,L"Six"); i = m_lc.InsertItem(6, L"T_7"); m_lc.SetItemText(i,1,L"Seven"); i = m_lc.InsertItem(7, L"T_8"); m_lc.SetItemText(i,1,L"Eight"); i = m_lc.InsertItem(8, L"T_9"); m_lc.SetItemText(i,1,L"Nine"); i = m_lc.InsertItem(9, L"T_0"); m_lc.SetItemText(i,1,L"Zero");
运行结果:
利用 SetExtendedStyle 来设置控件的扩展样式.List Control 具体的扩展样式(MSDN 链接)
我们来将控件设置一个具有整行高亮的属性且具有网格线并把实现添加至初始对话框的函数中(即函数 OnInitDialog 中).具体实现代码如下:
//获得控件扩展属性 DWORD dwStyle = m_lc.GetExtendedStyle(); //选中某行使整行高亮(只适用与report风格的listctrl) dwStyle |= LVS_EX_FULLROWSELECT; //网格线(只适用与report风格的listctrl) dwStyle |= LVS_EX_GRIDLINES; //设置控件扩展属性 m_lc.SetExtendedStyle(dwStyle); //插入列,列属性只对 View 属性值为 Report 时才起作用 //并且在 Report 下不能不插入列,不然显示不出任何东西 m_lc.InsertColumn(0, L"ColumnName",LVCFMT_LEFT,100); m_lc.InsertColumn(1,L"ColumnValue",LVCFMT_LEFT,100); /* 插入行 **************************************************/ int i = m_lc.InsertItem(0, L"T_1"); //在非 Report 下这个文本数据是不显示的 //设置第二列数据 m_lc.SetItemText(i,1,L"One"); i = m_lc.InsertItem(1, L"T_2"); m_lc.SetItemText(i,1,L"Two");
运行结果(为最右图,前两个图只是为了比较在添加了对应属性的和为添加的区别):
方法一:
为 List Control 控件添加 NM_CUSTOMDRAW 事件,并为事件添加如下代码:(其中有两个关键的结构体< NMHDR 和 NMLVCUSTOMDRAW> 点击其参看详细说名)
void CtestDlg::OnNMCustomdrawProtocol(NMHDR *pNMHDR, LRESULT *pResult) { //LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 //*pResult = 0; //将 pLVCD 指向参数 pNMHDR 转换为 NMLVCUSTOMDRAW 类型的对象 NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR ); *pResult = CDRF_DODEFAULT; if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage ) *pResult = CDRF_NOTIFYITEMDRAW; else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage ) *pResult = CDRF_NOTIFYSUBITEMDRAW; //当行被重绘时候 else if ( (CDDS_ITEMPREPAINT | CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage ) { COLORREF clrNewTextColor, clrNewBkColor; //获得要重绘的行的索引 int nItem = static_cast<int>( pLVCD->nmcd.dwItemSpec ); BOOL bSelect = FALSE; //获得选择行的位置 POSITION pos =m_lc.GetFirstSelectedItemPosition()-1; //若为重绘的该项为选中项 bSelect 为 true if((int)pos==nItem) bSelect = TRUE; //判断要重绘的项是否为选中项 if(bSelect) { //为选中的行文本的背景色和前景初始化 clrNewTextColor = RGB(255,255,255); clrNewBkColor = RGB(53,153,251); } else { //为未选中的行文本的背景色和前景初始化 clrNewTextColor = RGB(0,0,0); clrNewBkColor = RGB(255,255,255); } //设置控件文本和文本背景色 pLVCD->clrText = clrNewTextColor; pLVCD->clrTextBk = clrNewBkColor; *pResult = CDRF_DODEFAULT; } }
这里也可以实现行颜色和选中行颜色的自定义.即对上面中的一下代码颜色值进行调整即可:
if(bSelect) { //通过调整下面两个变量的 RGB 值实现自定义选中的行文本的背景色和前景色 clrNewTextColor = RGB(255,255,255); clrNewBkColor = RGB(53,153,251); } else { //通过调整下面两个变量的 RGB 值实现自定义未选中的行文本的背景色和前景色 clrNewTextColor = RGB(0,0,0); clrNewBkColor = RGB(255,255,255); }
运行结果与方法二一样
方法二:
为 List Control 控件添加 NM_KILLFOCUS 和 NM_SETFOCUS 事件,然后在对话框框中添加一个整形变量 m_SecCount.
接着在 NM_KILLFOCUS 和 NM_SETFOCUS 事件响应函数中添加如下代码:( SetItemState 相关说明参看上面)
/* NM_KILLFOCUS 事件响应函数中添加代码 *******************************************/ //获得选中行的索引 m_SecCount = (int)m_lc.GetFirstSelectedItemPosition()-1; //设置选中行一直高亮显示 m_lc.SetItemState(m_SecCount,LVIS_DROPHILITED,LVIF_STATE); /* NM_SETFOCUS 事件响应函数中添加代码 *******************************************/ //取消在失去高亮时候选中行的高亮显示 m_lc.SetItemState(m_SecCount,FALSE,LVIF_STATE);
运行结果:
相关文章: