Drag & Drop support with CTreeCtrl
Pete Silvestre -- psilvest@village.ios.com Thursday, January 25, 1996 I'm trying to add support for drag and drop between a Ctreectrl and a Clistctrl on the same window. Just to get my feet wet I took a look around on the both the MSDN & VC++ 4.0 CD's to see what samples were available. I only found one that used MFC, mfctree. It doesnt seem to operate correctly - I can drag a tree item but no image appears while it is being dragged and the code to do this seems to be present (it also required a minor change to compile under 4.0). I'm having the same problem when I try similar code in my app (ie: there is no drag image). Does anybody have or know where I can find a simple example of code like this. It could be for either the 95 tree or list control. FYI, this MFC 4.0, VC++ 4.0 under NT 3.51. TIA...
Mickey Williams -- 75460.2102@compuserve.com Sunday, January 28, 1996 Pete Silvestre wrote: > I'm trying to add support for drag and drop between a Ctreectrl and > a Clistctrl on the same window. > ... > Does anybody have or know where I can find > a simple example of code like this. It could be for either the 95 tree > or list control. FYI, this MFC 4.0, VC++ 4.0 under NT 3.51. TIA... The code for either is similar, but not identical, so I'll give you both - you would think that functions like GetImageRect would have the same signatures, but that's not the case. Anyway, merging the two is left as an excersize to the reader - hope this helps. --- Mickey ---------CTreeCtrl drag and drop ----------- // Handlers for TVN_BEGINDRAG, WM_MOUSEMOVE, and // WM_LBUTTONUP //The image list is 32 pixels wide, and image 3 is used for all the dragable items. // There are three member variables to handle dnd: // HTREEITEM m_hDragItem - the item being dragged // HTREEITEM m_hDragTarget - the item being dropped on // BOOL m_fIsDragging - TRUE if a drag is in progress void CTreeDispDlg::OnBegindragTree(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // In this tree, root nodes aren't allowed to move. if(m_tree.GetParentItem(pNMTreeView->itemNew.hItem) != NULL) { m_hDragItem = pNMTreeView->itemNew.hItem; CImageList* pDragImage; pDragImage = m_tree.CreateDragImage( m_hDragItem ); ASSERT( pDragImage ); // The next few lines calculate the position of the cursor rel to // the image. A crude bu simpler approach is to use CPoint(0,0) // as the cursor point in BeginDrag. CRect rcDrag; CPoint ptCursor; m_tree.GetItemRect( m_hDragItem, rcDrag, TRUE ); rcDrag.left -= 32; // Adjust by width of image GetCursorPos( &ptCursor ); m_tree.ScreenToClient( &ptCursor ); CPoint ptDrag( ptCursor - rcDrag.TopLeft() ); pDragImage->BeginDrag( 0, ptDrag ); pDragImage->DragEnter( &m_tree, pNMTreeView->ptDrag ); SetCapture(); m_fIsDragging = TRUE; } *pResult = 0; } void CTreeDispDlg::OnMouseMove(UINT nFlags, CPoint point) { if( m_fIsDragging == TRUE ) { CPoint ptTree(point); MapWindowPoints( &m_tree, &ptTree, 1 ); CImageList::DragMove( ptTree ); UINT uHitTest = TVHT_ONITEM; m_hDragTarget = m_tree.HitTest( ptTree, &uHitTest ); } CDialog::OnMouseMove(nFlags, point); } void CTreeDispDlg::OnLButtonUp(UINT nFlags, CPoint point) { if( m_fIsDragging == TRUE ) { CImageList::DragLeave( &m_tree ); CImageList::EndDrag(); ReleaseCapture(); m_fIsDragging = FALSE; // Test for valid drop target. if((m_hDragTarget != NULL)&&(m_hDragTarget != m_hDragItem)) { // Create a copy of the drag item. HTREEITEM hParent; hParent = m_tree.GetParentItem( m_hDragTarget ); CString szLabel = m_tree.GetItemText( m_hDragItem ); if( hParent != NULL ) m_tree.InsertItem( szLabel, 3, 3, hParent, m_hDragTarget ); else m_tree.InsertItem( szLabel, 3, 3, m_hDragTarget, TVI_FIRST ); // Remove the existing copy of the drag item. m_tree.DeleteItem( m_hDragItem ); } } else CDialog::OnLButtonUp(nFlags, point); } ---- A list view drag and drop ----------- // This list view uses image and text callbacks, so it isn't completely // interchangable with the tree-view. On the other hand, it does show // how the basic dnd works. // There are three member variables here also: // int m_nDragItem, m_nDragTarget; - the draggee and drop target // BOOL m_fIsDragging; - True if a drag is in progress void CTravelDlg::OnBegindragList(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; m_nDragItem = pNMListView->iItem; CImageList* pDragImage; pDragImage = m_listCtrl.CreateDragImage( m_nDragItem, &pNMListView->ptAction ); ASSERT( pDragImage ); CRect rcDrag; CPoint ptCursor; m_listCtrl.GetItemRect( m_nDragItem, rcDrag, LVIR_ICON ); GetCursorPos( &ptCursor ); m_listCtrl.ScreenToClient( &ptCursor ); CPoint ptDrag( ptCursor - rcDrag.TopLeft() ); pDragImage->BeginDrag( 0, ptDrag ); pDragImage->DragEnter( &m_listCtrl, pNMListView->ptAction ); SetCapture(); m_fIsDragging = TRUE; *pResult = 0; } void CTravelDlg::OnMouseMove(UINT nFlags, CPoint point) { if( m_fIsDragging == TRUE ) { CPoint ptList(point); MapWindowPoints( &m_listCtrl, &ptList, 1 ); CImageList::DragMove( ptList ); UINT uHitTest = LVHT_ONITEM; m_nDragTarget = m_listCtrl.HitTest( ptList, &uHitTest ); } CDialog::OnMouseMove(nFlags, point); } void CTravelDlg::OnLButtonUp(UINT nFlags, CPoint point) { if( m_fIsDragging == TRUE ) { CImageList::DragLeave( &m_listCtrl ); CImageList::EndDrag(); ReleaseCapture(); m_fIsDragging = FALSE; if((m_nDragTarget != -1)&&(m_nDragTarget != m_nDragItem)) { LV_ITEM theItem; theItem.iItem = m_nDragItem; theItem.iSubItem = 0; theItem.mask = LVIF_PARAM; VERIFY( m_listCtrl.GetItem( &theItem ) ); // Obviously, this section is different for other applications.... CHotel* pOldHotel = (CHotel*)theItem.lParam; ASSERT(pOldHotel); CHotel* pNewHotel = new CHotel(*pOldHotel); ASSERT(pNewHotel); theItem.iItem = m_nDragTarget; theItem.iImage = pNewHotel->m_nRank; theItem.mask |= (LVIF_TEXT | LVIF_IMAGE); theItem.pszText = LPSTR_TEXTCALLBACK; theItem.cchTextMax = 40; theItem.lParam = (LPARAM)pNewHotel; VERIFY( m_listCtrl.InsertItem(&theItem) != -1 ); m_listCtrl.SetItemText( m_nDragTarget, 1, LPSTR_TEXTCALLBACK ); m_listCtrl.SetItemText( m_nDragTarget, 2, LPSTR_TEXTCALLBACK ); if( m_nDragTarget < m_nDragItem ) m_nDragItem++; VERIFY( m_listCtrl.DeleteItem( m_nDragItem )); } } else CDialog::OnLButtonUp(nFlags, point); }
| Вернуться в корень Архива |