Drag/drop from one tree control to another?
Matthias Bohlen -- MATTES@logotec.com Monday, August 19, 1996 Environment: VC++ 4.0, NT 3.51 Hello, in the sample project CMNCTRLS, I have seen how to program drag and drop inside a CTreeCtrl. That was ugly. To make my life even more complicated, I'd like to know how to drag'n'drop from a CTreeCtrl into something else, maybe another CTreeCtrl, maybe an edit control, maybe even another application (OLE?). Does anyone know how to do it? Matthias o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o The ZEN master: "If you have a stick, I'll give you a stick. If you have not, I'll take that stick away from you". The banker: "If you have money, I'll give you money. If you have not, I'll take that money away from you". ----------------------------+-------------------------- Matthias Bohlen | Logotec Software GmbH Phone: +49 228 64 80 520 | Chateauneufstr. 10 FAX: +49 228 64 80 525 | D-53347 Alfter, Germany | http://www.logotec.com/ E-mail: mattes@logotec.com | CAD systems development ----------------------------+--------------------------
Dave Frederick -- sasdrf@unx.sas.com Tuesday, August 20, 1996 [Mini-digest: 6 responses] > From: Matthias Bohlen> To: mfc-l@netcom.com > Subject: Drag/drop from one tree control to another? > Date: Monday, August 19, 1996 4:58 AM > > Environment: VC++ 4.0, NT 3.51 > > Hello, > > in the sample project CMNCTRLS, I have seen how to program drag and drop > inside a CTreeCtrl. That was ugly. To make my life even more complicated, > I'd like to know how to drag'n'drop from a CTreeCtrl into something else, > maybe another CTreeCtrl, maybe an edit control, maybe even another > application (OLE?). > > Does anyone know how to do it? > > Matthias There's a sample of OLE drag and drop using the common controls (CListCtrl, but it should be easy to extrapolate to CTreeCtrl) on the MS Web Site. Look in the knowledge base for Q152092 to find the sample code. Good Luck! -- Dave Frederick SAS Institute, Inc. Sr. Systems Developer SAS Campus Drive Compilers and Tools Div. Cary, NC 27513 sasdrf@unx.sas.com (919) 677-8000 x7049 -----From: "(Bobby)Babak Lashkari" I drag and drop from a CTreeView derived class into a CView derived I don't know if it will work for CTreeCtrl or not this is how I do it. Hope it'll help void COldTreeView::OnTreeBegindrag(NMHDR* pNMHDR, LRESULT* pResult) { *pResult = 0; NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; SetCapture(); if(this == CWnd::GetCapture()) m_draging = TRUE; ::SetCursor(DragWndCursor); } void COldTreeView::OnMouseMove(UINT nFlags, CPoint point) { if(m_draging) { ClientToScreen(&point); CWnd* pWnd = WindowFromPoint( point ); if(pWnd == this) ::SetCursor(DragWndCursor); else if(pWnd->IsKindOf( RUNTIME_CLASS( COldView ) ) ) ::SetCursor(DropOkCursor); else ::SetCursor(DropNotOkCursor); } CTreeView::OnMouseMove(nFlags, point); } void COldTreeView::OnLButtonUp(UINT nFlags, CPoint point) { if(m_draging) { m_draging = FALSE; if(this != CWnd::GetCapture()) return; ReleaseCapture(); ClientToScreen(&point); CWnd* pWnd = WindowFromPoint( point ); if(pWnd->IsKindOf( RUNTIME_CLASS( COldView ) ) ) { GetDocument()->DoDropAction(pWnd); } } CTreeView::OnLButtonUp(nFlags, point); } -----From: pmoss@bbn.com (Peter Moss) I have solved this problem for my application in which I want to drag an item from a CTreeCtrl-derived object embedded in a CControlBar object like the MSVC InfoViewer control bar. The trick was that the notification msg for the start of the begin drag operation (TVN_BEGINDRAG) is sent to the parent of the CTreeCtrl window, not the CTreeCtrl itself. In the parent window, I handle the following 3 msgs: TVN_BEGINDRAG notification WM_MOUSEMOVE WM_LBUTTONUP The steps are as follows: 1) In the TVN_BEGINDRAG handler (you can use Class Wizard to write the stub): o I change the cursor using SetCursor() to indicate a drag operation. o In my app, I know the window where I will allow a drop operation. I get the coords of the client window of this drop target, and store them in a member variable in Screen coords (m_RectDropTarget). o I capture the mouse using SetCapture() 2) In OnMouseMove(), I change the shape of the cursor depending on the window that the mouse is over. It becomes the NoDrop cursor if the mouse is not over the Drop Target Window or the client window of the CTreeCtrl. 3) In the OnLButtonUp() handler, I make sure the drop point is within the window of my Drop Target. If not, I do nothing. Here is some sample code from my app.. ----------------------------------------------- void CVarListBar::OnBegindragVarList(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // TODO: Add your control notification handler code here *pResult = 0; if (!m_pVarPropSheet) // No prop sheet up, so return return; // Item to be dragged HTREEITEM hTItem = pNMTreeView->itemNew.hItem; if (GetItemType(hTItem) != VL_VARIABLE) // Not a var return; CTreeCtrl* pVarListCtrl = (CTreeCtrl*)GetDlgItem(IDC_VARLIST); pVarListCtrl->SelectItem(hTItem); // Begin the drag // Change the cursor SetCursor(AfxGetApp()->LoadCursor(IDC_POINTER_COPY)); m_etCursor = CT_COPY; // Determine drop rects pVarListCtrl->GetClientRect(&m_RectClient); // Client rect pVarListCtrl->ClientToScreen(&m_RectClient); // Convert to screen coords m_pVarPropSheet->GetDropRect(&m_RectDropTarget); SetCapture(); // Capture the mouse TRACE0("CVarListBar::OnBegindragVarList\n"); } void CVarListBar::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if (m_etCursor != CT_NORMAL) { // We are dragging an image CPoint ptScreen = point; ClientToScreen(&ptScreen); if (m_RectClient.PtInRect(ptScreen) || m_RectDropTarget.PtInRect(ptScreen)) { // Make it a Copy Cursor if (m_etCursor != CT_COPY) { // Change the cursor ::SetCursor(AfxGetApp()->LoadCursor(IDC_POINTER_COPY)); m_etCursor = CT_COPY; } } else { // Make it a Nodrop Cursor if (m_etCursor != CT_NODROP) { // Change the cursor ::SetCursor(AfxGetApp()->LoadCursor(IDC_NODROP)); m_etCursor = CT_NODROP; } } } CSNDialogBar::OnMouseMove(nFlags, point); } void CVarListBar::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if (m_etCursor != CT_NORMAL) { // I am dragging an item, but end it now SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); TRACE0("CVarListBar::OnLButtonUp Dragging finished\n"); // Test to see if we dropped in the target rect CPoint ptScreen = point; ClientToScreen(&ptScreen); if (m_RectDropTarget.PtInRect(ptScreen)) { // User dropped in target area, so add the selected var CString VarName; LPARAM lParam; if (GetSelectedVar(VarName, lParam)) m_pVarPropSheet->AddVar(VarName, lParam, &ptScreen); } ReleaseCapture(); m_etCursor = CT_NORMAL; } CSNDialogBar::OnLButtonUp(nFlags, point); } Good Luck, Pete Moss pmoss@bbn.com -----From: "Yury Kosov" Hi Matthias, This is the way I'm doing this: In response to TVN_BEGINDRAG in the TreeControl parent: MyClass::DoDrag(NMHDR *pns, LRESULT *result) { COleDataSource dataSrc; HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,sizeof(MyData)); MyData *cd = (ClipData *)GlobalLock(hMem); // stuff the memory with my data GlobalUnlock(hMem); dataSrc.CacheGlobalData(cf,hMem); CDropSource dropSrc; DROPEFFECT de = dataSrc.DoDragDrop(DROPEFFECT_COPY,0,&dropSrc); dataSrc.Empty(); *result = 0; } On the other side (usually in the View of some sort) implement some of the drag methods: OnDragEnter() OnDragOver() OnDragLeave() OnDrop(). And, of course, don't forget to initialize OLE. Yury Kosov CoreTek, Inc. yury@msn.com -----From: Lev Gloukhenki DAOVIEW from MSVC 4.x samples is a good example how to implement drag'n'dop from/in CTree/CListControl using OLE 2 uniform data transfer Lev Gloukhenki lev@shira.co.il -----From: Olav Beisland There's an example of how to do this in Microsoft's Softlib called Mfcdrag (Mfcdrag.exe 36508 bytes).
Sundar Narasimhan -- sundar@ai.mit.edu Friday, August 30, 1996 in the sample project CMNCTRLS, I have seen how to program drag and drop inside a CTreeCtrl. That was ugly. To make my life even more complicated, I'd like to know how to drag'n'drop from a CTreeCtrl into something else, maybe another CTreeCtrl, maybe an edit control, maybe even another application (OLE?). Does anyone know how to do it? Look at the documentation for CImageList. A clean way to do drag-drop is to store object pointers in the 32-bit values associated with an item, and mixin a drag-drop protocol into these objects. Separating the drag-drop protocol into an "ask", "drop" and "reverse" protocol usually results in fewer lines of code. Target highlighting can happen inside of and in response to the "ask" and the reverse is useful to implement "visitor" patterns to avoid coupling your drag-source and target header files. Hope that helps.
| Вернуться в корень Архива |