From c13c0b52d24fa6d2c82287aa418f5daaf0fb099b Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 14 May 2015 14:04:35 +0000 Subject: multiselect mode for CCtrlTreeView git-svn-id: http://svn.miranda-ng.org/main/trunk@13586 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/mir_core/src/mir_core.def | 11 ++ src/mir_core/src/mir_core64.def | 11 ++ src/mir_core/src/ui_utils.cpp | 286 ++++++++++++++++++++++++++++++++-------- 3 files changed, 250 insertions(+), 58 deletions(-) (limited to 'src/mir_core') diff --git a/src/mir_core/src/mir_core.def b/src/mir_core/src/mir_core.def index 058d980505..d59ce8407b 100644 --- a/src/mir_core/src/mir_core.def +++ b/src/mir_core/src/mir_core.def @@ -1079,3 +1079,14 @@ Proto_RegisterModule @1074 NONAME ?SetFlags@CCtrlTreeView@@QAEXI@Z @1080 NONAME ?CustomWndProc@CCtrlTreeView@@MAEJIIJ@Z @1081 NONAME ?OnInit@CCtrlTreeView@@MAEXXZ @1082 NONAME +?DropHilite@CCtrlTreeView@@QAEXPAU_TREEITEM@@@Z @1083 NONAME +?DropUnhilite@CCtrlTreeView@@QAEXPAU_TREEITEM@@@Z @1084 NONAME +?GetNumSelected@CCtrlTreeView@@QAEHXZ @1085 NONAME +?GetSelected@CCtrlTreeView@@QAEXAAU?$LIST@U_TREEITEM@@@@@Z @1086 NONAME +?IsSelected@CCtrlTreeView@@QAE_NPAU_TREEITEM@@@Z @1087 NONAME +?Select@CCtrlTreeView@@QAEXAAU?$LIST@U_TREEITEM@@@@@Z @1088 NONAME +?Select@CCtrlTreeView@@QAEXPAU_TREEITEM@@@Z @1089 NONAME +?SelectAll@CCtrlTreeView@@QAEXXZ @1090 NONAME +?SelectRange@CCtrlTreeView@@QAEXPAU_TREEITEM@@0@Z @1091 NONAME +?Unselect@CCtrlTreeView@@QAEXPAU_TREEITEM@@@Z @1092 NONAME +?UnselectAll@CCtrlTreeView@@QAEXXZ @1093 NONAME diff --git a/src/mir_core/src/mir_core64.def b/src/mir_core/src/mir_core64.def index 0efcff15f5..67bbf17e90 100644 --- a/src/mir_core/src/mir_core64.def +++ b/src/mir_core/src/mir_core64.def @@ -1079,3 +1079,14 @@ Proto_RegisterModule @1074 NONAME ?SetFlags@CCtrlTreeView@@QEAAXI@Z @1080 NONAME ?CustomWndProc@CCtrlTreeView@@MEAA_JI_K_J@Z @1081 NONAME ?OnInit@CCtrlTreeView@@MEAAXXZ @1082 NONAME +?DropHilite@CCtrlTreeView@@QEAAXPEAU_TREEITEM@@@Z @1083 NONAME +?DropUnhilite@CCtrlTreeView@@QEAAXPEAU_TREEITEM@@@Z @1084 NONAME +?GetNumSelected@CCtrlTreeView@@QEAAHXZ @1085 NONAME +?GetSelected@CCtrlTreeView@@QEAAXAEAU?$LIST@U_TREEITEM@@@@@Z @1086 NONAME +?IsSelected@CCtrlTreeView@@QEAA_NPEAU_TREEITEM@@@Z @1087 NONAME +?Select@CCtrlTreeView@@QEAAXAEAU?$LIST@U_TREEITEM@@@@@Z @1088 NONAME +?Select@CCtrlTreeView@@QEAAXPEAU_TREEITEM@@@Z @1089 NONAME +?SelectAll@CCtrlTreeView@@QEAAXXZ @1090 NONAME +?SelectRange@CCtrlTreeView@@QEAAXPEAU_TREEITEM@@0@Z @1091 NONAME +?Unselect@CCtrlTreeView@@QEAAXPEAU_TREEITEM@@@Z @1092 NONAME +?UnselectAll@CCtrlTreeView@@QEAAXXZ @1093 NONAME diff --git a/src/mir_core/src/ui_utils.cpp b/src/mir_core/src/ui_utils.cpp index 99124df0d0..d045182de1 100644 --- a/src/mir_core/src/ui_utils.cpp +++ b/src/mir_core/src/ui_utils.cpp @@ -1375,6 +1375,9 @@ void CCtrlTreeView::SetFlags(uint32_t dwFlags) if (dwFlags & MTREE_CHECKBOX) m_bCheckBox = true; + if (dwFlags & MTREE_MULTISELECT) + m_bMultiSelect = true; + if (dwFlags & MTREE_DND) { m_bDndEnabled = true; m_bDragging = false; @@ -1396,76 +1399,132 @@ LRESULT CCtrlTreeView::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam) switch (msg) { case WM_MOUSEMOVE: - if (!m_bDragging) - break; - - hti.pt.x = (short)LOWORD(lParam); - hti.pt.y = (short)HIWORD(lParam); - HitTest(&hti); - if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) { - HTREEITEM it = hti.hItem; - hti.pt.y -= GetItemHeight() / 2; + if (m_bDragging) { + hti.pt.x = (short)LOWORD(lParam); + hti.pt.y = (short)HIWORD(lParam); HitTest(&hti); - if (!(hti.flags & TVHT_ABOVE)) - SetInsertMark(hti.hItem, 1); - else - SetInsertMark(it, 0); + if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) { + HTREEITEM it = hti.hItem; + hti.pt.y -= GetItemHeight() / 2; + HitTest(&hti); + if (!(hti.flags & TVHT_ABOVE)) + SetInsertMark(hti.hItem, 1); + else + SetInsertMark(it, 0); + } + else { + if (hti.flags & TVHT_ABOVE) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0); + if (hti.flags & TVHT_BELOW) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0); + SetInsertMark(NULL, 0); + } } - else { - if (hti.flags & TVHT_ABOVE) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0); - if (hti.flags & TVHT_BELOW) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0); + break; + + case WM_LBUTTONUP: + if (m_bDragging) { SetInsertMark(NULL, 0); + m_bDragging = 0; + ReleaseCapture(); + + hti.pt.x = (short)LOWORD(lParam); + hti.pt.y = (short)HIWORD(lParam) - GetItemHeight() / 2; + HitTest(&hti); + if (m_hDragItem == hti.hItem) + break; + + if (hti.flags & TVHT_ABOVE) + hti.hItem = TVI_FIRST; + else if (hti.flags & TVHT_BELOW) + hti.hItem = TVI_LAST; + + TVITEMEX tvi; + tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_IMAGE; + tvi.hItem = m_hDragItem; + GetItem(&tvi); + if ((hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) || hti.hItem == TVI_FIRST) { + TCHAR name[128]; + TVINSERTSTRUCT tvis = { 0 }; + tvis.itemex.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvis.itemex.stateMask = 0xFFFFFFFF; + tvis.itemex.pszText = name; + tvis.itemex.cchTextMax = SIZEOF(name); + tvis.itemex.hItem = m_hDragItem; + tvis.itemex.iImage = tvis.itemex.iSelectedImage = tvi.iImage; + GetItem(&tvis.itemex); + + // the pointed lParam will be freed inside TVN_DELETEITEM + // so lets substitute it with 0 + LPARAM saveOldData = tvis.itemex.lParam; + tvis.itemex.lParam = 0; + SetItem(&tvis.itemex); + + // now current item contain lParam = 0 we can delete it. the memory will be kept. + tvis.itemex.lParam = saveOldData; + DeleteItem(m_hDragItem); + + tvis.hParent = NULL; + tvis.hInsertAfter = hti.hItem; + SelectItem(InsertItem(&tvis)); + + NotifyChange(); + } } break; - case WM_LBUTTONUP: - if (!m_bDragging) + case WM_LBUTTONDOWN: + if (!m_bMultiSelect) break; - SetInsertMark(NULL, 0); - m_bDragging = 0; - ReleaseCapture(); - hti.pt.x = (short)LOWORD(lParam); - hti.pt.y = (short)HIWORD(lParam) - GetItemHeight() / 2; - HitTest(&hti); - if (m_hDragItem == hti.hItem) + hti.pt.y = (short)HIWORD(lParam); + if (!TreeView_HitTest(m_hwnd, &hti)) { + UnselectAll(); break; - if (hti.flags & TVHT_ABOVE) - hti.hItem = TVI_FIRST; + } - TVITEMEX tvi; - tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_IMAGE; - tvi.hItem = m_hDragItem; - GetItem(&tvi); - if ((hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) || hti.hItem == TVI_FIRST) { - TCHAR name[128]; - TVINSERTSTRUCT tvis = { 0 }; - tvis.itemex.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; - tvis.itemex.stateMask = 0xFFFFFFFF; - tvis.itemex.pszText = name; - tvis.itemex.cchTextMax = SIZEOF(name); - tvis.itemex.hItem = m_hDragItem; - tvis.itemex.iImage = tvis.itemex.iSelectedImage = tvi.iImage; - GetItem(&tvis.itemex); - - // the pointed lParam will be freed inside TVN_DELETEITEM - // so lets substitute it with 0 - LPARAM saveOldData = tvis.itemex.lParam; - tvis.itemex.lParam = 0; - SetItem(&tvis.itemex); - - // now current item contain lParam = 0 we can delete it. the memory will be kept. - tvis.itemex.lParam = saveOldData; - DeleteItem(m_hDragItem); - - tvis.hParent = NULL; - tvis.hInsertAfter = hti.hItem; - SelectItem(InsertItem(&tvis)); - - NotifyChange(); + if (!(wParam & (MK_CONTROL | MK_SHIFT)) || !(hti.flags & (TVHT_ONITEMICON | TVHT_ONITEMLABEL | TVHT_ONITEMRIGHT))) { + UnselectAll(); + TreeView_SelectItem(m_hwnd, hti.hItem); + break; } - break; + + if (wParam & MK_CONTROL) { + LIST<_TREEITEM> selected(1); + GetSelected(selected); + + // Check if have to deselect it + for (int i = 0; i < selected.getCount(); i++) { + if (selected[i] == hti.hItem) { + // Deselect it + UnselectAll(); + selected.remove(i); + + if (i > 0) + hti.hItem = selected[0]; + else if (i < selected.getCount()) + hti.hItem = selected[i]; + else + hti.hItem = NULL; + break; + } + } + + TreeView_SelectItem(m_hwnd, hti.hItem); + Select(selected); + } + else if (wParam & MK_SHIFT) { + HTREEITEM hItem = TreeView_GetSelection(m_hwnd); + if (hItem == NULL) + break; + + LIST<_TREEITEM> selected(1); + GetSelected(selected); + + TreeView_SelectItem(m_hwnd, hti.hItem); + Select(selected); + SelectRange(hItem, hti.hItem); + } + return 0; } return CSuper::CustomWndProc(msg, wParam, lParam); @@ -1615,6 +1674,117 @@ void CCtrlTreeView::GetItem(HTREEITEM hItem, TVITEMEX *tvi, TCHAR *szText, int i GetItem(tvi); } +bool CCtrlTreeView::IsSelected(HTREEITEM hItem) +{ + return (TVIS_SELECTED & TreeView_GetItemState(m_hwnd, hItem, TVIS_SELECTED)) == TVIS_SELECTED; +} + +void CCtrlTreeView::Select(HTREEITEM hItem) +{ + TreeView_SetItemState(m_hwnd, hItem, TVIS_SELECTED, TVIS_SELECTED); +} + +void CCtrlTreeView::Unselect(HTREEITEM hItem) +{ + TreeView_SetItemState(m_hwnd, hItem, 0, TVIS_SELECTED); +} + +void CCtrlTreeView::DropHilite(HTREEITEM hItem) +{ + TreeView_SetItemState(m_hwnd, hItem, TVIS_DROPHILITED, TVIS_DROPHILITED); +} + +void CCtrlTreeView::DropUnhilite(HTREEITEM hItem) +{ + TreeView_SetItemState(m_hwnd, hItem, 0, TVIS_DROPHILITED); +} + +void CCtrlTreeView::SelectAll() +{ + TreeView_SelectItem(m_hwnd, NULL); + + HTREEITEM hItem = TreeView_GetRoot(m_hwnd); + while (hItem) { + Select(hItem); + hItem = TreeView_GetNextSibling(m_hwnd, hItem); + } +} + +void CCtrlTreeView::UnselectAll() +{ + TreeView_SelectItem(m_hwnd, NULL); + + HTREEITEM hItem = TreeView_GetRoot(m_hwnd); + while (hItem) { + Unselect(hItem); + hItem = TreeView_GetNextSibling(m_hwnd, hItem); + } +} + +void CCtrlTreeView::SelectRange(HTREEITEM hStart, HTREEITEM hEnd) +{ + int start = 0; + int end = 0; + int i = 0; + HTREEITEM hItem = TreeView_GetRoot(m_hwnd); + while (hItem) { + if (hItem == hStart) + start = i; + if (hItem == hEnd) + end = i; + + i++; + hItem = TreeView_GetNextSibling(m_hwnd, hItem); + } + + if (end < start) { + int tmp = start; + start = end; + end = tmp; + } + + i = 0; + hItem = TreeView_GetRoot(m_hwnd); + while (hItem) { + if (i >= start) + Select(hItem); + if (i == end) + break; + + i++; + hItem = TreeView_GetNextSibling(m_hwnd, hItem); + } +} + +int CCtrlTreeView::GetNumSelected() +{ + int ret = 0; + for (HTREEITEM hItem = TreeView_GetRoot(m_hwnd); hItem; hItem = TreeView_GetNextSibling(m_hwnd, hItem)) + if (IsSelected(hItem)) + ret++; + + return ret; +} + +void CCtrlTreeView::GetSelected(LIST<_TREEITEM> &selected) +{ + HTREEITEM hItem = TreeView_GetRoot(m_hwnd); + while (hItem) { + if (IsSelected(hItem)) + selected.insert(hItem); + hItem = TreeView_GetNextSibling(m_hwnd, hItem); + } +} + +void CCtrlTreeView::Select(LIST<_TREEITEM> &selected) +{ + for (int i = 0; i < selected.getCount(); i++) + if (selected[i] != NULL) + Select(selected[i]); +} + +///////////////////////////////////////////////////////////////////////////////////////// + HIMAGELIST CCtrlTreeView::CreateDragImage(HTREEITEM hItem) { return TreeView_CreateDragImage(m_hwnd, hItem); } -- cgit v1.2.3