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.
| Вернуться в корень Архива
|