// MultiSelTree.cpp : implementation file // #include "stdafx.h" #include "MultiSelTree.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMultiSelTree CMultiSelTree::CMultiSelTree() { m_hItemFirstSel = NULL; m_bOnMouseSel = FALSE; } CMultiSelTree::~CMultiSelTree() { } BEGIN_MESSAGE_MAP(CMultiSelTree, CTreeCtrl) //{{AFX_MSG_MAP(CMultiSelTree) ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw) ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged) ON_WM_DESTROY() ON_WM_LBUTTONDOWN() ON_WM_RBUTTONDOWN() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMultiSelTree message handlers void CMultiSelTree::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* CMultiSelTree::GetSelectedItems() { return &m_listSels; } void CMultiSelTree::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 CMultiSelTree::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default m_bOnMouseSel = TRUE; CTreeCtrl::OnLButtonDown(nFlags, point); m_bOnMouseSel = FALSE; HTREEITEM hItem = HitTest(point); if(hItem) SelectItem(nFlags, hItem); } void CMultiSelTree::SelectItem(UINT nFlags, HTREEITEM hItem) { if(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 { m_listSels.RemoveAll(); m_listSels.SetAt((LPVOID)hItem, (LPVOID)1); m_hItemFirstSel = hItem; } m_hItemLastSel = hItem; Invalidate(); } } DWORD CMultiSelTree::GetItemData (HTREEITEM hItem) const { CTreeItemData* pData = (CTreeItemData*)CTreeCtrl::GetItemData(hItem); if(pData) { return pData->m_dwData; } return NULL; } BOOL CMultiSelTree::SetItemData (HTREEITEM hItem, DWORD dwData) { CTreeItemData* pData = (CTreeItemData*)CTreeCtrl::GetItemData(hItem); if(pData) { pData->m_dwData = dwData; } return pData != NULL; } HTREEITEM CMultiSelTree::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 CMultiSelTree::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 CMultiSelTree::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 CMultiSelTree::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 CMultiSelTree::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; CTreeItemData* pData = (CTreeItemData*)CTreeCtrl::GetItemData(hItem); if(pData) { delete pData; } return CTreeCtrl::DeleteItem(hItem); } BOOL CMultiSelTree::DeleteAllItems () { HTREEITEM hRoot = GetRootItem(); while(hRoot) { HTREEITEM hRootLast = hRoot; hRoot = GetNextSiblingItem(hRoot); DeleteItem(hRootLast); } return TRUE; } void CMultiSelTree::OnDestroy() { DeleteAllItems(); CTreeCtrl::OnDestroy(); // TODO: Add your message handler code here } void CMultiSelTree::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default 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(); } } m_bOnMouseSel = TRUE; CTreeCtrl::OnRButtonDown(nFlags, point); m_bOnMouseSel = FALSE; }