From fd54c1d33cf4d53c71f725484bf6963be0f1fd85 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 13 May 2015 00:09:14 +0000 Subject: - MTREE_DND implemented, all drag-n-drop operations in trees went into the core; - fixed chaos inside CCtrlBase::Subclass(); - two app dialogs switched to MTREE_DND; git-svn-id: http://svn.miranda-ng.org/main/trunk@13566 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/mir_core/src/ui_utils.cpp | 144 ++++++++++++++++++++++++++++++------ src/modules/clist/contacts.cpp | 85 +-------------------- src/modules/clist/protocolorder.cpp | 93 +---------------------- 3 files changed, 126 insertions(+), 196 deletions(-) (limited to 'src') diff --git a/src/mir_core/src/ui_utils.cpp b/src/mir_core/src/ui_utils.cpp index 700dd30f67..ce86fe1735 100644 --- a/src/mir_core/src/ui_utils.cpp +++ b/src/mir_core/src/ui_utils.cpp @@ -34,10 +34,10 @@ static int CompareDialogs(const CDlgBase *p1, const CDlgBase *p2) } static LIST arDialogs(10, CompareDialogs); -static int CompareDialogs(const CCtrlBase *p1, const CCtrlBase *p2) +static int CompareControls(const CCtrlBase *p1, const CCtrlBase *p2) { return (INT_PTR)p1->GetHwnd() - (INT_PTR)p2->GetHwnd(); } -static LIST arControls(10, PtrKeySortT); +static LIST arControls(10, CompareControls); #pragma comment(lib, "uxtheme") @@ -1382,31 +1382,131 @@ void CCtrlTreeView::SetFlags(uint32_t dwFlags) } } +void CCtrlTreeView::OnInit() +{ + CSuper::OnInit(); + + if (m_bDndEnabled) + Subclass(); +} + +LRESULT CCtrlTreeView::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam) +{ + TVHITTESTINFO hti; + + 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; + 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); + } + break; + + case WM_LBUTTONUP: + if (!m_bDragging) + 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) + 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(); + } + break; + } + + return CSuper::CustomWndProc(msg, wParam, lParam); +} + BOOL CCtrlTreeView::OnNotify(int, NMHDR *pnmh) { TEventInfo evt = { this, pnmh }; switch (pnmh->code) { - case TVN_BEGINDRAG: OnBeginDrag(&evt); return TRUE; - case TVN_BEGINLABELEDIT: OnBeginLabelEdit(&evt); return TRUE; - case TVN_BEGINRDRAG: OnBeginRDrag(&evt); return TRUE; - case TVN_DELETEITEM: OnDeleteItem(&evt); return TRUE; - case TVN_ENDLABELEDIT: OnEndLabelEdit(&evt); return TRUE; - case TVN_GETDISPINFO: OnGetDispInfo(&evt); return TRUE; - case TVN_GETINFOTIP: OnGetInfoTip(&evt); return TRUE; - case TVN_ITEMEXPANDED: OnItemExpanded(&evt); return TRUE; - case TVN_ITEMEXPANDING: OnItemExpanding(&evt); return TRUE; - case TVN_SELCHANGED: OnSelChanged(&evt); return TRUE; - case TVN_SELCHANGING: OnSelChanging(&evt); return TRUE; - case TVN_SETDISPINFO: OnSetDispInfo(&evt); return TRUE; - case TVN_SINGLEEXPAND: OnSingleExpand(&evt); return TRUE; - - case TVN_KEYDOWN: - if (m_bCheckBox && evt.nmtvkey->wVKey == VK_SPACE) - InvertCheck(GetSelection()); - - OnKeyDown(&evt); - return TRUE; + case TVN_BEGINLABELEDIT: OnBeginLabelEdit(&evt); return TRUE; + case TVN_BEGINRDRAG: OnBeginRDrag(&evt); return TRUE; + case TVN_DELETEITEM: OnDeleteItem(&evt); return TRUE; + case TVN_ENDLABELEDIT: OnEndLabelEdit(&evt); return TRUE; + case TVN_GETDISPINFO: OnGetDispInfo(&evt); return TRUE; + case TVN_GETINFOTIP: OnGetInfoTip(&evt); return TRUE; + case TVN_ITEMEXPANDED: OnItemExpanded(&evt); return TRUE; + case TVN_ITEMEXPANDING: OnItemExpanding(&evt); return TRUE; + case TVN_SELCHANGED: OnSelChanged(&evt); return TRUE; + case TVN_SELCHANGING: OnSelChanging(&evt); return TRUE; + case TVN_SETDISPINFO: OnSetDispInfo(&evt); return TRUE; + case TVN_SINGLEEXPAND: OnSingleExpand(&evt); return TRUE; + + case TVN_BEGINDRAG: + OnBeginDrag(&evt); + + // user-defined can clear the event code to disable dragging + if (m_bDndEnabled && pnmh->code) { + ::SetCapture(m_hwnd); + m_bDragging = true; + m_hDragItem = evt.nmtv->itemNew.hItem; + SelectItem(m_hDragItem); + } + return TRUE; + + case TVN_KEYDOWN: + if (m_bCheckBox && evt.nmtvkey->wVKey == VK_SPACE) + InvertCheck(GetSelection()); + + OnKeyDown(&evt); + return TRUE; } if (m_bCheckBox && pnmh->code == NM_CLICK) { diff --git a/src/modules/clist/contacts.cpp b/src/modules/clist/contacts.cpp index 204dc3221c..98e2669fe0 100644 --- a/src/modules/clist/contacts.cpp +++ b/src/modules/clist/contacts.cpp @@ -376,9 +376,6 @@ static INT_PTR GetContactInfo(WPARAM, LPARAM lParam) class CContactOptsDlg : public CDlgBase { - int dragging; - HTREEITEM hDragItem; - CCtrlTreeView m_nameOrder; public: @@ -386,13 +383,12 @@ public: CDlgBase(hInst, IDD_OPT_CONTACT), m_nameOrder(this, IDC_NAMEORDER) { - m_nameOrder.OnBeginDrag = Callback(this, &CContactOptsDlg::OnBeginDrag); + m_nameOrder.SetFlags(MTREE_DND); + m_nameOrder.OnBeginDrag = Callback(this, &CContactOptsDlg::OnBeginDrag); } virtual void OnInitDialog() { - dragging = 0; - TVINSERTSTRUCT tvis; tvis.hParent = NULL; tvis.hInsertAfter = TVI_LAST; @@ -423,82 +419,7 @@ public: { LPNMTREEVIEW pNotify = evt->nmtv; if (pNotify->itemNew.lParam == 0 || pNotify->itemNew.lParam == SIZEOF(nameOrderDescr) - 1) - return; - - SetCapture(m_hwnd); - dragging = 1; - hDragItem = pNotify->itemNew.hItem; - m_nameOrder.SelectItem(hDragItem); - } - - virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) - { - TVHITTESTINFO hti; - - switch (msg) { - case WM_MOUSEMOVE: - if (!dragging) - break; - - hti.pt.x = (short)LOWORD(lParam); - hti.pt.y = (short)HIWORD(lParam); - ClientToScreen(m_hwnd, &hti.pt); - ScreenToClient(m_nameOrder.GetHwnd(), &hti.pt); - m_nameOrder.HitTest(&hti); - if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) { - hti.pt.y -= m_nameOrder.GetItemHeight() / 2; - m_nameOrder.HitTest(&hti); - m_nameOrder.SetInsertMark(hti.hItem, 1); - } - else { - if (hti.flags & TVHT_ABOVE) m_nameOrder.SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0); - if (hti.flags & TVHT_BELOW) m_nameOrder.SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0); - m_nameOrder.SetInsertMark(NULL, 0); - } - break; - - case WM_LBUTTONUP: - if (!dragging) - break; - - m_nameOrder.SetInsertMark(NULL, 0); - dragging = 0; - ReleaseCapture(); - - hti.pt.x = (short)LOWORD(lParam); - hti.pt.y = (short)HIWORD(lParam); - ClientToScreen(m_hwnd, &hti.pt); - ScreenToClient(m_nameOrder.GetHwnd(), &hti.pt); - hti.pt.y -= m_nameOrder.GetItemHeight() / 2; - m_nameOrder.HitTest(&hti); - if (hDragItem == hti.hItem) - break; - - TVITEMEX tvi; - tvi.mask = TVIF_HANDLE | TVIF_PARAM; - tvi.hItem = hti.hItem; - m_nameOrder.GetItem(&tvi); - if (tvi.lParam == SIZEOF(nameOrderDescr) - 1) - break; - - if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) { - TCHAR name[128]; - TVINSERTSTRUCT tvis = { 0 }; - tvis.itemex.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT | TVIF_PARAM; - tvis.itemex.stateMask = 0xFFFFFFFF; - tvis.itemex.pszText = name; - tvis.itemex.cchTextMax = SIZEOF(name); - tvis.itemex.hItem = hDragItem; - m_nameOrder.GetItem(&tvis.itemex); - m_nameOrder.DeleteItem(hDragItem); - tvis.hParent = NULL; - tvis.hInsertAfter = hti.hItem; - m_nameOrder.SelectItem(m_nameOrder.InsertItem(&tvis)); - NotifyChange(); - } - break; - } - return CDlgBase::DlgProc(msg, wParam, lParam); + pNotify->hdr.code = 0; // deny dragging } }; diff --git a/src/modules/clist/protocolorder.cpp b/src/modules/clist/protocolorder.cpp index a454793de3..274ae0dce6 100644 --- a/src/modules/clist/protocolorder.cpp +++ b/src/modules/clist/protocolorder.cpp @@ -149,8 +149,7 @@ public: { m_btnReset.OnClick = Callback(this, &CProtocolOrderOpts::onReset_Click); - m_order.SetFlags(MTREE_CHECKBOX); - m_order.OnBeginDrag = Callback(this, &CProtocolOrderOpts::onOrder_BeginDrag); + m_order.SetFlags(MTREE_CHECKBOX | MTREE_DND); m_order.OnDeleteItem = Callback(this, &CProtocolOrderOpts::onOrder_DeleteItem); } @@ -216,96 +215,6 @@ public: if (pnmtv) mir_free((ProtocolData*)pnmtv->itemOld.lParam); } - - void onOrder_BeginDrag(CCtrlTreeView::TEventInfo *env) - { - SetCapture(m_hwnd); - m_bDragging = true; - m_hDragItem = env->nmtv->itemNew.hItem; - m_order.SelectItem(m_hDragItem); - } - - virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) - { - TVHITTESTINFO hti; - - switch (msg) { - case WM_MOUSEMOVE: - if (!m_bDragging) - break; - - hti.pt.x = (short)LOWORD(lParam); - hti.pt.y = (short)HIWORD(lParam); - ClientToScreen(m_hwnd, &hti.pt); - ScreenToClient(m_order.GetHwnd(), &hti.pt); - m_order.HitTest(&hti); - if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) { - HTREEITEM it = hti.hItem; - hti.pt.y -= m_order.GetItemHeight() / 2; - m_order.HitTest(&hti); - if (!(hti.flags & TVHT_ABOVE)) - m_order.SetInsertMark(hti.hItem, 1); - else - m_order.SetInsertMark(it, 0); - } - else { - if (hti.flags & TVHT_ABOVE) m_order.SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0); - if (hti.flags & TVHT_BELOW) m_order.SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0); - m_order.SetInsertMark(NULL, 0); - } - break; - - case WM_LBUTTONUP: - if (!m_bDragging) - break; - - m_order.SetInsertMark(NULL, 0); - m_bDragging = false; - ReleaseCapture(); - - hti.pt.x = (short)LOWORD(lParam); - hti.pt.y = (short)HIWORD(lParam); - ClientToScreen(m_hwnd, &hti.pt); - ScreenToClient(m_order.GetHwnd(), &hti.pt); - hti.pt.y -= m_order.GetItemHeight() / 2; - m_order.HitTest(&hti); - if (m_hDragItem == hti.hItem) - break; - if (hti.flags & TVHT_ABOVE) - hti.hItem = TVI_FIRST; - - TVITEMEX tvi; - tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_IMAGE; - tvi.hItem = m_hDragItem; - m_order.GetItem(&tvi); - if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT) || (hti.hItem == TVI_FIRST)) { - TCHAR name[128]; - TVINSERTSTRUCT tvis; - tvis.itemex.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT | 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; - m_order.GetItem(&tvis.itemex); - - // the pointed lParam will be freed inside TVN_DELETEITEM - // so lets substitute it with 0 - ProtocolData *lpOldData = (ProtocolData*)tvis.itemex.lParam; - tvis.itemex.lParam = 0; - m_order.SetItem(&tvis.itemex); - - // now current item contain lParam = 0 we can delete it. the memory will be kept. - tvis.itemex.lParam = (LPARAM)lpOldData; - m_order.DeleteItem(m_hDragItem); - tvis.hParent = NULL; - tvis.hInsertAfter = hti.hItem; - m_order.SelectItem(m_order.InsertItem(&tvis)); - NotifyChange(); - } - } - return CDlgBase::DlgProc(msg, wParam, lParam); - } }; int ProtocolOrderOptInit(WPARAM wParam, LPARAM) -- cgit v1.2.3