TreeCtrl的使用和一个CTreeCtrl的派生类

1.树视图风格:

TVS_HASBUTTONS;  //在父项旁边显示(+)(-)

    TVS_HASLINES;   //使用线条显示各项之间的层次

    TVS_LINESATROOT;//使用线条链接树视图控件根部各项

2.处理单击事件:TVN_SELCHANGED

void CTreeCtrlDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)

{

    LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR);

    // TODO: 在此添加控件通知处理程序代码

    HTREEITEM ht=m_treeCtrl.GetSelectedItem();

    CString strSelect=m_treeCtrl.GetItemText(ht);

    m_strTreeVal=strSelect;

    UpdateData(FALSE);

    *pResult = 0;

}

3.同时让自己派生的CMyTreeCtrl类和对话框处理TVN_SELCHANGED消息:

只须在CMyTreeCtrl中处理以下消息,并返回FALSEOKON_NOTIFY_REFLECT_EX(TVN_SELCHANGED, OnTvnSelchanged) OnTvnSelchanged的签名如下

BOOL CMyTreeCtrl::OnTvnSelchanged(NMHDR *pNMHDR,LRESULT *pResult)

 

4.编辑标签:要允许编辑树视图控件中的文本,可以设置以下三个步骤

    1.设置树视图的TVS_EDITLABELS风格

TVS_EDITLABE可以通过资源编辑框内部修改(Edit labels),也可以用代码的方式修改,如下

long lStyle=::GetWindowLong(m_treeCtrl.GetSafeHwnd(),GWL_STYLE);

    lStyle|=TVS_EDITLABELS;

    ::SetWindowLong(m_treeCtrl.GetSafeHwnd(),GWL_STYLE,lStyle)

    2.处理TVN_BEGINLABELEDIT通知消息

     //设置相关限制,如限制编辑框字符串长度

CEdit*pEdit=GetEditControl();   //获取当前选中结点编辑框

    ASSERT(pEdit);

    if (pEdit)

    {

        pEdit->LimitText(15);//设置编辑框文本长度为15个字符串

        *pResult = 0;      

    }

    3.处理TVN_ENDLABLEEDIT通知消息

    HTREEITEM hParent=GetParentItem(pTVDispInfo->item.hItem); //获取父结点 

    HTREEITEM hChild=GetChildItem(hParent?hParent:TVI_ROOT); //获取第一个根结点

hChild=GetNextSiblingItem(hChild);          //获取下一个兄弟节点

if (pTVDispInfo->item.hItem!=hChild)        //判断是否与当前节点相同

pTVDispInfo->item.pszText                   //获取当前节点的字符串

CString strText=GetItemText(hChild);        //获取节点的字符串

 

3.让树视图处理EscEnter

重载PreTranslateMessage函数

BOOL bHandleMsg=FALSE;

    switch(pMsg->message) {

    case VK_ESCAPE:

    case VK_RETURN:

        if (::GetKeyState(VK_CONTROL)&0x8000)

        {

            break;

        }

        if (GetEditControl())

        {

            ::TranslateMessage(pMsg);

            ::DispatchMessage(pMsg);

            bHandleMsg=TRUE;

        }

        break;

    }

4.实现上下文菜单

WM_RBUTTONDOWN消息处理函数上实现上下文菜单

5.展开和收起树视图结点:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

HTREEITEM hItem=GetRootItem();              //获取根结点,可能会有多个根结点

ItemHasChildren(hParent)                    //判断结点是否有孩子结点

hItem=GetChildItem(hParent);                //获取第一个子结点

hItem=GetNextSiblingItem(hItem));           //获取下一个兄弟结点结点

Expand(hItem,bExpand?TVE_EXPAND:TVE_COLLAPSE);//展开/叠起结点

Select(hItem,TVGN_FIRSTVISIBLE);                //设置选中结点

CString str=GetItemText(hChild);            //获取结点字符串信息

HTREEITEM hCurrSel = GetSelectedItem();     //获取当前选中结点

SelectItem(hNewSel);

HTREEITEM hNewSel = HitTest(pt, &nFlags);       //判断坐标是否在当前结点范围内

HTREEITEM hItem=InsertItem(dlg.m_strItemText,hItemParent);  //插入结点

   

 

#pragma once

 

//定义文件MyTreeCtrl.h

// CMyTreeCtrl

 

class CMyTreeCtrl : public CTreeCtrl

{

    DECLARE_DYNAMIC(CMyTreeCtrl)

 

public:

    CMyTreeCtrl();

    virtual ~CMyTreeCtrl();

 

protected:

    DECLARE_MESSAGE_MAP()

    void ExpandBranch(HTREEITEM hItem,BOOL bExpand =TRUE);

public:

    void ExpandAllBranches(BOOL bExpand =TRUE);

    BOOL DoesItemExist(HTREEITEM hItemParent, CString const& strItem);

    afx_msg void OnRButtonDown(UINT nFlags, CPoint point);

    afx_msg void OnAddItem();

    virtual BOOL PreTranslateMessage(MSG* pMsg);

    afx_msg void OnTvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult);

    afx_msg void OnTvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult);

   

    afx_msg BOOL OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult);

};

 

// MyTreeCtrl.cpp : 实现文件

//

 

#include "stdafx.h"

#include "TreeCtrl.h"

#include "MyTreeCtrl.h"

#include "./mytreectrl.h"

#include "AddItemDlg.h"

 

 

// CMyTreeCtrl

 

IMPLEMENT_DYNAMIC(CMyTreeCtrl, CTreeCtrl)

CMyTreeCtrl::CMyTreeCtrl()

{

}

 

CMyTreeCtrl::~CMyTreeCtrl()

{

}

 

 

BEGIN_MESSAGE_MAP(CMyTreeCtrl, CTreeCtrl)

    ON_WM_RBUTTONDOWN()

    ON_COMMAND(IDR_ADD_ITEM, OnAddItem)

    ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnTvnEndlabeledit)

    ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnTvnBeginlabeledit)

    ON_NOTIFY_REFLECT_EX(TVN_SELCHANGED, OnTvnSelchanged)

END_MESSAGE_MAP()

 

 

 

// CMyTreeCtrl 消息处理程序

void CMyTreeCtrl::ExpandBranch(HTREEITEM hItem,BOOL bExpand /* =TRUE */)

//展开

{

    if (ItemHasChildren(hItem))  //判断是否有孩子结点

    {

        Expand(hItem,bExpand?TVE_EXPAND:TVE_COLLAPSE);

        //展开/叠起结点

        hItem=GetChildItem(hItem);//获取第一个子结点

        do {

            ExpandBranch(hItem);

        } while(hItem=GetNextSiblingItem(hItem));//获取兄弟结点

    }

}

void CMyTreeCtrl::ExpandAllBranches(BOOL bExpand /* =TRUE */)

{

    HTREEITEM hItem=GetRootItem();//获取根结点,可能会有多个根结点

    do {

        ExpandBranch(hItem,bExpand);

    } while(hItem=GetNextSiblingItem(hItem));

    Select(hItem,TVGN_FIRSTVISIBLE);//设置选中结点

}

 

 

 

BOOL CMyTreeCtrl::DoesItemExist(HTREEITEM hItemParent,

                                CString const& strItem)

{

    BOOL bDoesItemExist=FALSE;

    ASSERT(strItem.GetLength());

 

    HTREEITEM hChild=GetChildItem(hItemParent?hItemParent:TVI_ROOT);

    while (NULL!=hChild&&!bDoesItemExist)

    {

        CString str=GetItemText(hChild);//获取结点字符串信息

        if (0==str.CompareNoCase(strItem))

        {

            bDoesItemExist=TRUE;

        }

        else

        {

            hChild=GetNextSiblingItem(hChild);

        }

    }

    return bDoesItemExist;

}

 

void CMyTreeCtrl::OnRButtonDown(UINT nFlags, CPoint point)

{

    // TODO: 在此添加消息处理程序代码和/或调用默认值   

    // set focus to the tree control

    SetFocus();

 

    // map the point that is passed to the

    // function from client coordinates

    // to screen coordinates

    ClientToScreen(&point);

 

    // Get the currently selected item

    HTREEITEM hCurrSel = GetSelectedItem();//获取当前选中结点

 

    // Figure out which item was right clicked

    CPoint pt(0, 0);

    ::GetCursorPos(&pt);

    ScreenToClient (&pt);

    HTREEITEM hNewSel = HitTest(pt, &nFlags);

 

    // Set the selection to the item that the

    // mouse was over when the user right

    // clicked

    if (NULL == hNewSel)

    {

        SelectItem(NULL);

    }

    else if (hCurrSel != hNewSel)

    {

        SelectItem(hNewSel);

        SetFocus();

    }

 

    // Load the context menu

    CMenu Menu;

    if (Menu.LoadMenu(IDM_CONTEXT_MENU))

    {

        CMenu* pSubMenu = Menu.GetSubMenu(0);

 

        if (pSubMenu!=NULL)

        {

            // Display the context menu

            pSubMenu->TrackPopupMenu(

                TPM_LEFTALIGN | TPM_RIGHTBUTTON,

                point.x, point.y, this);

        }

    }  

}

 

void CMyTreeCtrl::OnAddItem()

//添加上下文菜单

{

    // TODO: 在此添加命令处理程序代码

    HTREEITEM hItemParent=GetSelectedItem();

    //获取当前选中结点

 

    CAddItemDlg dlg;

    if (dlg.DoModal()==IDOK)

    {

        if (!DoesItemExist(hItemParent,dlg.m_strItemText))

        {

            HTREEITEM hItem=InsertItem(dlg.m_strItemText,hItemParent);

            //插入结点

            SelectItem(hItem);

        }

        else

        {

            AfxMessageBox("已存在相同结点");

        }

    }

   

}

 

BOOL CMyTreeCtrl::PreTranslateMessage(MSG* pMsg)

{

    // TODO: 在此添加专用代码和/或调用基类

    BOOL bHandledMsg = FALSE;

 

    switch (pMsg->message)

    {

        case WM_KEYDOWN:

        {

            switch (pMsg->wParam)

            {

            case VK_ESCAPE:

            case VK_RETURN:   

                if (::GetKeyState(VK_CONTROL) & 0x8000)

                {

                    break;

                }

 

                if (GetEditControl())

                {

                    ::TranslateMessage(pMsg);

                    ::DispatchMessage(pMsg);

                    bHandledMsg = TRUE;

                }

 

                break;

 

            default: break;

            } // switch (pMsg->wParam)

        } // WM_KEYDOWN

        break;

 

    default: break;

    } // switch (pMsg->message)                  

 

    // continue normal translation and dispatching             

    return (bHandledMsg ?TRUE : CTreeCtrl::PreTranslateMessage(pMsg));

 

}

void CMyTreeCtrl::OnTvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult)

{

    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast(pNMHDR);

    // TODO: 在此添加控件通知处理程序代码

    *pResult=1;

    CEdit*pEdit=GetEditControl();

    ASSERT(pEdit);

    if (pEdit)

    {

        pEdit->LimitText(15);

        *pResult=0;

    }  

}

void CMyTreeCtrl::OnTvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult)

{

    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast(pNMHDR);

    // TODO: 在此添加控件通知处理程序代码

 

    BOOL bValidItem=FALSE;

 

    CString strItem=pTVDispInfo->item.pszText;

    if (0

    {

        HTREEITEM hParent=GetParentItem(pTVDispInfo->item.hItem);

        bValidItem=!DoesItemExist(hParent,strItem);    

    }

    *pResult = bValidItem;

}

 

 

 

BOOL CMyTreeCtrl::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)

{

    LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR);

    // TODO: 在此添加控件通知处理程序代码

    TRACE(GetItemText(pNMTreeView->itemNew.hItem));

    TRACE("/n");

    *pResult = 0;

    return FALSE;       //返回FALSE可以让父窗口进行进一步的处理

}

 

 

你可能感兴趣的:(TreeCtrl的使用和一个CTreeCtrl的派生类)