// DataNodeTree.cpp : implementation file // #include "stdafx.h" #include "DataManager.h" #include "DataNodeTree.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CDataNodeTree IMPLEMENT_DYNCREATE(CDataNodeTree, CTreeView)//CTreeCtrl) CDataNodeTree::CDataNodeTree() { m_pNode = NULL; } CDataNodeTree::~CDataNodeTree() { } BEGIN_MESSAGE_MAP(CDataNodeTree, CTreeView)//CTreeCtrl) //{{AFX_MSG_MAP(CDataNodeTree) ON_WM_CREATE() ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding) ON_WM_SHOWWINDOW() ON_WM_SIZE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDataNodeTree message handlers CDataNodeTreeCtrl& CDataNodeTree::GetTreeCtrl() { return m_tree; // return CTreeView::GetTreeCtrl(); } int CDataNodeTree::OnCreate(LPCREATESTRUCT lpCreateStruct) { // if (CTreeCtrl::OnCreate(lpCreateStruct) == -1) if (CTreeView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here // this->ModifyStyle(NULL, TVS_FULLROWSELECT|TVS_HASBUTTONS|TVS_HASLINES|TVS_INFOTIP|TVS_LINESATROOT|TVS_SHOWSELALWAYS); // if(!m_imageList.Create()) // return -1; // this->GetTreeCtrl().SetImageList(&m_imageList, TVSIL_NORMAL ); CRect rectWnd; CTreeView::GetTreeCtrl().GetWindowRect(&rectWnd); ScreenToClient(&rectWnd); // UINT uID = CTreeView::GetTreeCtrl().GetDlgCtrlID(); // BOOL bOK = m_tree.SubclassDlgItem(uID, this); // BOOL bOK = m_tree.SubclassWindow(m_hWnd); m_tree.Create(NULL, rectWnd, this, TREE_CONTROL_IN_VIEW); CTreeView::GetTreeCtrl().ShowWindow(SW_HIDE); m_tree.ShowWindow(SW_SHOW); // m_tree.Attach(CTreeView::GetTreeCtrl().Detach()); return 0; } void CDataNodeTree::SetDataNode(CDataNodeBase* pNode, BOOL bInitCtrl) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_tree.SetDataNode(pNode, bInitCtrl); // m_pNode = pNode; // if(bInitCtrl) // GetTreeCtrl().DeleteAllItems(); // //this->ModifyStyle(NULL, TVS_FULLROWSELECT|TVS_HASBUTTONS|TVS_HASLINES|TVS_INFOTIP|TVS_LINESATROOT|TVS_SHOWSELALWAYS); // if(m_imageList.m_hImageList == NULL) // { // m_imageList.Create(); // this->GetTreeCtrl().SetImageList(&m_imageList, TVSIL_NORMAL ); // } // m_pNode->BuildTree(*this, TVI_ROOT); } void CDataNodeTree::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // TODO: Add your control notification handler code here // CDataNodeBase* pNode = (CDataNodeBase*)GetTreeCtrl().GetItemData(pNMTreeView->itemNew.hItem); // pNode->BuildTree(*this, pNMTreeView->itemNew.hItem, MAX_DEPTH, TRUE); *pResult = 0; } void CDataNodeTree::OnShowWindow(BOOL bShow, UINT nStatus) { CTreeView::OnShowWindow(bShow, nStatus); // TODO: Add your message handler code here CTreeView::GetTreeCtrl().ShowWindow(SW_HIDE); // this->ModifyStyle(NULL, TVS_FULLROWSELECT|TVS_HASBUTTONS|TVS_HASLINES|TVS_INFOTIP|TVS_LINESATROOT|TVS_SHOWSELALWAYS); // if(m_imageList.m_hImageList == NULL) // { // m_imageList.Create(); // this->GetTreeCtrl().SetImageList(&m_imageList, TVSIL_NORMAL ); // } } void CDataNodeTree::OnSize(UINT nType, int cx, int cy) { CTreeView::OnSize(nType, cx, cy); // TODO: Add your message handler code here if(m_tree.m_hWnd) { CRect rectWnd; CTreeView::GetTreeCtrl().GetWindowRect(&rectWnd); ScreenToClient(&rectWnd); m_tree.MoveWindow(rectWnd); } } ////////////////////////////////////////////////////////////////////////// // CDataNodeTreeCtrl IMPLEMENT_DYNCREATE(CDataNodeTreeCtrl, CTreeCtrl) CDataNodeTreeCtrl::CDataNodeTreeCtrl() { m_pNode = NULL; m_hItemFirstSel = NULL; m_bOnMouseSel = FALSE; } CDataNodeTreeCtrl::~CDataNodeTreeCtrl() { } BEGIN_MESSAGE_MAP(CDataNodeTreeCtrl, CTreeCtrl) //{{AFX_MSG_MAP(CDataNodeTreeCtrl) ON_WM_CREATE() ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding) ON_WM_SHOWWINDOW() ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged) ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw) ON_WM_DESTROY() ON_WM_LBUTTONDOWN() ON_WM_KEYDOWN() ON_WM_RBUTTONDOWN() ON_WM_LBUTTONUP() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDataNodeTreeCtrl message handlers int CDataNodeTreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CTreeCtrl::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here AFX_MANAGE_STATE(AfxGetStaticModuleState()); this->ModifyStyle(NULL, TVS_FULLROWSELECT|TVS_HASBUTTONS|TVS_HASLINES|TVS_INFOTIP|TVS_LINESATROOT|TVS_SHOWSELALWAYS); if(!m_imageList.Create()) return -1; m_imageList.GetImage("ProjectN"); m_imageList.GetImage("ProjectA"); m_nPauseMaskImage = m_imageList.GetImage("PauseMask"); BOOL bOK = m_imageList.SetOverlayImage(0, 1); m_nPauseMaskImage = INDEXTOOVERLAYMASK(1); this->SetImageList(&m_imageList, TVSIL_NORMAL ); return 0; } void CDataNodeTreeCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) { //draw each item.set txt color,bkcolor.... NMTVCUSTOMDRAW* pTVCD = (NMTVCUSTOMDRAW*)(pNMHDR); // Take the default processing unless we set this to something else below. *pResult = CDRF_DODEFAULT; // First thing - check the draw stage. If it's the control's prepaint // stage, then tell Windows we want messages for every item. switch(pTVCD->nmcd.dwDrawStage) { case CDDS_PREPAINT: *pResult = CDRF_NOTIFYITEMDRAW; break; case CDDS_ITEMPREPAINT: { CTreeItemData* p = (CTreeItemData*)pTVCD->nmcd.lItemlParam; int nTemp; if(p && m_listSels.Lookup((LPVOID)p->m_hItem, (void*&)nTemp)) { pTVCD->clrTextBk = GetSysColor(COLOR_HIGHLIGHT); pTVCD->clrText = GetSysColor(COLOR_HIGHLIGHTTEXT); } else { pTVCD->clrTextBk = GetSysColor(COLOR_WINDOW); pTVCD->clrText = GetSysColor(COLOR_WINDOWTEXT); } } *pResult = CDRF_NEWFONT; break; default: break; } } CMapPtrToPtr* CDataNodeTreeCtrl::GetSelectedItems() { return &m_listSels; } void CDataNodeTreeCtrl::SetDataNode(CDataNodeBase* pNode, BOOL bInitCtrl) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_pNode = pNode; if(bInitCtrl) DeleteAllItems(); //this->ModifyStyle(NULL, TVS_FULLROWSELECT|TVS_HASBUTTONS|TVS_HASLINES|TVS_INFOTIP|TVS_LINESATROOT|TVS_SHOWSELALWAYS); if(m_imageList.m_hImageList == NULL) { m_imageList.Create(); this->SetImageList(&m_imageList, TVSIL_NORMAL ); } m_pNode->BuildTree(*this, TVI_ROOT); } void CDataNodeTreeCtrl::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // TODO: Add your control notification handler code here // CDataNodeBase* pNode = (CDataNodeBase*)GetTreeCtrl().GetItemData(pNMTreeView->itemNew.hItem); // pNode->BuildTree(*this, pNMTreeView->itemNew.hItem, MAX_DEPTH, TRUE); *pResult = 0; } void CDataNodeTreeCtrl::OnShowWindow(BOOL bShow, UINT nStatus) { CTreeCtrl::OnShowWindow(bShow, nStatus); // TODO: Add your message handler code here this->ModifyStyle(NULL, TVS_FULLROWSELECT|TVS_HASBUTTONS|TVS_HASLINES|TVS_INFOTIP|TVS_LINESATROOT|TVS_SHOWSELALWAYS); if(m_imageList.m_hImageList == NULL) { m_imageList.Create(); this->GetTreeCtrl().SetImageList(&m_imageList, TVSIL_NORMAL ); } } CDataNodeTreeCtrl& CDataNodeTreeCtrl::GetTreeCtrl() { return *this; } void CDataNodeTreeCtrl::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // TODO: Add your control notification handler code here if(!m_bOnMouseSel) { BOOL bShit = (0x80 & GetKeyState(VK_SHIFT)); BOOL bCtrl = (0x80 & GetKeyState(VK_CONTROL)); UINT nFlags = 0; if(bShit) nFlags |= MK_SHIFT; if(bCtrl) nFlags |= MK_CONTROL; SelectItem(nFlags, pNMTreeView->itemNew.hItem); } *pResult = 0; } void CDataNodeTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default m_bOnMouseSel = TRUE; CTreeCtrl::OnLButtonDown(nFlags, point); HTREEITEM hItem = HitTest(point); if(hItem) SelectItem(nFlags, hItem); m_bOnMouseSel = FALSE; this->GetParent()->SendMessage(WM_OPERATION, (LPARAM)this, WM_LBUTTONDOWN); } void CDataNodeTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default // HTREEITEM hItem = GetTreeCtrl().GetSelectedItem(); // if(hItem) // { // m_listSels.RemoveAll(); // m_listSels.SetAt((LPVOID)hItem, (LPVOID)1); // m_hItemFirstSel = hItem; // } // m_hItemLastSel = hItem; // Invalidate(); CTreeCtrl::OnLButtonUp(nFlags, point); } void CDataNodeTreeCtrl::SelectItem(UINT nFlags, HTREEITEM hItem) { if(hItem) { CTreeCtrl::SelectItem(hItem); if(nFlags & MK_CONTROL) { int nTemp; if(m_listSels.Lookup((LPVOID)hItem, (void*&)nTemp)) { m_listSels.RemoveKey((LPVOID)hItem); } else { m_listSels.SetAt((LPVOID)hItem, (LPVOID)1); m_hItemFirstSel = hItem; } } else if(nFlags & MK_SHIFT) { HTREEITEM hDelStart = NULL; HTREEITEM hDelEnd = NULL; HTREEITEM hAddStart = NULL; HTREEITEM hAddEnd = NULL; HTREEITEM hItemFind = GetRootItem(); while (hItemFind) { if(hItemFind == m_hItemLastSel || hItemFind == hItem) { if(hDelStart == NULL) { hDelStart = hItemFind; } if(hDelStart != NULL) { hDelEnd = hItemFind; } } if(hItemFind == m_hItemFirstSel || hItemFind == hItem) { if(hAddStart == NULL) { hAddStart = hItemFind; } if(hAddStart != NULL) { hAddEnd = hItemFind; } } hItemFind = GetNextVisibleItem(hItemFind); } if(hDelStart != NULL && hDelEnd != NULL) { HTREEITEM hDel = hDelStart; while (hDel) { m_listSels.RemoveKey((LPVOID)hDel); if(hDel == hDelEnd) break; hDel = GetNextVisibleItem(hDel); } } if(hAddStart != NULL && hAddEnd != NULL) { HTREEITEM hAdd = hAddStart; while (hAdd) { m_listSels.SetAt((LPVOID)hAdd, (LPVOID)1); if(hAdd == hAddEnd) break; hAdd = GetNextVisibleItem(hAdd); } } } else { //int nTemp;不支持拖动操作,故这个条件限制先屏蔽 //if(!m_listSels.Lookup((LPVOID)hItem, (void*&)nTemp)) //{//当前点中的不是原来已经选中的情况才做重选操作 m_listSels.RemoveAll(); m_listSels.SetAt((LPVOID)hItem, (LPVOID)1); m_hItemFirstSel = hItem; //} } m_hItemLastSel = hItem; // if(this->GetChildItem(hItem) == NULL) // { // CDataNodeBase* pNode = (CDataNodeBase*)GetTreeCtrl().GetItemData(hItem); // pNode->BuildTree(*this, hItem, MAX_DEPTH, TRUE); // } Invalidate(); this->GetParent()->PostMessage(WM_SELCHANGED, (LPARAM)this, NULL); } } DWORD CDataNodeTreeCtrl::GetItemData (HTREEITEM hItem) const { CTreeItemData* pData = (CTreeItemData*)CTreeCtrl::GetItemData(hItem); if(pData) { return pData->m_dwData; } return NULL; } BOOL CDataNodeTreeCtrl::SetItemData (HTREEITEM hItem, DWORD dwData) { CTreeItemData* pData = (CTreeItemData*)CTreeCtrl::GetItemData(hItem); if(pData) { pData->m_dwData = dwData; } return pData != NULL; } HTREEITEM CDataNodeTreeCtrl::InsertItem( LPTVINSERTSTRUCT lpInsertStruct ) { HTREEITEM hItem = CTreeCtrl::InsertItem(lpInsertStruct); if(hItem) { CTreeItemData* p = new CTreeItemData; p->m_hItem = hItem; p->m_dwData = (DWORD)lpInsertStruct->item.lParam; CTreeCtrl::SetItemData(hItem, (DWORD)p); } return hItem; } HTREEITEM CDataNodeTreeCtrl::InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam, HTREEITEM hParent, HTREEITEM hInsertAfter ) { HTREEITEM hItem = CTreeCtrl::InsertItem(nMask, lpszItem, nImage, nSelectedImage, nState, nStateMask, lParam, hParent, hInsertAfter); if(hItem) { CTreeItemData* p = new CTreeItemData; p->m_hItem = hItem; p->m_dwData = (DWORD)lParam; CTreeCtrl::SetItemData(hItem, (DWORD)p); } return hItem; } HTREEITEM CDataNodeTreeCtrl::InsertItem( LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter ) { HTREEITEM hItem = CTreeCtrl::InsertItem(lpszItem, hParent, hInsertAfter); if(hItem) { CTreeItemData* p = new CTreeItemData; p->m_hItem = hItem; CTreeCtrl::SetItemData(hItem, (DWORD)p); } return hItem; } HTREEITEM CDataNodeTreeCtrl::InsertItem( LPCTSTR lpszItem, int nImage, int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter) { HTREEITEM hItem = CTreeCtrl::InsertItem(lpszItem, nImage, nSelectedImage, hParent, hInsertAfter); if(hItem) { CTreeItemData* p = new CTreeItemData; p->m_hItem = hItem; CTreeCtrl::SetItemData(hItem, (DWORD)p); } return hItem; } BOOL CDataNodeTreeCtrl::DeleteItem (HTREEITEM hItem) { HTREEITEM hSub = GetChildItem(hItem); while (hSub) { HTREEITEM hSubLast = hSub; hSub = GetNextSiblingItem(hSub); DeleteItem(hSubLast); } if(m_hItemFirstSel == hItem) m_hItemFirstSel = NULL; if(m_hItemLastSel == hItem) m_hItemLastSel = NULL; m_listSels.RemoveKey(hItem); CTreeItemData* pData = (CTreeItemData*)CTreeCtrl::GetItemData(hItem); if(pData) { m_mapNodeTohItem.RemoveKey((LPVOID)pData->m_dwData); delete pData; } BOOL bRtn = CTreeCtrl::DeleteItem(hItem); if(m_listSels.GetCount() == 0) {//删除节点时,若自己管理的选择已经没有被选中的项,则重新选择 HTREEITEM hSel = CTreeCtrl::GetSelectedItem(); if(hSel) { m_listSels.SetAt((LPVOID)hSel, (LPVOID)1); m_hItemFirstSel = hSel; } } return bRtn; } BOOL CDataNodeTreeCtrl::DeleteAllItems () { HTREEITEM hRoot = GetRootItem(); while(hRoot) { HTREEITEM hRootLast = hRoot; hRoot = GetNextSiblingItem(hRoot); DeleteItem(hRootLast); } return TRUE; } void CDataNodeTreeCtrl::OnDestroy() { DeleteAllItems(); if(m_imageList.m_hImageList != NULL) { m_imageList.DeleteImageList(); } CTreeCtrl::OnDestroy(); // TODO: Add your message handler code here } BOOL CDataNodeTreeCtrl::SelectItem(HTREEITEM hItem) { BOOL bRtn = CTreeCtrl::SelectItem(hItem); SelectItem(NULL, hItem); return bRtn; } void CDataNodeTreeCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default CTreeCtrl::OnKeyDown(nChar, nRepCnt, nFlags); if(nChar == VK_UP || nChar == VK_DOWN || nChar == VK_LEFT || nChar == VK_RIGHT) { HTREEITEM hItem = CTreeCtrl::GetSelectedItem(); if(hItem) { BOOL bShit = (0x80 & GetKeyState(VK_SHIFT)); BOOL bCtrl = (0x80 & GetKeyState(VK_CONTROL)); nFlags = 0; if(bShit) nFlags |= MK_SHIFT; if(bCtrl) nFlags |= MK_CONTROL; SelectItem(nFlags, hItem); } } } void CDataNodeTreeCtrl::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default m_bOnMouseSel = TRUE; HTREEITEM hItem = HitTest(point, NULL); if(hItem != NULL) { CTreeCtrl::SelectItem(hItem); int nTemp; if(m_listSels.Lookup((LPVOID)hItem, (void*&)nTemp)) {//do nothing else } else { m_listSels.RemoveAll(); m_listSels.SetAt((LPVOID)hItem, (LPVOID)1); Invalidate(); } } CTreeCtrl::OnRButtonDown(nFlags, point); m_bOnMouseSel = FALSE; } HTREEITEM CDataNodeTreeCtrl::GetSelectedItem () const { HTREEITEM hRtn = CTreeCtrl::GetSelectedItem(); if(m_listSels.GetCount() == 1) { int nTemp; POSITION pos = m_listSels.GetStartPosition(); if(pos) m_listSels.GetNextAssoc(pos, (void*&)hRtn, (void*&)nTemp); } else if(m_listSels.GetCount() == 0) { } return hRtn; } void CDataNodeTreeCtrl::ChangePauseDeviceIco(HTREEITEM hItem, BOOL bPause) { int nStatus = 0; if(bPause) nStatus = m_nPauseMaskImage; SetItemState(hItem, nStatus, TVIS_OVERLAYMASK); }