Treectrl de 用法

来源:互联网 发布:corethink php版本 编辑:程序博客网 时间:2024/04/29 10:45

1.树视图风格:

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

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

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

2.处理单击事件:TVN_SELCHANGED

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

{

      LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(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中处理以下消息,并返回FALSE就OK了ON_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.让树视图处理Esc和Enter键

重载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<LPNMTVDISPINFO>(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<LPNMTVDISPINFO>(pNMHDR);

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

      BOOL bValidItem=FALSE;

      CString strItem=pTVDispInfo->item.pszText;

      if (0<strItem.GetLength())

      {

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

          bValidItem=!DoesItemExist(hParent,strItem);    

      }

      *pResult = bValidItem;

}

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

{

      LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);

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

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

      TRACE("/n");

      *pResult = 0;

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

}