CTreeCtrl 树控件的使用

以下链接可以下载全文:

https://download.csdn.net/download/h3974/33161552

一 用代码创建树控件

1.在要创建树控件的父对话框的头文件中,声明树控件对象(或称变量):
    CTreeCtrl   tree;

2.添加父对话框的OnCreate函数,在函数中创建树控件:
int CMFCApplication1Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CDialogEx::OnCreate(lpCreateStruct) == -1)
        return -1;
    tree.Create(WS_CHILD | WS_VISIBLE | WS_BORDER| TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS, 
        CRect(10, 10, 300, 400), this, IDC_TREE1);
    return 0;
}

3.在父对话框DoDataExchange函数中,子类化控件:
void CMFCApplication1Dlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_TREE1, tree);
}

4.在资源头文件中,定义树控件标识:
    #define    IDC_TREE1          1000
 

二 使用图像的树控件的初始化

1.在对话框头文件中声明树控件使用的图像列表:
    CImageList imagelist;
2.在对话框初始化函数中,初始化树控件:
    imagelist.Create(32, 32, ILC_COLOR32, 6, 6);//创建图像列表
    //初始化图像列表
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON9));//不使用索引为0的图像
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON2));
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON3));
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON4));
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON5));
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON6));
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON7));
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON8));

    tree.SetImageList(&imagelist, TVSIL_NORMAL);//为树控件设置图像列表。如果树控件不使用图像,此步可以省略,并可以不创建图像列表
    //为树控件添加项,并设置项使用的图像
    HTREEITEM h1 = tree.InsertItem(_T("A"), 1,1,0, TVI_LAST);
    HTREEITEM h11=tree.InsertItem(_T("A1"), 4, 4, h1, TVI_LAST);    HTREEITEM h12=tree.InsertItem(_T("A2"), 5, 5, h1, TVI_LAST);
    HTREEITEM h2 = tree.InsertItem(_T("B"),2,2, 0, TVI_LAST);
    HTREEITEM h21=tree.InsertItem(_T("B1"), 6, 6, h2, TVI_LAST);    HTREEITEM h22=tree.InsertItem(_T("B2"), 7, 7, h2, TVI_LAST);
    HTREEITEM h3 = tree.InsertItem(_T("C"), 3,3,0, TVI_LAST);
    HTREEITEM h31=tree.InsertItem(_T("C1"), 8, 8, h3, TVI_LAST);    
    //为树控件项关联数值
    tree.SetItemData(h1, 100); tree.SetItemData(h11, 130); tree.SetItemData(h12, 150);
    tree.SetItemData(h2, 200); tree.SetItemData(h21, 230); tree.SetItemData(h22, 250);
    tree.SetItemData(h3, 300); tree.SetItemData(h31, 330);
    //设置树控件的背景色,文本颜色
    tree.SetBkColor(RGB(20, 118, 252)); tree.SetTextColor(RGB(255, 255, 255));
    //设置树控件的扩展样式
    tree.SetExtendedStyle(TVS_EX_AUTOHSCROLL, TVS_EX_AUTOHSCROLL);//不需要扩展样式,省略此步
    tree.SetLineColor(RGB(255, 0, 0));//设置连接线的颜色,没有连接线的控件省略此步
    tree.SetInsertMarkColor(RGB(255, 0, 0));//设置插入标记的颜色,如果不使用插入标记,或不更改插入标记的默认颜色,省略此步

三 不使用图像的树控件的初始化

在对话框初始化函数中,初始化树控件:

    //为树控件添加项,并设置项使用的图像
    HTREEITEM h1 = tree.InsertItem(_T("A"), 0, TVI_LAST);
    HTREEITEM h11=tree.InsertItem(_T("A1"), h1, TVI_LAST);    HTREEITEM h12=tree.InsertItem(_T("A2"), h1, TVI_LAST);
    HTREEITEM h2 = tree.InsertItem(_T("B"), 0, TVI_LAST);
    HTREEITEM h21=tree.InsertItem(_T("B1"), h2, TVI_LAST);    HTREEITEM h22=tree.InsertItem(_T("B2"), h2, TVI_LAST);
    HTREEITEM h3 = tree.InsertItem(_T("C"), 0, TVI_LAST);
    HTREEITEM h31=tree.InsertItem(_T("C1"), h3, TVI_LAST);    
    //为树控件项关联数值
    tree.SetItemData(h1, 100); tree.SetItemData(h11, 130); tree.SetItemData(h12, 150);
    tree.SetItemData(h2, 200); tree.SetItemData(h21, 230); tree.SetItemData(h22, 250);
    tree.SetItemData(h3, 300); tree.SetItemData(h31, 330);
    
    tree.SetBkColor(RGB(20, 118, 252)); tree.SetTextColor(RGB(255, 255, 255));//设置树控件的背景色,文本颜色
    
    tree.SetExtendedStyle(TVS_EX_AUTOHSCROLL, TVS_EX_AUTOHSCROLL);//设置树控件的扩展样式。不需要扩展样式,省略此步
    tree.SetLineColor(RGB(255, 0, 0));//设置连接线的颜色,没有连接线的控件省略此步
    tree.SetInsertMarkColor(RGB(255, 0, 0));//设置插入标记的颜色,如果不使用插入标记,或不更改插入标记的默认颜色,省略此步


四 添加根项

在末尾添加根项:
    tree.InsertItem(_T("项文本"), 0, TVI_LAST);
在开头添加根项:
    tree.InsertItem(_T("项文本"), 0, TVI_FIRST);
在某根项的后面添加根项:
    tree.InsertItem(_T("项文本"), 0, hItem);//在句柄为hItem的根项后面添加根项

 

五 添加子项

在开头添加子项:
    tree.InsertItem(_T("项文本"), h_par, TVI_FIRST);//h_par是父项句柄
在末尾添加子项:
    tree.InsertItem(_T("项文本"), h_par, TVI_LAST);//h_par是父项句柄

 

六 在某项的前面添加新项

    HTREEITEM hSel = tree.GetSelectedItem();//获取选中项的句柄
    if (hSel != NULL)
    {
        HTREEITEM hPar = tree.GetParentItem(hSel);//获取选中项的父项
        HTREEITEM hPre = tree.GetPrevSiblingItem(hSel);//获取选中项的上一个兄弟项
        if (hPre == NULL)//如果没有上一个兄弟项
        {
            tree.InsertItem(_T("新项文本"), hPar, TVI_FIRST);//在子项列表的开头添加子项
        }
        else//如果有上一个兄弟项
        {
            tree.InsertItem(_T("新项文本"), hPar, hPre);//在上一个兄弟项的后面添加新项
        }
    }

 

七 在某项的后面添加新项

    HTREEITEM hSel = tree.GetSelectedItem();//获取选中项的句柄
    if (hSel != NULL)
    {
        HTREEITEM hPar = tree.GetParentItem(hSel);//获取选中项的父项
        tree.InsertItem(_T("新项文本"), hPar, hSel);//在选中项的后面添加新项
    }

 

八 保存树控件所有项的文本及数值到文件

    HTREEITEM h_item = tree.GetRootItem();//获取第一个根项
    CString item_str; UINT cj = 0; int data;//记录项文本,项层级,项数值
    if (h_item == NULL)return;   //如果树控件不包含任何项返回
    else
    {
        item_str = tree.GetItemText(h_item); data = tree.GetItemData(h_item);//获取项文本和数值
    }
    CFile F(_T("树控件数据.dat"), CFile::modeCreate | CFile::modeWrite);
    CArchive ar(&F, CArchive::store);
    UINT count = tree.GetCount();
    ar << count;
    ar << item_str << cj << data;//写入项文本,项层级,项数值
jump1:
    if (tree.ItemHasChildren(h_item))    //如果有子项
    {
        h_item = tree.GetChildItem(h_item);//获取子项
        cj += 1;//层级加1
        item_str = tree.GetItemText(h_item); data = tree.GetItemData(h_item);//获取项文本和数值
        ar << item_str << cj << data;//写入项文本,项层级,项数值
        goto jump1;
    }
jump2:
    if (tree.GetNextSiblingItem(h_item) == NULL)    //如果没有下一个兄弟项
    {
        if (cj == 0)goto end;//如果层级到达0,且没有下一个兄弟项,跳出循环
        h_item = tree.GetParentItem(h_item);//获取父项
        cj -= 1;//层级减1
        goto jump2;
    }
    else    //如果有下一个兄弟项
    {
        h_item = tree.GetNextSiblingItem(h_item);//获取下一个兄弟项
        item_str = tree.GetItemText(h_item); data = tree.GetItemData(h_item);//获取项文本和数值
        ar << item_str << cj << data;//写入项文本,项层级,项数值
        goto jump1;
    }
end:
    ;

 

九 由文件加载项到树控件

    CFile F(_T("树控件数据.dat"), CFile::modeRead);
    CArchive ar(&F, CArchive::load);
    HTREEITEM h[15];//声明的数组的大小必须大于或等于树控件的层深,层深已由"树控件数据.dat"文件决定
    CString item_str; UINT cj,count; int data;//记录项文本,项层级,项数值的变量类型,必须与保存到文件时使用的类型一致
    ar >> count;
    for (UINT i = 0; i < count;i++)
    {
        ar >> item_str >> cj >> data;
        if (cj == 0)
        {
            h[cj] = tree.InsertItem(item_str, 0, 0); tree.SetItemData(h[cj], data);
        }
        else
        {
            h[cj] = tree.InsertItem(item_str, h[cj - 1], TVI_LAST); tree.SetItemData(h[cj],data);
        }
    }

 

十 就地编辑树控件项文本

树控件必须具有TVS_EDITLABELS样式,在对话框编辑器创建的树控件指定控件Edit Lablels属性为TRUE;为树控件添加TVN_ENDLABELEDIT事件响应函数,在函数中添加如下代码:
void CMFCApplication1Dlg::OnTvnEndlabeleditTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
    if (pTVDispInfo->hdr.idFrom == IDC_TREE1)//如果通知由IDC_TREE1树控件发出
    {
        *pResult = 1;
    }
    else
        *pResult = 0;
}
    pTVDispInfo->hdr.code;//UINT 通知代码
    pTVDispInfo->hdr.hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pTVDispInfo->hdr.idFrom;//UINT_PTR 发送通知的树控件的标识
    pTVDispInfo->item;//TVITEM结构
    pTVDispInfo->item.hItem;//HTREEITEM 就地编辑文本的项的句柄
    pTVDispInfo->item.pszText;//LPWSTR 正在编辑的文本

 

十一 在树控件中查找项

此代码在树控件查找项文本具有指定前缀的项,如果查找到,选中该项。
        CString str=_T("要查找的文本");
    HTREEITEM h_item = tree.GetRootItem();
    CString item_str; UINT cj = 0;
    if (h_item == NULL)return;//如果树控件不包含项返回
    else
    {
        item_str = tree.GetItemText(h_item);//获取项文本
    }
    if (str == item_str.Left(str.GetLength()))//如果找到匹配项
    {
        tree.SelectItem(h_item); return;//选中该项,返回
    }
jump1:
    if (tree.ItemHasChildren(h_item))//如果有子项
    {
        h_item = tree.GetChildItem(h_item);//获取子项
        cj += 1;
        item_str = tree.GetItemText(h_item);//获取项文本
        if (str == item_str.Left(str.GetLength()))//如果找到匹配项
        {
            tree.SelectItem(h_item); return;//选中该项,返回
        }
        goto jump1;
    }
jump2:
    if (tree.GetNextItem(h_item, TVGN_NEXT) == NULL)//如果没有下一个兄弟项
    {
        if (cj == 0)return;//如果层级到达0,且没有下一个兄弟项,返回
        h_item = tree.GetParentItem(h_item);//获取父项
        cj -= 1;
        goto jump2;
    }
    else//如果有下一个兄弟项
    {
        h_item = tree.GetNextItem(h_item, TVGN_NEXT);//获取下一个兄弟项
        item_str = tree.GetItemText(h_item);//获取项文本
        if (str == item_str.Left(str.GetLength()))//如果找到匹配项
        {
            tree.SelectItem(h_item); return;//选中该项
        }
        goto jump1;
    }

 

十二 拖放项

方法一,使用MFC函数:
1. 以CTreeCtrl为基类创建派生类CMyTreeCtrl,修改树控件变量声明:
    CMyTreeCtrl tree;
2.在CMyTreeCtrl类的头文件中,声明被拖动项句柄,声明拖动图像列表,声明布尔变量:
    HTREEITEM hSour;//被拖动项句柄
    CImageList* pList;//拖动图像列表
    BOOL g_fDragging = FALSE;

3. 在CMyTreeCtrl类中,添加TVN_BEGINDRAG通知响应函数,在函数中添加如下代码:
void CMyTreeCtrl::OnTvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR); 
    RECT rcItem;
    hSour = pNMTreeView->itemNew.hItem;
    pList=CreateDragImage(hSour);
    GetItemRect(hSour, &rcItem, TRUE);
    pList->BeginDrag(0, CPoint(0, 0));
    CWnd* pwnd = FromHandle(pNMTreeView->hdr.hwndFrom);
    pList->DragEnter(pwnd, CPoint(pNMTreeView->ptDrag.x, pNMTreeView->ptDrag.x));
    ShowCursor(FALSE);
    SetCapture();
    g_fDragging = TRUE;
    *pResult = 0;
}

4.在CMyTreeCtrl类中,添加WM_MOUSEMOVE消息响应函数,在函数中添加如下代码:
void CMyTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
    HTREEITEM htiTarget;
    TVHITTESTINFO tvht;
    if (g_fDragging)
    {
        pList->DragMove(point);
        pList->DragShowNolock(FALSE);
        tvht.pt.x = point.x;
        tvht.pt.y = point.y;
        if ((htiTarget = HitTest(&tvht)) != NULL)
        {
            SelectDropTarget(htiTarget);
        }
        pList->DragShowNolock(TRUE);
    }
    CTreeCtrl::OnMouseMove(nFlags, point);
}

5.在CMyTreeCtrl类中,添加WM_LBUTTONUP消息响应函数,在函数中添加如下代码:
void CMyTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
    if (g_fDragging)
    {
        HTREEITEM htiDest = GetDropHilightItem();
        if (htiDest != NULL)//在这里,处理被拖动节点的实际移动
        {
            
        }
        pList->EndDrag();
        SelectDropTarget(htiDest);
        ReleaseCapture();
        ShowCursor(TRUE);
        g_fDragging = FALSE;
        delete pList;
    }
    CTreeCtrl::OnLButtonUp(nFlags, point);
}

方法二,使用控件宏:
1. 以CTreeCtrl为基类创建派生类CMyTreeCtrl,修改树控件变量声明:
    CMyTreeCtrl tree;

2.在CMyTreeCtrl类的头文件中,声明被拖动项句柄,声明拖动图像列表,声明布尔变量:
    HTREEITEM hSour;//被拖动项句柄
    CImageList* pList;//拖动图像列表
    BOOL g_fDragging = FALSE;

3. 在CMyTreeCtrl类中,添加TVN_BEGINDRAG通知响应函数,在函数中添加如下代码:
void CMyTreeCtrl::OnTvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    HIMAGELIST himl;
    RECT rcItem;
    hSour = pNMTreeView->itemNew.hItem;//被拖动项句柄
    himl = TreeView_CreateDragImage(GetSafeHwnd(), pNMTreeView->itemNew.hItem);
    TreeView_GetItemRect(GetSafeHwnd(), pNMTreeView->itemNew.hItem, &rcItem, TRUE);
    ImageList_BeginDrag(himl, 0, 0, 0);
    ImageList_DragEnter(GetSafeHwnd(), pNMTreeView->ptDrag.x, pNMTreeView->ptDrag.x);
    ShowCursor(FALSE);
    SetCapture();
    g_fDragging = TRUE;
    *pResult = 0;
}

4. 在CMyTreeCtrl类中,添加WM_MOUSEMOVE消息响应函数,在函数中添加如下代码:
void CMyTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
    HTREEITEM htiTarget;
    TVHITTESTINFO tvht;
    if (g_fDragging)
    {
        ImageList_DragMove(point.x, point.y);
        ImageList_DragShowNolock(FALSE);
        tvht.pt.x = point.x;
        tvht.pt.y = point.y;
        if ((htiTarget = TreeView_HitTest(GetSafeHwnd(), &tvht)) != NULL)
        {
            TreeView_SelectDropTarget(GetSafeHwnd(), htiTarget);
        }
        ImageList_DragShowNolock(TRUE);
    }
    CTreeCtrl::OnMouseMove(nFlags, point);
}

5. 在CMyTreeCtrl类中,添加WM_LBUTTONUP消息响应函数,在函数中添加如下代码:
void CMyTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
    if (g_fDragging)
    {
        HTREEITEM htiDest = TreeView_GetDropHilight(GetSafeHwnd());//目标项句柄
        if (htiDest != NULL)//在这里,处理被拖动节点的实际移动
        {
            
        }
        ImageList_EndDrag();
        TreeView_SelectDropTarget(GetSafeHwnd(), NULL);
        ReleaseCapture();
        ShowCursor(TRUE);
        g_fDragging = FALSE;
        delete pList;
    }
    CTreeCtrl::OnLButtonUp(nFlags, point);
}

 

十三 为项添加覆盖图像

覆盖图像是覆盖在项图像上面的图像。
    CImageList imagelist;//在对话框头文件中声明图像列表对象
    //下面代码创建并初始化图像列表,将图像列表设置给树控件,初始化树控件。可将下面代码放在对话框初始化函数中
    imagelist.Create(32, 32, ILC_COLOR32 | ILC_MASK, 8, 8);//创建图像列表,要求图像列表具有ILC_MASK类型
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON8));//不使用索引为0的图片
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON1));//索引为1的图片
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON2));//索引为2的图片
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON3));//索引为3的图片
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON4));//索引为4的图片
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON5));//索引为5的图片
    imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON6));//索引为6的图片
    int index = imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON7));//索引为7的图片,将用作覆盖图片
    imagelist.SetOverlayImage(index, 1);//创建覆盖图像,1为覆盖图像基于1的索引
    tree.SetImageList(&imagelist, TVSIL_NORMAL);//将图像列表设置给树控件

    HTREEITEM h1 = tree.InsertItem(_T("A"), 1, 1, 0, 0);//初始化树控件
    HTREEITEM h11 = tree.InsertItem(_T("A1"), 2, 2, h1, TVI_LAST);    HTREEITEM h12 = tree.InsertItem(_T("A2"), 3, 3, h1, TVI_LAST);
    HTREEITEM h2 = tree.InsertItem(_T("B"), 4, 4, 0, 0);
    HTREEITEM h21 = tree.InsertItem(_T("B1"), 5, 5, h2, TVI_LAST);    HTREEITEM h22 = tree.InsertItem(_T("B2"), 6, 6, h2, TVI_LAST);
    
为指定项添加覆盖图像:
    TVITEM tvItem;
    tvItem.mask = TVIF_HANDLE | TVIF_STATE;
    tvItem.hItem = h_item;//为要添加覆盖图像的项的句柄
    tvItem.stateMask = TVIS_OVERLAYMASK;//此掩码指定项使用覆盖图像
    tvItem.state = INDEXTOOVERLAYMASK(1);//1为覆盖图像基于1的索引
    tree.SetItem(&tvItem);


十四 为项添加状态图像

状态图像是显示在项图像左侧的图像。
在对话框头文件中,声明状态图像列表:
    CImageList statelist;
创建并初始化状态图像列表:
    statelist.Create(32, 32, ILC_COLOR32, 10, 10);
    statelist.Add(AfxGetApp()->LoadIcon(IDI_ICON1));//将第一个图像设置为一个不使用的图像,其索引为0
    statelist.Add(AfxGetApp()->LoadIcon(IDI_ICON2));//状态图像
设置树控件使用的状态图像列表:
    tree.SetImageList(&statelist, TVSIL_STATE);//参数2必须为 TVSIL_STATE
设置项的状态图像:
    TVITEM tvItem;
    tvItem.mask = TVIF_HANDLE | TVIF_STATE;
    tvItem.hItem = hItem;//要设置状态图像的项的句柄
    tvItem.stateMask = TVIS_STATEIMAGEMASK;//此掩码指定项使用状态图像
    tvItem.state = INDEXTOSTATEIMAGEMASK(1);
    tree.SetItem(&tvItem);

 

十五 使用树控件信息提示

下面代码,将项文本添加到项的提示信息中。
要求控件具有TVS_INFOTIP样式,或指定树控件Info Tip属性为TREU,ToolTips属性为TRUE;添加TVN_GETINFOTIP通知的响应函数,在函数中添加如下代码:
void CMFCApplication1Dlg::OnTvnGetInfoTipTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTVGETINFOTIP pGetInfoTip = reinterpret_cast<LPNMTVGETINFOTIP>(pNMHDR);
    if (pGetInfoTip->hdr.idFrom == IDC_TREE1)//IDC_TREE1是要添加提示信息的树控件标识
    {
        CTreeCtrl* pTree = (CTreeCtrl*)FromHandle(pGetInfoTip->hdr.hwndFrom);//获取树控件指针
        TVITEM tvitem;
        tvitem.mask = TVIF_TEXT;
        tvitem.hItem = pGetInfoTip->hItem;
        TCHAR temp[1024];
        tvitem.pszText = temp;
        tvitem.cchTextMax = sizeof(temp) / sizeof(TCHAR);
        pTree->GetItem(&tvitem);//获取项的文本。
        wcscpy_s(pGetInfoTip->pszText, pGetInfoTip->cchTextMax, tvitem.pszText);//将项文本复制到信息提示。
    }
    *pResult = 0;
}

 

十六 树控件事件

NM_CLICK
通知父窗口,用户在树控件中单击了鼠标左键。
处理函数声明:
    afx_msg void OnNMClickTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(NM_CLICK, IDC_TREE1, &CMFCApplication1Dlg::OnNMClickTree1)
处理函数定义:
void CMFCApplication1Dlg::OnNMClickTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数pNMHDR
为NMHDR结构的指针,包含此通知的其他信息。
    pNMHDR->code;//UINT 通知代码,为NM_CLICK
    int n = (int)(pNMHDR->code);//n==NM_CLICK==-2
    pNMHDR->hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMHDR->idFrom;//UINT_PTR 发送通知的树控件的标识
参数pResult
*pResult = 1;
返回非零以防止默认处理。
*pResult = 0;
返回零以允许默认处理。

 

NM_CUSTOMDRAW
由树控件发送,通知其父窗口,实现控件的自定义绘制。此通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnNMCustomdrawTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(NM_CUSTOMDRAW, IDC_TREE1, &CMFCApplication1Dlg::OnNMCustomdrawTree1)
处理函数定义:
void CMFCApplication1Dlg::OnNMCustomdrawTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    LPNMTVCUSTOMDRAW pD = reinterpret_cast<LPNMTVCUSTOMDRAW>(pNMHDR);
    pD->nmcd;//NMCUSTOMDRAW结构
    pD->nmcd.hdr;//NMHDR结构
    pD->nmcd.hdr.hwndFrom;//HWND 发送通知的控件的句柄
    pD->nmcd.hdr.idFrom;//UINT_PTR 发送通知的控件的标识
    pD->nmcd.hdr.code;//UINT 通知代码,为NM_CUSTOMDRAW
    pD->nmcd.dwDrawStage;//DWORD 当前绘制阶段
    pD->nmcd.hdc;//HDC 控件的设备上下文的句柄
    pD->nmcd.rc;//RECT结构,要绘制区域的边界矩形
    pD->nmcd.dwItemSpec;//DWORD_PTR 项句柄
    pD->nmcd.uItemState;//UINT 当前项状态
    pD->nmcd.lItemlParam;//LPARAM 项数据
参数pResult
*pResult = CDRF_DODEFAULT;
控件将自行绘制。在此绘制周期内,它将不会发送其他NM_CUSTOMDRAW通知代码。该标志不能与任何其他标志一起使用。
 
*pResult = CDRF_DOERASE;
控件将仅绘制背景。

*pResult = CDRF_NEWFONT;
您的应用程序为此项指定了新字体;控件将使用新字体。当dwDrawStage等于CDDS_ITEMPREPAINT时,会发生这种情况。

*pResult = CDRF_NOTIFYITEMDRAW;
控件将把任何与项相关的绘图操作通知给父级。它将在绘制项之前和之后发送NM_CUSTOMDRAW通知代码。当dwDrawStage等于CDDS_PREPAINT时,会发生这种情况。

*pResult = CDRF_NOTIFYPOSTERASE;
控件将在擦除项后通知父级。当dwDrawStage等于CDDS_PREPAINT时,会发生这种情况。

*pResult = CDRF_NOTIFYPOSTPAINT;
当整个控件的绘制周期完成时,控件将发送NM_CUSTOMDRAW通知代码。当dwDrawStage等于CDDS_PREPAINT时,会发生这种情况。

*pResult = CDRF_NOTIFYSUBITEMDRAW;
您的应用程序将收到NM_CUSTOMDRAW通知代码,其中dwDrawStage设置为CDDS_ITEMPREPAINT | CDDS_SUBITEM绘制每个列表视图子项之前。然后,您可以分别为每个子项目指定字体和颜色,或者返回CDRF_DODEFAULT进行默认处理。当dwDrawStage等于CDDS_ITEMPREPAINT时,会发生这种情况。

*pResult = CDRF_SKIPDEFAULT;
您的应用程序手动绘制了该项。控件将不会绘制该项。当dwDrawStage等于CDDS_ITEMPREPAINT时,会发生这种情况。
 
*pResult = CDRF_SKIPPOSTPAINT;
控件将不会在项周围绘制焦点矩形。

绘制阶段值                              说明
CDDS_PREPAINT                  在绘制周期开始之前
CDDS_POSTPAINT               在绘制周期完成之后
CDDS_PREERASE                 擦除开始之前
CDDS_POSTERASE              擦除完成后
CDDS_ITEMPREPAINT          绘制项之前
CDDS_ITEMPOSTPAINT        绘制项后
CDDS_ITEMPREERASE        删除项之前
CDDS_ITEMPOSTERASE      删除项之后
CDDS_SUBITEM                     绘制子项

自定义绘制示例1://绘制树控件的背景,项的选中状态,热点状态,焦点状态。
void CMFCApplication1Dlg::OnNMCustomdrawTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
    LPNMTVCUSTOMDRAW pD = reinterpret_cast<LPNMTVCUSTOMDRAW>(pNMHDR);
    if (pD->nmcd.hdr.idFrom == IDC_TREE1)//IDC_TREE1为树控件标识
    {
        CDC dc; dc.Attach(pD->nmcd.hdc);
        switch (pD->nmcd.dwDrawStage)
        {
        case CDDS_PREPAINT://在绘制周期开始之前
            dc.FillSolidRect(&(pD->nmcd.rc), RGB(200, 100, 100));//绘制树控件背景
            *pResult = CDRF_NOTIFYITEMDRAW;
            //将*pResult赋值CDRF_NOTIFYITEMDRAW,则下一个NM_CUSTOMDRAW通知已将dwDrawStage设置为CDDS_ITEMPREPAINT。
            break;
        case CDDS_ITEMPREPAINT://绘制项之前
            pD->clrText = RGB(255, 255, 255);//指定项文本颜色
            pD->clrTextBk = RGB(200, 100, 100);//指定项文本背景色
            if (pD->nmcd.uItemState & CDIS_SELECTED)//选中状态
            {
                pD->clrTextBk = RGB(100, 100, 220);//指定项文本背景色
                dc.FillSolidRect(&(pD->nmcd.rc), RGB(100, 100, 220)); //绘制项背景颜色
            }
            if (pD->nmcd.uItemState & CDIS_HOT)//热点状态
            {
                pD->clrTextBk = RGB(220, 120, 120);//指定项文本背景色
                dc.FillSolidRect(&(pD->nmcd.rc), RGB(200, 100, 100));//绘制项背景颜色
            }
            if (pD->nmcd.uItemState & CDIS_FOCUS)//项具有焦点状态
            {
                pD->clrTextBk = RGB(120, 120, 240);//指定项文本背景色
                dc.FillSolidRect(&(pD->nmcd.rc), RGB(120, 120, 240));//绘制项背景颜色
            }
            *pResult = 0;
            break;
        }
        dc.Detach();
    }
}
绘制结果:
 
自定义绘制示例2://更改树控件字体
void CMFCApplication1Dlg::OnNMCustomdrawTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
    LPNMTVCUSTOMDRAW pD = reinterpret_cast<LPNMTVCUSTOMDRAW>(pNMHDR);
    if (pD->nmcd.hdr.idFrom == IDC_TREE1)//IDC_TREE1为树控件标识
    {
        CDC dc; dc.Attach(pD->nmcd.hdc);
        switch (pD->nmcd.dwDrawStage)
        {
        case CDDS_PREPAINT://在绘制周期开始之前
            *pResult = CDRF_NOTIFYITEMDRAW;
            //将*pResult赋值CDRF_NOTIFYITEMDRAW,则下一个NM_CUSTOMDRAW通知已将dwDrawStage设置为CDDS_ITEMPREPAINT。
            break;
        case CDDS_ITEMPREPAINT://绘制项之前
            dc.SelectObject(&font);//字体font需预先声明并创建
            *pResult = CDRF_NEWFONT;
            break;
        }
        dc.Detach();
    }
}
 

NM_DBLCLK
通知父窗口,用户在树控件内双击了鼠标左键。
处理函数声明:
    afx_msg void OnNMDblclkTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(NM_DBLCLK, IDC_TREE1, &CMFCApplication1Dlg::OnNMDblclkTree1)
处理函数定义:
void CMFCApplication1Dlg::OnNMDblclkTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数pNMHDR
    pNMHDR->code;//UINT 通知代码,为NM_DBLCLK
    int n = (int)(pNMHDR->code);//n==NM_DBLCLK==-3
    pNMHDR->hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMHDR->idFrom;//UINT_PTR 发送通知的树控件的标识
参数pResult
*pResult = 1;
返回非零以防止默认处理。
*pResult = 0;
返回零以允许默认处理。
 

NM_KILLFOCUS
通知父窗口,树控件失去输入焦点。
处理函数声明:
    afx_msg void OnNMKillfocusTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(NM_KILLFOCUS, IDC_TREE1, &CMFCApplication1Dlg::OnNMKillfocusTree1)
处理函数定义:
void CMFCApplication1Dlg::OnNMKillfocusTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    *pResult = 0;
}
参数pNMHDR
    pNMHDR->code;//UINT 通知代码,为NM_KILLFOCUS
    int n = (int)(pNMHDR->code);//n==NM_KILLFOCUS==-8
    pNMHDR->hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMHDR->idFrom;//UINT_PTR 发送通知的树控件的标识
参数pResult
返回值被忽略。
 

NM_OUTOFMEMORY
通知父窗口,由于没有足够的可用内存,无法完成操作。此通知代码以 WM_NOTIFY 消息的形式发送。
处理函数声明:
    afx_msg void OnNMOutofmemoryTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(NM_OUTOFMEMORY, IDC_TREE1, &CMFCApplication1Dlg::OnNMOutofmemoryTree1)
处理函数定义:
void CMFCApplication1Dlg::OnNMOutofmemoryTree1(NMHDR* pNMHDR, LRESULT* pResult)
{

    *pResult = 0;
}
参数pNMHDR
    pNMHDR->code;//UINT 通知代码,为NM_OUTOFMEMORY
    int n = (int)(pNMHDR->code);//n==NM_OUTOFMEMORY==-1
    pNMHDR->hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMHDR->idFrom;//UINT_PTR 发送通知的树控件的标识
参数pResult

 

NM_RCLICK 
通知父窗口,用户在控件中单击了鼠标右键。 此通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnNMRClickTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(NM_RCLICK, IDC_TREE1, &CMFCApplication1Dlg::OnNMRClickTree1)
处理函数定义:
void CMFCApplication1Dlg::OnNMRClickTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数pNMHDR
    pNMHDR->code;//UINT 通知代码,为NM_RCLICK
    int n = (int)(pNMHDR->code);//n==NM_RCLICK==-5
    pNMHDR->hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMHDR->idFrom;//UINT_PTR 发送通知的树控件的标识
参数pResult
*pResult = 1;
返回非零以防止默认处理。
*pResult = 0;
返回零以允许默认处理。

NM_SETFOCUS
通知父窗口,树控件获得输入焦点。此通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnNMSetfocusTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(NM_SETFOCUS, IDC_TREE1, &CMFCApplication1Dlg::OnNMSetfocusTree1)
处理函数定义:
void CMFCApplication1Dlg::OnNMSetfocusTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数pNMHDR
    pNMHDR->code;//UINT 通知代码,为NM_SETFOCUS
    int n = (int)(pNMHDR->code);//n==NM_SETFOCUS==-7
    pNMHDR->hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMHDR->idFrom;//UINT_PTR 发送通知的树控件的标识
参数pResult
返回值被忽略。
 

TVN_BEGINDRAG
通知父窗口,树控件开始左键拖放操作。此通知代码以WM_NOTIFY消息的形式发送。
具有TVS_DISABLEDRAGDROP样式的树控件不会发送此通知代码。
处理函数声明:
    afx_msg void OnTvnBegindragTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_BEGINDRAG, IDC_TREE1, &CMFCApplication1Dlg::OnTvnBegindragTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnBegindragTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数pNMHDR
    pNMHDR->code;//UINT 通知代码,为TVN_BEGINDRAG
    int n = (int)(pNMHDR->code);//n==TVN_BEGINDRAG==-456
    pNMHDR->hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMHDR->idFrom;//UINT_PTR 发送通知的树控件的标识
参数pResult
返回值被忽略。
 

TVN_BEGINLABELEDIT
通知父窗口,树控件项文本的编辑开始。此通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnTvnBeginlabeleditTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_BEGINLABELEDIT, IDC_TREE1, &CMFCApplication1Dlg::OnTvnBeginlabeleditTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnBeginlabeleditTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数pNMHDR
    pNMHDR->code;//UINT 通知代码,为TVN_BEGINLABELEDIT
    int n = (int)(pNMHDR->code);//n==TVN_BEGINLABELEDIT==-459
    pNMHDR->hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMHDR->idFrom;//UINT_PTR 发送通知的树控件的标识
参数pResult
*pResult = 1;
返回非零,取消项文本编辑。
*pResult = 0;
返回零,完成项文本编辑。
 

TVN_BEGINRDRAG
通知父窗口,开始树控件项的右键拖动。此通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnTvnBeginrdragTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_BEGINRDRAG, IDC_TREE1, &CMFCApplication1Dlg::OnTvnBeginrdragTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnBeginrdragTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数pNMHDR
    pNMHDR->code;//UINT 通知代码,为TVN_BEGINRDRAG
    int n = (int)(pNMHDR->code);//n==TVN_BEGINRDRAG==-457
    pNMHDR->hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMHDR->idFrom;//UINT_PTR 发送通知的树控件的标识
参数pResult
返回值被忽略。
 

TVN_DELETEITEM
通知父窗口,树控件正在删除项。此通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnTvnDeleteitemTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_DELETEITEM, IDC_TREE1, &CMFCApplication1Dlg::OnTvnDeleteitemTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnDeleteitemTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pNMTreeView->hdr;//NMHDR结构
    pNMTreeView->hdr.code;//UINT 通知代码。为TVN_DELETEITEM
    pNMTreeView->hdr.hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMTreeView->hdr.idFrom;//UINT_PTR 发送通知的树控件的标识
    pNMTreeView->action;//UINT 操作标志
    pNMTreeView->itemOld;//TVITEM结构 旧项状态的信息,为被删除项的句柄
    pNMTreeView->itemOld.hItem;//HTREEITEM 被删除项的句柄
    pNMTreeView->itemNew;//TVITEM结构 新项状态的信息,不使用此参数
    pNMTreeView->ptDrag;//POINT 发送通知时,鼠标的客户端坐标
参数pResult
返回值被忽略。
 

TVN_ENDLABELEDIT
通知父窗口,树控件项文本编辑结束。此通知代码以WM_NOTIFY消息的形式发送。
要发送此通知,要求树控件具有TVS_EDITLABELS样式。
处理函数声明:
    afx_msg void OnTvnEndlabeleditTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE1, &CMFCApplication1Dlg::OnTvnEndlabeleditTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnEndlabeleditTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
    *pResult = 0;
}
参数pNMHDR
    pTVDispInfo->hdr;//NMHDR结构
    pTVDispInfo->hdr.code;//UINT 通知代码。为TVN_ENDLABELEDIT
    pTVDispInfo->hdr.hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pTVDispInfo->hdr.idFrom;//UINT_PTR 发送通知的树控件的标识
    pTVDispInfo->item;//TVITEM结构
    pTVDispInfo->item.hItem;//HTREEITEM 完成文本编辑的项的句柄
    pTVDispInfo->item.pszText;//LPWSTR 新的项文本
参数pResult
*pResult = 1;
返回TRUE,将已编辑的文本设置为项文本。
*pResult = 0;
返回FALSE,拒绝已编辑的文本,恢复为原来的文本。

示例
void CMFCApplication1Dlg::OnTvnEndlabeleditTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
    if (pTVDispInfo->hdr.idFrom == IDC_TREE1)//如果通知由IDC_TREE1树控件发出
    {
        *pResult = 1;
    }
    else
        *pResult = 0;
}
 

TVN_GETDISPINFO
通知父窗口,树控件请求显示或排序项所需的信息。此通知代码以WM_NOTIFY消息的形式发送。
树控件在以下3种情况下,发出此通知:
1.项的TVITEM结构的pszText成员是LPSTR_TEXTCALLBACK值。
2.项的TVITEM结构的iImage或iSelectedImage成员是I_IMAGECALLBACK值。
3.项的TVITEM结构的cChildren成员是I_CHILDRENCALLBACK值。

函数声明:
    afx_msg void OnTvnGetdispinfoTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_GETDISPINFO, IDC_TREE1, &CMFCApplication1Dlg::OnTvnGetdispinfoTree1)
函数定义:
void CMFCApplication1Dlg::OnTvnGetdispinfoTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
    *pResult = 0;
}
参数pNMHDR
    pTVDispInfo;//NMTVDISPINFO结构
    pTVDispInfo->hdr;//NMHDR结构
    pTVDispInfo->item;//TVITEM结构
    pTVDispInfo->item.mask;//UINT  NMTVDISPINFO结构掩码
    pTVDispInfo->item.hItem;//HTREEITEM  项的句柄
    pTVDispInfo->item.state;//UINT  一组位标志和图像列表索引,用于指示项的状态。
    pTVDispInfo->item.stateMask;//UINT 项状态掩码
    pTVDispInfo->item.pszText;//LPTSTR 指向存储项文本字符串缓冲区的指针
    pTVDispInfo->item.cchTextMax;//int 缓冲区的大小,以字符为单位
    pTVDispInfo->item.iImage;//int 项的图像的索引
    pTVDispInfo->item.iSelectedImage;//int 项选中时的图像索引
    pTVDispInfo->item.cChildren;//int 指示项是否含有子项
    pTVDispInfo->item.lParam;//LPARAM 项关联的数值
参数pResult
返回值被忽略。

示例
    HTREEITEM h1, h2, h3, h4;
    h1=tree.InsertItem(L"A", 0, 0);    h2=tree.InsertItem(L"B", 0, 0);
    h3=tree.InsertItem(L"C", 0, 0);    h4=tree.InsertItem(L"D", 0, 0);//初始化树控件
1.更改项属性:
    TVITEM tvItem1;
    tvItem1.mask = TVIF_HANDLE | TVIF_TEXT;
    tvItem1.hItem = h1;//指定第1项句柄
    tvItem1.pszText = LPSTR_TEXTCALLBACK;
    tree.SetItem(&tvItem1);//设置第1项文本为LPSTR_TEXTCALLBACK值

    TVITEM tvItem2;
    tvItem2.mask= TVIF_HANDLE | TVIF_TEXT;
    tvItem2.hItem = h2;//指定第2项句柄
    tvItem2.pszText = LPSTR_TEXTCALLBACK;
    tree.SetItem(&tvItem2);//设置第2项文本为LPSTR_TEXTCALLBACK值

2.添加TVN_GETDISPINFO通知的响应函数,在函数中指定项文本:
void CMFCApplication1Dlg::OnTvnGetdispinfoTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
    if (pTVDispInfo->hdr.idFrom == IDC_TREE1 && pTVDispInfo->item.hItem == h1)
    {
        pTVDispInfo->item.pszText = L"ABCD";//指定第1项的文本
    }
    if (pTVDispInfo->hdr.idFrom == IDC_TREE1 && pTVDispInfo->item.hItem==h2)
    {
        pTVDispInfo->item.pszText = L"1234";//指定第2项的文本
    }
    *pResult = 0;
}

TVN_GETINFOTIP
由具有TVS_INFOTIP样式(“信息提示”属性为TRUE)的树控件发送到父窗口。请求在工具提示中显示其他文本信息。通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnTvnGetInfoTipTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_GETINFOTIP, IDC_TREE1, &CMFCApplication1Dlg::OnTvnGetInfoTipTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnGetInfoTipTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTVGETINFOTIP pGetInfoTip = reinterpret_cast<LPNMTVGETINFOTIP>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数pGetInfoTip
    pGetInfoTip->hdr;//NMHDR结构
    pGetInfoTip->hdr.code;//UINT 通知代码,为TVN_GETINFOTIP
    pGetInfoTip->hdr.hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pGetInfoTip->hdr.idFrom;//UINT_PTR 发送通知的树控件的标识
    pGetInfoTip->hItem;//HTREEITEM 请求提示信息的树控件项的句柄
    pGetInfoTip->pszText;//LPWSTR 请求提示信息的树控件项的文本缓冲区的指针
    pGetInfoTip->cchTextMax;//int 文本缓冲区的大小,以字符为单位
    pGetInfoTip->lParam;//LPARAM 项关联的数值
参数pResult
忽略返回值。
示例
    HTREEITEM h1, h2, h3, h4;//将项句柄声明为全局变量
    h1=tree.InsertItem(L"A", 0, 0);    h2=tree.InsertItem(L"B", 0, 0);
    h3=tree.InsertItem(L"C", 0, 0);    h4=tree.InsertItem(L"D", 0, 0);

void CMFCApplication1Dlg::OnTvnGetInfoTipTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTVGETINFOTIP pGetInfoTip = reinterpret_cast<LPNMTVGETINFOTIP>(pNMHDR);
    if (pGetInfoTip->hdr.idFrom == IDC_TREE1 && pGetInfoTip->hItem == h1)
    {
        pGetInfoTip->pszText = _T("提示文本内容1");
    }
    if (pGetInfoTip->hdr.idFrom == IDC_TREE1 && pGetInfoTip->hItem == h2)
    {
        pGetInfoTip->pszText = _T("提示文本内容2");
    }
    *pResult = 0;
}
 

TVN_ITEMCHANGED
通知父窗口,树控件项属性已更改。此通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnTvnItemChangedTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_ITEMCHANGED, IDC_TREE1, &CMFCApplication1Dlg::OnTvnItemChangedTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnItemChangedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    NMTVITEMCHANGE* pNMTVItemChange = reinterpret_cast<NMTVITEMCHANGE*>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pNMTVItemChange->hdr;//NMHDR结构
    pNMTVItemChange->hdr.code;//UINT 通知代码,为TVN_ITEMCHANGED
    pNMTVItemChange->hdr.hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMTVItemChange->hdr.idFrom;//UINT_PTR 发送通知的树控件的标识
    pNMTVItemChange->hItem;//HTREEITEM 已更改属性的项的句柄
    pNMTVItemChange->uChanged;//UINT 指定属性。唯一受支持的属性是状态属性,值为TVIF_STATE
    pNMTVItemChange->uStateOld;//UINT 项以前的状态标志
    pNMTVItemChange->uStateNew;//UINT 项新的状态标志
    pNMTVItemChange->lParam;//LPARAM 与项关联的数值
参数pResult
*pResult = 0;
返回FALSE以接受更改。
*pResult = 1;
返回TRUE以阻止更改。

处理函数会为每个发生属性更改的项调用。
 

TVN_ITEMCHANGING
通知父窗口,树控件项属性即将更改。此通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnTvnItemChangingTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_ITEMCHANGING, IDC_TREE1, &CMFCApplication1Dlg::OnTvnItemChangingTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnItemChangingTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    NMTVITEMCHANGE* pNMTVItemChange = reinterpret_cast<NMTVITEMCHANGE*>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pNMTVItemChange->hdr;//NMHDR结构
    pNMTVItemChange->hdr.code;//UINT 通知代码,为TVN_ITEMCHANGING
    pNMTVItemChange->hdr.hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMTVItemChange->hdr.idFrom;//UINT_PTR 发送通知的树控件的标识
    pNMTVItemChange->hItem;//HTREEITEM 即将更改属性的项的句柄
    pNMTVItemChange->uChanged;//UINT 指定属性。唯一受支持的属性是状态属性,值为TVIF_STATE
    pNMTVItemChange->uStateOld;//UINT 项以前的状态标志
    pNMTVItemChange->uStateNew;//UINT 项新的状态标志
    pNMTVItemChange->lParam;//LPARAM 与项关联的数值
参数pResult
*pResult = 0;
返回FALSE以接受更改。
*pResult = 1;
返回TRUE以阻止更改。

处理函数会为每个发生属性更改的项调用。
 

TVN_ITEMEXPANDED
通知父窗口,树控件含有子项的项,已展开或折叠子项列表。此通知以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnTvnItemexpandedTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_ITEMEXPANDED, IDC_TREE1, &CMFCApplication1Dlg::OnTvnItemexpandedTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnItemexpandedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pNMTreeView->hdr;//NMHDR结构
    pNMTreeView->hdr.code;//UINT 通知代码,为TVN_ITEMEXPANDED
    pNMTreeView->hdr.hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMTreeView->hdr.idFrom;//UINT_PTR 发送通知的树控件的标识
    pNMTreeView->action;//UINT 操作标志。展开为TVE_EXPAND,折叠为TVE_COLLAPSE
    pNMTreeView->itemOld;//TVITEM结构  发生展开或折叠的项的旧状态信息
    pNMTreeView->itemNew;//TVITEM结构  发生展开或折叠的项的新状态信息
    pNMTreeView->ptDrag;//POINT 鼠标的客户端坐标。此参数始终为CPoint(0,0)
参数pResult
返回值被忽略。
 

TVN_ITEMEXPANDING
通知父窗口,树控件含有子项的项,即将展开或折叠子项列表。此通知以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnTvnItemexpandingTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_ITEMEXPANDING, IDC_TREE1, &CMFCApplication1Dlg::OnTvnItemexpandingTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnItemexpandingTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pNMTreeView->hdr;//NMHDR结构
    pNMTreeView->hdr.code;//UINT 通知代码,为TVN_ITEMEXPANDING
    pNMTreeView->hdr.hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMTreeView->hdr.idFrom;//UINT_PTR 发送通知的树控件的标识
    pNMTreeView->action;//UINT 操作标志。展开为TVE_EXPAND,折叠为TVE_COLLAPSE
    pNMTreeView->itemOld;//TVITEM结构  发生展开或折叠的项的旧状态信息。此参数不包含项信息
    pNMTreeView->itemNew;//TVITEM结构  发生展开或折叠的项的新状态信息
    pNMTreeView->ptDrag;//POINT 鼠标的客户端坐标。此参数始终为CPoint(0,0)
参数pResult
*pResult = 1;
返回TRUE以防止子项列表展开或折叠。
*pResult = 0;
返回FALSE完成子项列表展开或折叠。
 

TVN_KEYDOWN
通知父窗口,树控件具有焦点时,用户按下了一个键。此通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnTvnKeydownTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_KEYDOWN, IDC_TREE1, &CMFCApplication1Dlg::OnTvnKeydownTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnKeydownTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTVKEYDOWN pTVKeyDown = reinterpret_cast<LPNMTVKEYDOWN>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pTVKeyDown->hdr;//NMHDR结构 
    pTVKeyDown->hdr.code;//UINT 通知代码,为TVN_KEYDOWN
    pTVKeyDown->hdr.hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pTVKeyDown->hdr.idFrom;//UINT_PTR 发送通知的树控件的标识
    pTVKeyDown->wVKey;//WORD 虚拟键代码
    pTVKeyDown->flags;//UINT 始终为零
参数pResult
*pResult = 0;
如果按下的是字符键,返回零,则该字符将继续用作树控件键盘接口输入字符。
*pResult = 1;
如果按下的是字符键,返回非零,该字符不会用作树控件键盘接口输入字符。
对于其它键,将忽略返回值。
示例
void CMFCApplication1Dlg::OnTvnKeydownTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTVKEYDOWN pTVKeyDown = reinterpret_cast<LPNMTVKEYDOWN>(pNMHDR);
    if (pTVKeyDown->hdr.idFrom == IDC_TREE1)
    {
        switch (pTVKeyDown->wVKey)
        {
        case 65:          //按下了A键
            MessageBox(_T("A"));
            break;
        case 66:         //按下了B键
            MessageBox(_T("B"));
            break;
        }
    }
    *pResult = 1;
}
 

TVN_SELCHANGED
通知父窗口,树控件项选择已改变,此通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnTvnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, &CMFCApplication1Dlg::OnTvnSelchangedTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pNMTreeView->hdr;//NMHDR结构
    pNMTreeView->hdr.code;//UINT 通知代码。为TVN_SELCHANGED
    pNMTreeView->hdr.hwndFrom;//HWND 发送通知的控件的窗口句柄
    pNMTreeView->hdr.idFrom;//UINT_PTR 发送通知的控件的标识
    pNMTreeView->itemNew;//TVITEM结构 包含新选中项的信息。只有结构的mask,hItem,state和lParam成员才有效。
    pNMTreeView->itemNew.hItem;//HTREEITEM 新选中项的句柄
    pNMTreeView->itemOld;//TVITEM结构 包含原来的选中项的信息。只有结构的mask,hItem,state和lParam成员才有效。
参数pResult
返回值被忽略。
示例
void CMFCApplication1Dlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    if(pNMTreeView->hdr.idFrom == IDC_TREE1)
    {
        CTreeCtrl* pTree = (CTreeCtrl*)FromHandle(pNMTreeView->hdr.hwndFrom);//获取树控件的指针
        CString str=pTree->GetItemText(pNMTreeView->itemNew.hItem);//获取新选中项的文本
    }
    *pResult = 0;
}
 

TVN_SELCHANGING
通知父窗口,树控件项选择即将改变。此通知代码以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnTvnSelchangingTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_SELCHANGING, IDC_TREE1, &CMFCApplication1Dlg::OnTvnSelchangingTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnSelchangingTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pNMTreeView->hdr;//NMHDR结构
    pNMTreeView->hdr.code;//UINT 通知代码,为TVN_SELCHANGING
    pNMTreeView->hdr.hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMTreeView->hdr.idFrom;//UINT_PTR 发送通知的树控件的标识
    pNMTreeView->action;//UINT 操作标志。展开为TVE_EXPAND,折叠为TVE_COLLAPSE
    pNMTreeView->itemOld;//TVITEM结构  先前选中项的信息
    pNMTreeView->itemNew;//TVITEM结构  新选中项的信息
参数pResult
*pResult = 1;
返回TRUE以防止选择更改。
*pResult = 0;
返回FALSE完成选择更改。
 

TVN_SINGLEEXPAND
由具有TVS_SINGLEEXPAND样式(或“单个展开”属性为TRUE)的树控件发送到父窗口,通过鼠标单击改变了选中项。此通知代码以WM_NOTIFY消息的形式发送。
TVS_SINGLEEXPAND样式即为:展开选中的项,折叠未选中的项。
处理函数声明:
    afx_msg void OnTvnSingleExpandTree1(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(TVN_SINGLEEXPAND, IDC_TREE1, &CMFCApplication1Dlg::OnTvnSingleExpandTree1)
处理函数定义:
void CMFCApplication1Dlg::OnTvnSingleExpandTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pNMTreeView->hdr;//NMHDR结构
    pNMTreeView->hdr.code;//UINT 通知代码,为TVN_SINGLEEXPAND
    pNMTreeView->hdr.hwndFrom;//HWND 发送通知的树控件的窗口句柄
    pNMTreeView->hdr.idFrom;//UINT_PTR 发送通知的树控件的标识
    pNMTreeView->action;//UINT 操作标志。始终为1000
    pNMTreeView->itemOld;//TVITEM结构  先前选中项的信息
    pNMTreeView->itemNew;//TVITEM结构  新选中项的信息
参数pResult
*pResult = 0;
发生默认行为。即展开选中的项,折叠未选中的项。
*pResult = TVNRET_SKIPOLD;
不折叠未选中的项。
*pResult = TVNRET_SKIPNEW;
不展开选中的项。
 

十七 树控件样式

样式常量                                  16进制值            10进制值    说明
TVS_CHECKBOXES                   0x0100           256             
启用复选框。
TVS_DISABLEDRAGDROP        0x0010           16               
禁止树控件发送TVN_BEGINDRAG通知代码。
TVS_EDITLABELS                      0x0008            8                 
允许用户编辑树控件项的标签(项文本)。
TVS_FULLROWSELECT             0x1000           4096            
整行选择。
TVS_HASBUTTONS                0x0001              1                  
显示父项旁边的加号(+)和减号( - )按钮。
TVS_HASLINES                       0x0002              2                  
使用线条显示项的层次结构。
TVS_INFOTIP                          0x0800              2048            
通过发送TVN_GETINFOTIP通知获取工具提示信息
TVS_LINESATROOT                0x0004             4                 
使用行连接树控件根目录中的项。
TVS_NOHSCROLL                   0x8000              32768         
禁用控件中的水平滚动条。
TVS_NONEVENHEIGHT          0x4000             16384          
使用TVM_SETITEMHEIGHT消息将项的高度设置为奇数高度。
TVS_NOSCROLL                      0x2000              8192            
禁用控件中的水平和垂直滚动条。
TVS_NOTOOLTIPS                  0x0080              128              
禁用工具提示。
TVS_RTLREADING                  0x0040               64               
树控件文本将以与父窗口中文本相反的方向读取。
TVS_SHOWSELALWAYS         0x0020              32               
当树控件失去焦点时,使选定的项保持选中状态。
TVS_SINGLEEXPAND             0x0400              1024             
选中某项时,展开该项。
TVS_TRACKSELECT               0x0200              512              
启用热跟踪。

 

十八 树控件扩展样式    

样式常量                                                   16进制值    10进制值    说明
TVS_EX_AUTOHSCROLL                        0x0020      32    
删除水平滚动条并根据鼠标位置自动水平滚动。
TVS_EX_DIMMEDCHECKBOXES           0x0200      512    
如果控件具有TVS_CHECKBOXES样式,则包括灰色复选框状态。
TVS_EX_DOUBLEBUFFER                     0x0004       4    
双缓冲。
TVS_EX_DRAWIMAGEASYNC                0x0400       1024    
检索日历网格信息。
TVS_EX_EXCLUSIONCHECKBOXES     0x0100        256    
如果控件具有TVS_CHECKBOXES样式,则包括排除复选框状态。
TVS_EX_FADEINOUTEXPANDOS           0x0040        64    
当鼠标移开或进入鼠标悬停状态时,淡入淡出expando按钮。
TVS_EX_MULTISELECT                           0x0002        2    
不支持。不使用。
TVS_EX_NOINDENTSTATE                      0x0008        8    
不要缩进expando按钮的树状视图。
TVS_EX_NOSINGLECOLLAPSE              0x0001         1    
不折叠项。
TVS_EX_PARTIALCHECKBOXES            0x0080         128    
如果控件具有TVS_CHECKBOXES样式,则包括部分复选框状态。
TVS_EX_RICHTOOLTIP                            0x0010         16    
允许在树控件中使用多格式工具提示(使用图标和文本自定义绘制)。

十九 树控件项状态

状态常量                                 16进制值    10进制值    说明
TVIS_BOLD                             0x0010      16    
该项为粗体。
TVIS_CUT                               0x0004        4    
该项被选择为剪切和粘贴操作的一部分.
TVIS_DROPHILITED              0x0008        8    
该项选择为拖放目标。
TVIS_EXPANDED                   0x0020        32    
该项的子项已展开.
TVIS_EXPANDEDONCE         0x0040        64      
该项曾经展开(子项至少展开一次)。
TVIS_EXPANDPARTIAL         0x0080        128    
展开该项的部分。
TVIS_SELECTED                   0x0002         2    
该项被选中。
TVIS_OVERLAYMASK           0x0F00         3840    
用于指定项的叠加图像索引的位的掩码。
TVIS_STATEIMAGEMASK     0xF000         61440    
用于指定项的状态图像索引的位的掩码。
TVIS_USERMASK                  0xF000         61440    
与TVIS_STATEIMAGEMASK相同。
0                                              0x0000         0    
不包含以上所有状态。

二十 TVITEM结构掩码

掩码常量                             16进制值    10进制值    说明
TVIF_CHILDREN                0x0040       64    
cChildren成员有效。
TVIF_DI_SETITEM             0x1000       4096    
由控件保留信息。
TVIF_HANDLE                    0x0010       16    
hItem成员有效。
TVIF_IMAGE                       0x0002        2    
iImage成员有效。
TVIF_PARAM                       0x0004       4    
lParam成员有效。
TVIF_SELECTEDIMAGE    0x0020        32    
iSelectedImage成员有效。
TVIF_STATE                        0x0008        8    
state和stateMask成员有效。
TVIF_TEXT                          0x0001        1    
pszText和cchTextMax成员有效。

二十一 树控件键盘接口

当树控件具有焦点,用户按下字符键时,会选中项文本以该字符开头的项;按向下箭头键,会向下移动选择;按向上箭头键,向上移动选择。
当某项具有焦点且包含子项,按向右箭头键,展开子项;按向左箭头键,关闭子项的显示。
当按Ctrl+Page Down时,向下滚动树控件。
当按Ctrl+Page Up时,向上滚动树控件。
当按Ctrl+End时,滚动到树控件的末尾。
当按Ctrl+Home时,滚动到树控件的开头。

 

 以下链接可以下载全文:

https://download.csdn.net/download/h3974/33161552

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页

打赏作者

h3974

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值