当点击节点左边的加号(+)或减号(-)时,带有子节点的项目就相应展开或折叠起来。这时树控件向其父窗口发送TVN_ITEMEXPANDING通知消息。这个消息的lParam参数是NMTREEVIEW结构指针。它含有两个TVITEM成员itemOld和itemNew,itemOld成员代表刚刚失去焦点的节点而itemNew成员表示正在获得焦点的节点。其中itemNew成员的hItem字段即为正在获得焦点的节点句柄。在处理TVN_ITEMEXPANDING通知消息时就是通过该句柄来对此节点的状态属性进行设置或获取操作的。而NMTREEVIEW结构的action成员用于进一步确定节点是展开还是折叠:当action == TVE_EXPAND节点展开;当action == TVE_COLLAPSE节点折叠。通常节点展开时希望该节点的图标换成展开状态的图标,比如一个表示已打开文件样式的图标等等而结点折叠则用另外的图标表示之,下面的代码就是处理这样的情况:
case TVN_ITEMEXPANDING:
{
lpnmtv = (LPNMTREEVIEW)lParam;
HTREEITEM hSelected = lpnmtv->itemNew.hItem;
if(lpnmtv->action == TVE_EXPAND){
tvitem.mask = TVIF_HANDLE | TVIF_IMAGE |
TVIF_SELECTEDIMAGE | TVIF_STATE;
tvitem.hItem = hSelected;
tvitem.state = 0;
tvitem.stateMask = TVIS_SELECTED;
tvitem.iImage = 3;
tvitem.iSelectedImage = 3;
SendMessage(GetDlgItem(hWnd, ID_TREEVIEW), TVM_SETITEM,
(WPARAM)0, (LPARAM)(const LPTVITEM)&tvitem);
}
else if(lpnmtv->action == TVE_COLLAPSE){
tvitem.mask = TVIF_HANDLE | TVIF_IMAGE |
TVIF_SELECTEDIMAGE | TVIF_STATE;
tvitem.hItem = hSelected;
tvitem.state = 0;
tvitem.stateMask = TVIS_SELECTED;
tvitem.iSelectedImage = 2;
tvitem.iImage = 2;
SendMessage(GetDlgItem(hWnd, ID_TREEVIEW), TVM_SETITEM,
(WPARAM)0, (LPARAM)(const LPTVITEM)&tvitem);
}
break;
}
四、 节点状态图标消息
可以使用TVS_CHECKBOXES样式的树控件使每个节点旁都有一个checkbox,也可以自己手动添加checkbox样式的图标来表示下面的代码负责手动添加checkbox图标:
先在WM_CREATE消息处理中插入节点:
hbitmapcheck = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP2));
himlc = ImageList_Create(13, 13, ILC_COLOR16 , 8, 0);
ImageList_Add(himlc, hbitmapcheck, 0);
DeleteObject(hbitmapcheck);
tvinsert.hParent = NULL;
tvinsert.hInsertAfter = TVI_LAST;
tvinsert.item.mask = TVIF_TEXT | TVIF_HANDLE |TVIF_STATE;
tvinsert.item.hItem = NULL;
tvinsert.item.state = INDEXTOSTATEIMAGEMASK(1);
tvinsert.item.stateMask = TVIS_STATEIMAGEMASK;
tvinsert.item.cchTextMax = 6;
SendMessage(hwndTreeCheck, TVM_SETIMAGELIST,(WPARAM)TVSIL_STATE,
(LPARAM)(HIMAGELIST)himlc);
tvinsert.item.pszText = _T("Item01");
SendMessage(hwndTreeCheck, TVM_INSERTITEM , 0 ,(LPARAM)&tvinsert);
tvinsert.item.pszText = _T("Item02");
SendMessage(hwndTreeCheck, TVM_INSERTITEM , 0 ,(LPARAM)&tvinsert);
tvinsert.item.pszText = _T("Item03");
SendMessage(hwndTreeCheck, TVM_INSERTITEM , 0 ,(LPARAM)&tvinsert);
tvinsert.item.pszText = _T("Item04");
SendMessage(hwndTreeCheck, TVM_INSERTITEM , 0 ,(LPARAM)&tvinsert);
tvinsert.item.pszText = _T("Item05");
SendMessage(hwndTreeCheck, TVM_INSERTITEM , 0 ,(LPARAM)&tvinsert);
然后在NM_CLICK消息中处理当鼠标单击节点的checkbox图标时变化checkbox的状态用于确认节点被选中:
case NM_CLICK:
{
UINT uFlags = 0;
POINT pt;
GetCursorPos(&pt);
ScreenToClient(GetDlgItem(hWnd, ID_TREECHECK),&pt);
TVHITTESTINFO hti;
hti.pt = pt;
TVITEM item;
//Selected必须是全局变量,然后到处理TVN_ENDLABELEDIT消息这个变量才//有效!!
Selected = (HTREEITEM)SendMessage(GetDlgItem(hWnd, ID_TREECHECK),
TVM_HITTEST, 0, (LPARAM)&hti);
uFlags = hti.flags;
if( uFlags & TVHT_ONITEMSTATEICON){
item.mask = TVIF_HANDLE | TVIF_STATE;
item.hItem = Selected;
item.stateMask = TVIS_STATEIMAGEMASK;
item.state = 0;
SendMessage(GetDlgItem(hWnd, ID_TREECHECK), TVM_GETITEM,
(WPARAM)0, (LPARAM)&item);
item.state = INDEXTOSTATEIMAGEMASK((item.state>>12) == 1 ? 2 : 1);
item.stateMask = TVIS_STATEIMAGEMASK;
SendMessage(GetDlgItem(hWnd, ID_TREECHECK), TVM_SETITEM,
(WPARAM)0, (LPARAM)&item);
break;
}
0 件のコメント:
コメントを投稿