852 lines
24 KiB
C++
852 lines
24 KiB
C++
|
//**********************************************************************
|
||
|
// File name: IDT.CPP
|
||
|
//
|
||
|
// Implementation file for CDropTarget
|
||
|
//
|
||
|
// Functions:
|
||
|
//
|
||
|
// See IDT.H for class definition
|
||
|
//
|
||
|
// Copyright (c) 1992 - 1993 Microsoft Corporation. All rights reserved.
|
||
|
//**********************************************************************
|
||
|
|
||
|
#include "pre.h"
|
||
|
#include "iocs.h"
|
||
|
#include "ias.h"
|
||
|
#include "app.h"
|
||
|
#include "site.h"
|
||
|
#include "doc.h"
|
||
|
#include "idt.h"
|
||
|
|
||
|
extern CLIPFORMAT g_cfObjectDescriptor;
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::QueryDrop
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Check if the desired drop operation (identified by the given key
|
||
|
// state) is possible at the current mouse position (pointl).
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// DWORD grfKeyState - current key state
|
||
|
// POINTL pointl - position of mouse
|
||
|
// BOOL fDragScroll - TRUE if drag scrolling cursor should
|
||
|
// be shown.
|
||
|
// LPDWORD pdwEffect - (OUT) drag effect that should occur
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// BOOL - TRUE if drop could take place,
|
||
|
// else FALSE
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// OleStdGetDropEffect OLE2UI API
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
BOOL CDropTarget::QueryDrop (
|
||
|
DWORD grfKeyState,
|
||
|
POINTL pointl,
|
||
|
BOOL fDragScroll,
|
||
|
LPDWORD pdwEffect
|
||
|
)
|
||
|
{
|
||
|
DWORD dwScrollEffect = 0L;
|
||
|
DWORD dwOKEffects = m_pDoc->m_lpApp->m_dwTargetEffect & *pdwEffect;
|
||
|
|
||
|
/* check if the cursor is in the active scroll area, if so need the
|
||
|
** special scroll cursor.
|
||
|
*/
|
||
|
if (fDragScroll)
|
||
|
dwScrollEffect = DROPEFFECT_SCROLL;
|
||
|
|
||
|
/* if we have already determined that the source does NOT have any
|
||
|
** acceptable data for us, the return NO-DROP
|
||
|
*/
|
||
|
if (! m_fCanDropCopy && ! m_fCanDropLink)
|
||
|
goto dropeffect_none;
|
||
|
|
||
|
/* OLE2NOTE: determine what type of drop should be performed given
|
||
|
** the current modifier key state. we rely on the standard
|
||
|
** interpretation of the modifier keys:
|
||
|
** no modifier -- DROPEFFECT_MOVE or whatever is allowed by src
|
||
|
** SHIFT -- DROPEFFECT_MOVE
|
||
|
** CTRL -- DROPEFFECT_COPY
|
||
|
** CTRL-SHIFT -- DROPEFFECT_LINK
|
||
|
*/
|
||
|
|
||
|
*pdwEffect = OleStdGetDropEffect(grfKeyState);
|
||
|
if (*pdwEffect == 0)
|
||
|
{
|
||
|
// No modifier keys given. Try in order MOVE, COPY, LINK.
|
||
|
if ((DROPEFFECT_MOVE & dwOKEffects) && m_fCanDropCopy)
|
||
|
*pdwEffect = DROPEFFECT_MOVE;
|
||
|
else if ((DROPEFFECT_COPY & dwOKEffects) && m_fCanDropCopy)
|
||
|
*pdwEffect = DROPEFFECT_COPY;
|
||
|
else if ((DROPEFFECT_LINK & dwOKEffects) && m_fCanDropLink)
|
||
|
*pdwEffect = DROPEFFECT_LINK;
|
||
|
else
|
||
|
goto dropeffect_none;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* OLE2NOTE: we should check if the drag source application allows
|
||
|
** the desired drop effect.
|
||
|
*/
|
||
|
if (!(*pdwEffect & dwOKEffects))
|
||
|
goto dropeffect_none;
|
||
|
|
||
|
if ((*pdwEffect == DROPEFFECT_COPY || *pdwEffect == DROPEFFECT_MOVE)
|
||
|
&& ! m_fCanDropCopy)
|
||
|
goto dropeffect_none;
|
||
|
|
||
|
if (*pdwEffect == DROPEFFECT_LINK && ! m_fCanDropLink)
|
||
|
goto dropeffect_none;
|
||
|
}
|
||
|
|
||
|
*pdwEffect |= dwScrollEffect;
|
||
|
return TRUE;
|
||
|
|
||
|
dropeffect_none:
|
||
|
|
||
|
*pdwEffect = DROPEFFECT_NONE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::QueryDrop
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Check to see if Drag scroll operation should be initiated.
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// POINTL pointl - position of mouse
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// BOOL - TRUE if scroll cursor should be given
|
||
|
// else FALSE
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// ScreenToClient WINDOWS API
|
||
|
// GetClientRect WINDOWS API
|
||
|
//
|
||
|
// Comments:
|
||
|
// A Drag scroll operation should be initiated when the mouse has
|
||
|
// remained in the active scroll area (11 pixels frame around border
|
||
|
// of window) for a specified amount of time (50ms).
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
BOOL CDropTarget::DoDragScroll (POINTL pointl)
|
||
|
{
|
||
|
DWORD dwScrollDir = SCROLLDIR_NULL;
|
||
|
DWORD dwTime = GetCurrentTime();
|
||
|
int nScrollInset = m_pDoc->m_lpApp->m_nScrollInset;
|
||
|
int nScrollDelay = m_pDoc->m_lpApp->m_nScrollDelay;
|
||
|
int nScrollInterval = m_pDoc->m_lpApp->m_nScrollInterval;
|
||
|
POINT point;
|
||
|
RECT rect;
|
||
|
|
||
|
point.x = (int)pointl.x;
|
||
|
point.y = (int)pointl.y;
|
||
|
|
||
|
ScreenToClient( m_pDoc->m_hDocWnd, &point);
|
||
|
GetClientRect ( m_pDoc->m_hDocWnd, (LPRECT) &rect );
|
||
|
|
||
|
if (rect.top <= point.y && point.y<=(rect.top+nScrollInset))
|
||
|
dwScrollDir = SCROLLDIR_UP;
|
||
|
else if ((rect.bottom-nScrollInset) <= point.y && point.y <= rect.bottom)
|
||
|
dwScrollDir = SCROLLDIR_DOWN;
|
||
|
else if (rect.left <= point.x && point.x <= (rect.left+nScrollInset))
|
||
|
dwScrollDir = SCROLLDIR_LEFT;
|
||
|
else if ((rect.right-nScrollInset) <= point.x && point.x <= rect.right)
|
||
|
dwScrollDir = SCROLLDIR_RIGHT;
|
||
|
|
||
|
if (m_dwTimeEnterScrollArea)
|
||
|
{
|
||
|
/* cursor was already in Scroll Area */
|
||
|
|
||
|
if (! dwScrollDir)
|
||
|
{
|
||
|
/* cusor moved OUT of scroll area.
|
||
|
** clear "EnterScrollArea" time.
|
||
|
*/
|
||
|
m_dwTimeEnterScrollArea = 0L;
|
||
|
m_dwNextScrollTime = 0L;
|
||
|
m_dwLastScrollDir = SCROLLDIR_NULL;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
if (dwScrollDir != m_dwLastScrollDir)
|
||
|
{
|
||
|
/* cusor moved into a different direction scroll area.
|
||
|
** reset "EnterScrollArea" time to start a new 50ms delay.
|
||
|
*/
|
||
|
m_dwTimeEnterScrollArea = dwTime;
|
||
|
m_dwNextScrollTime = dwTime + (DWORD)nScrollDelay;
|
||
|
m_dwLastScrollDir = dwScrollDir;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
if (dwTime && dwTime >= m_dwNextScrollTime)
|
||
|
{
|
||
|
m_pDoc->Scroll ( dwScrollDir ); // Scroll document now
|
||
|
m_dwNextScrollTime = dwTime + (DWORD)nScrollInterval;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (dwScrollDir)
|
||
|
{
|
||
|
/* cusor moved INTO a scroll area.
|
||
|
** reset "EnterScrollArea" time to start a new 50ms delay.
|
||
|
*/
|
||
|
m_dwTimeEnterScrollArea = dwTime;
|
||
|
m_dwNextScrollTime = dwTime + (DWORD)nScrollDelay;
|
||
|
m_dwLastScrollDir = dwScrollDir;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (dwScrollDir ? TRUE : FALSE);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Support functions/macros
|
||
|
#define SetTopLeft(rc, pt) \
|
||
|
((rc)->top = (pt)->y,(rc)->left = (pt)->x)
|
||
|
#define SetBottomRight(rc, pt) \
|
||
|
((rc)->bottom = (pt)->y,(rc)->right = (pt)->x)
|
||
|
#define OffsetPoint(pt, dx, dy) \
|
||
|
((pt)->x += dx, (pt)->y += dy)
|
||
|
|
||
|
|
||
|
/* HighlightRect
|
||
|
** -------------
|
||
|
** Invert rectangle on screen. used for drop target feedback.
|
||
|
*/
|
||
|
|
||
|
static int HighlightRect(HWND hwnd, HDC hdc, LPRECT rc)
|
||
|
{
|
||
|
POINT pt1, pt2;
|
||
|
int old = SetROP2(hdc, R2_NOT);
|
||
|
HPEN hpen;
|
||
|
HGDIOBJ hold;
|
||
|
|
||
|
pt1.x = rc->left;
|
||
|
pt1.y = rc->top;
|
||
|
pt2.x = rc->right;
|
||
|
pt2.y = rc->bottom;
|
||
|
|
||
|
ScreenToClient(hwnd, &pt1);
|
||
|
ScreenToClient(hwnd, &pt2);
|
||
|
|
||
|
hold = SelectObject(hdc, GetStockObject(HOLLOW_BRUSH));
|
||
|
hpen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 2,
|
||
|
GetSysColor(COLOR_ACTIVEBORDER)));
|
||
|
|
||
|
Rectangle(hdc, pt1.x, pt1.y, pt2.x, pt2.y);
|
||
|
|
||
|
SetROP2(hdc, old);
|
||
|
|
||
|
hold = SelectObject(hdc, hold);
|
||
|
hpen = (HPEN) SelectObject(hdc, hpen);
|
||
|
|
||
|
DeleteObject(hpen);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::InitDragFeedback
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Initialize data used to draw drop target feedback.
|
||
|
// As feedback we draw a rectangle the size of the object.
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// LPDATAOBJECT pDataObj - IDataObject from Drop source
|
||
|
// POINTL pointl - position of mouse
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// none.
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// IDataObject::GetData Object
|
||
|
// XformSizeInHimetricToPixels OLE2UI Library
|
||
|
// GlobalLock WINDOWS API
|
||
|
// GlobalUnlock WINDOWS API
|
||
|
// ReleaseStgMedium OLE2 API
|
||
|
// OffsetPoint IDT.CPP
|
||
|
// SetTopLeft IDT.CPP
|
||
|
// SetBottomRight IDT.CPP
|
||
|
//
|
||
|
// Comments:
|
||
|
// In order to know the size of the object before the object
|
||
|
// is actually dropped, we render CF_OBJECTDESCRIPTOR format.
|
||
|
// this data format tells us both the size of the object as
|
||
|
// well as which aspect is the object is displayed as in the
|
||
|
// source. If the object is currently displayed as DVASPECT_ICON
|
||
|
// then we want to create the object also as DVASPECT_ICON.
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
void CDropTarget::InitDragFeedback(LPDATAOBJECT pDataObj, POINTL pointl)
|
||
|
{
|
||
|
FORMATETC fmtetc;
|
||
|
STGMEDIUM stgmed;
|
||
|
POINT pt;
|
||
|
int height, width;
|
||
|
HRESULT hrErr;
|
||
|
|
||
|
height = width = 100; // some default values
|
||
|
pt.x = (int)pointl.x;
|
||
|
pt.y = (int)pointl.y;
|
||
|
|
||
|
// do a GetData for CF_OBJECTDESCRIPTOR format to get the size of the
|
||
|
// object as displayed in the source. using this size, initialize the
|
||
|
// size for the drag feedback rectangle.
|
||
|
fmtetc.cfFormat = g_cfObjectDescriptor;
|
||
|
fmtetc.ptd = NULL;
|
||
|
fmtetc.lindex = -1;
|
||
|
fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
|
fmtetc.tymed = TYMED_HGLOBAL;
|
||
|
|
||
|
hrErr = pDataObj->GetData(&fmtetc, &stgmed);
|
||
|
if (hrErr == NOERROR)
|
||
|
{
|
||
|
LPOBJECTDESCRIPTOR pOD=(LPOBJECTDESCRIPTOR)GlobalLock(stgmed.hGlobal);
|
||
|
if (pOD != NULL)
|
||
|
{
|
||
|
XformSizeInHimetricToPixels(NULL, &pOD->sizel, &pOD->sizel);
|
||
|
|
||
|
width = (int)pOD->sizel.cx;
|
||
|
height = (int)pOD->sizel.cy;
|
||
|
m_dwSrcAspect = pOD->dwDrawAspect;
|
||
|
}
|
||
|
|
||
|
GlobalUnlock(stgmed.hGlobal);
|
||
|
ReleaseStgMedium(&stgmed);
|
||
|
}
|
||
|
|
||
|
m_ptLast = pt;
|
||
|
m_fDragFeedbackDrawn = FALSE;
|
||
|
|
||
|
OffsetPoint(&pt, -(width/2), -(height/2));
|
||
|
SetTopLeft(&m_rcDragRect, &pt);
|
||
|
|
||
|
OffsetPoint(&pt, width, height);
|
||
|
SetBottomRight(&m_rcDragRect, &pt);
|
||
|
}
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::UndrawDragFeedback
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Erase any drop target feedback.
|
||
|
// As feedback we draw a rectangle the size of the object.
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// none.
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// none.
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// GetDC WINDOWS API
|
||
|
// ReleaseDC WINDOWS API
|
||
|
// HighlightRect IDT.CPP
|
||
|
//
|
||
|
// Comments:
|
||
|
// In order to know the size of the object before the object
|
||
|
// is actually dropped, we render CF_OBJECTDESCRIPTOR format.
|
||
|
// this data format tells us both the size of the object as
|
||
|
// well as which aspect is the object is displayed as in the
|
||
|
// source. if the object is currently displayed as DVASPECT_ICON
|
||
|
// then we want to create the object also as DVASPECT_ICON.
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
void CDropTarget::UndrawDragFeedback( void )
|
||
|
{
|
||
|
if (m_fDragFeedbackDrawn)
|
||
|
{
|
||
|
m_fDragFeedbackDrawn = FALSE;
|
||
|
HDC hDC = GetDC(m_pDoc->m_hDocWnd);
|
||
|
HighlightRect(m_pDoc->m_hDocWnd, hDC, &m_rcDragRect);
|
||
|
ReleaseDC(m_pDoc->m_hDocWnd, hDC);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::DrawDragFeedback
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Compute new position of drop target feedback rectangle and
|
||
|
// erase old rectangle and draw new rectangle.
|
||
|
// As feedback we draw a rectangle the size of the object.
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// POINTL pointl - position of mouse
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// none.
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// OffsetPoint IDT.CPP
|
||
|
// OffsetRect IDT.CPP
|
||
|
// HighlightRect IDT.CPP
|
||
|
// GetDC WINDOWS API
|
||
|
// ReleaseDC WINDOWS API
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
void CDropTarget::DrawDragFeedback( POINTL pointl )
|
||
|
{
|
||
|
POINT ptDiff;
|
||
|
|
||
|
ptDiff.x = (int)pointl.x - m_ptLast.x;
|
||
|
ptDiff.y = (int)pointl.y - m_ptLast.y;
|
||
|
|
||
|
if (m_fDragFeedbackDrawn && (ptDiff.x == 0 && ptDiff.y == 0))
|
||
|
return; // mouse did not move; leave rectangle as drawn
|
||
|
|
||
|
HDC hDC = GetDC(m_pDoc->m_hDocWnd);
|
||
|
if (m_fDragFeedbackDrawn)
|
||
|
{
|
||
|
m_fDragFeedbackDrawn = FALSE;
|
||
|
HighlightRect(m_pDoc->m_hDocWnd, hDC, &m_rcDragRect);
|
||
|
}
|
||
|
|
||
|
OffsetRect(&m_rcDragRect, ptDiff.x, ptDiff.y);
|
||
|
HighlightRect(m_pDoc->m_hDocWnd, hDC, &m_rcDragRect);
|
||
|
m_fDragFeedbackDrawn = TRUE;
|
||
|
m_ptLast.x = (int)pointl.x;
|
||
|
m_ptLast.y = (int)pointl.y;
|
||
|
ReleaseDC(m_pDoc->m_hDocWnd, hDC);
|
||
|
}
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::QueryInterface
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Used for interface negotiation
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// REFIID riid - ID of interface to be returned
|
||
|
// LPVOID FAR* ppvObj - Location to return the interface
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// S_OK - Interface supported
|
||
|
// E_NOINTERFACE - Interface NOT supported
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// TestDebugOut Windows API
|
||
|
// CSimpleDoc::QueryInterface DOC.CPP
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
STDMETHODIMP CDropTarget::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
|
||
|
{
|
||
|
TestDebugOut("In IDT::QueryInterface\r\n");
|
||
|
|
||
|
// delegate to the document
|
||
|
return m_pDoc->QueryInterface(riid, ppvObj);
|
||
|
}
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::AddRef
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Increments the reference count of CSimpleDoc. Since CDropTarget is
|
||
|
// a nested class of CSimpleDoc, we don't need a separate reference
|
||
|
// count for CDropTarget. We can safely use the reference count of
|
||
|
// CSimpleDoc.
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// The new reference count of CSimpleDoc
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// CSimpleDoc::AddReff DOC.CPP
|
||
|
// TestDebugOut Windows API
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CDropTarget::AddRef()
|
||
|
{
|
||
|
TestDebugOut("In IDT::AddRef\r\n");
|
||
|
|
||
|
// delegate to the document Object
|
||
|
return m_pDoc->AddRef();
|
||
|
}
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::Release
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Decrements the reference count of CSimpleDoc. Since CDropTarget is
|
||
|
// a nested class of CSimpleDoc, we don't need a separate reference
|
||
|
// count for CDropTarget. We can safely use the reference count of
|
||
|
// CSimpleDoc.
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// The new reference count of CSimpleDoc
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// CSimpleDoc::Release DOC.CPP
|
||
|
// TestDebugOut Windows API
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CDropTarget::Release()
|
||
|
{
|
||
|
TestDebugOut("In IDT::Release\r\n");
|
||
|
|
||
|
// delegate to the document object
|
||
|
return m_pDoc->Release();
|
||
|
}
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::DragEnter
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Called when the mouse first enters our DropTarget window
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// LPDATAOBJECT pDataObj - IDataObject from Drop source
|
||
|
// DWORD grfKeyState - current key state
|
||
|
// POINTL pointl - position of mouse
|
||
|
// LPDWORD pdwEffect - (IN-OUT) drag effect that should occur
|
||
|
// ON INPUT, this is dwOKEffects that source
|
||
|
// passed to DoDragDrop API.
|
||
|
// ON OUTPUT, this is the effect that we
|
||
|
// want to take effect (used to determine
|
||
|
// cursor feedback).
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// NOERROR
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// TestDebugOut Windows API
|
||
|
// OleQueryCreateFromData OLE2 API
|
||
|
// DoDragScroll IDT.CPP
|
||
|
// QueryDrop IDT.CPP
|
||
|
// InitDragFeedback IDT.CPP
|
||
|
// DrawDragFeedback IDT.CPP
|
||
|
//
|
||
|
// Comments:
|
||
|
// Callee should honor the dwEffects as passed in to determine
|
||
|
// if the caller allows DROPEFFECT_MOVE.
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
STDMETHODIMP CDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState,
|
||
|
POINTL pointl, LPDWORD pdwEffect)
|
||
|
{
|
||
|
TestDebugOut("In IDT::DragEnter\r\n");
|
||
|
|
||
|
/* Determine if the drag source data object offers a data format
|
||
|
** that we understand. we accept only creating embedded objects.
|
||
|
*/
|
||
|
m_fCanDropCopy = ((OleQueryCreateFromData(pDataObj) == NOERROR) ?
|
||
|
TRUE : FALSE);
|
||
|
m_fCanDropLink = FALSE; // linking NOT supported in this simple sample
|
||
|
|
||
|
if (m_fCanDropCopy || m_fCanDropLink)
|
||
|
InitDragFeedback(pDataObj, pointl);
|
||
|
|
||
|
BOOL fDragScroll = DoDragScroll ( pointl );
|
||
|
|
||
|
if (QueryDrop(grfKeyState,pointl,fDragScroll,pdwEffect))
|
||
|
{
|
||
|
DrawDragFeedback( pointl );
|
||
|
}
|
||
|
|
||
|
// with our drag drop optimization, pDataObj will actually be a
|
||
|
// wrapper data object. QueryGetData calls (currently) will be
|
||
|
// propogated to the drag source (whereas EnumFormatetc is handled
|
||
|
// locally). Make sure we can do a QueryGetData.
|
||
|
|
||
|
FORMATETC formatetc;
|
||
|
formatetc.cfFormat = CF_METAFILEPICT;
|
||
|
formatetc.tymed = TYMED_MFPICT;
|
||
|
formatetc.ptd = NULL;
|
||
|
formatetc.lindex = -1;
|
||
|
formatetc.dwAspect = DVASPECT_CONTENT;
|
||
|
|
||
|
// E_FAIL is usually returned if we could not get the drag source
|
||
|
// data object.
|
||
|
if( pDataObj->QueryGetData(&formatetc) == E_FAIL )
|
||
|
{
|
||
|
TestDebugOut("WARNING! QueryGetData failed!");
|
||
|
}
|
||
|
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::DragOver
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Called when the mouse moves, key state changes, or a time
|
||
|
// interval passes while the mouse is still within our DropTarget
|
||
|
// window.
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// DWORD grfKeyState - current key state
|
||
|
// POINTL pointl - position of mouse
|
||
|
// LPDWORD pdwEffect - (IN-OUT) drag effect that should occur
|
||
|
// ON INPUT, this is dwOKEffects that source
|
||
|
// passed to DoDragDrop API.
|
||
|
// ON OUTPUT, this is the effect that we
|
||
|
// want to take effect (used to determine
|
||
|
// cursor feedback).
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// NOERROR
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// TestDebugOut Windows API
|
||
|
// DoDragScroll IDT.CPP
|
||
|
// QueryDrop IDT.CPP
|
||
|
// DrawDragFeedback IDT.CPP
|
||
|
// UndrawDragFeedback IDT.CPP
|
||
|
//
|
||
|
// Comments:
|
||
|
// Callee should honor the dwEffects as passed in to determine
|
||
|
// if the caller allows DROPEFFECT_MOVE. OLE pulses the DragOver
|
||
|
// calls in order that the DropTarget can implement drag scrolling
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
STDMETHODIMP CDropTarget::DragOver (DWORD grfKeyState, POINTL pointl,
|
||
|
LPDWORD pdwEffect)
|
||
|
{
|
||
|
TestDebugOut("In IDT::DragOver\r\n");
|
||
|
|
||
|
BOOL fDragScroll = DoDragScroll ( pointl );
|
||
|
|
||
|
if (QueryDrop(grfKeyState,pointl,fDragScroll,pdwEffect))
|
||
|
{
|
||
|
DrawDragFeedback( pointl );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UndrawDragFeedback();
|
||
|
}
|
||
|
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::DragLeave
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Called when the mouse leaves our DropTarget window
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// none.
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// S_OK
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// TestDebugOut Windows API
|
||
|
// UndrawDragFeedback IDT.CPP
|
||
|
// ResultFromScode OLE2 API
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
STDMETHODIMP CDropTarget::DragLeave ()
|
||
|
{
|
||
|
TestDebugOut("In IDT::DragLeave\r\n");
|
||
|
|
||
|
UndrawDragFeedback();
|
||
|
|
||
|
return ResultFromScode(S_OK);
|
||
|
}
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CDropTarget::Drop
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Called when a Drop operation should take place.
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// LPDATAOBJECT pDataObj - IDataObject from Drop source
|
||
|
// DWORD grfKeyState - current key state
|
||
|
// POINTL pointl - position of mouse
|
||
|
// LPDWORD pdwEffect - (IN-OUT) drag effect that should occur
|
||
|
// ON INPUT, this is dwOKEffects that source
|
||
|
// passed to DoDragDrop API.
|
||
|
// ON OUTPUT, this is the effect that we
|
||
|
// want to take effect (used to determine
|
||
|
// cursor feedback).
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// S_OK if sucess or HRESULT of the error code if fails
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// TestDebugOut Windows API
|
||
|
// CSimpleSite::Create SITE.CPP
|
||
|
// CSimpleSite::InitObject SITE.CPP
|
||
|
// OleCreateFromData OLE2 API
|
||
|
// DoDragScroll IDT.CPP
|
||
|
// QueryDrop IDT.CPP
|
||
|
// InitDragFeedback IDT.CPP
|
||
|
// DrawDragFeedback IDT.CPP
|
||
|
// UndrawDragFeedback IDT.CPP
|
||
|
// GetScode OLE2 API
|
||
|
// ResultFromScode OLE2 API
|
||
|
//
|
||
|
// Comments:
|
||
|
// Callee should honor the dwEffects as passed in to determine
|
||
|
// if the caller allows DROPEFFECT_MOVE.
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
STDMETHODIMP CDropTarget::Drop (LPDATAOBJECT pDataObj, DWORD grfKeyState,
|
||
|
POINTL pointl, LPDWORD pdwEffect)
|
||
|
{
|
||
|
FORMATETC fmtetc;
|
||
|
SCODE sc = S_OK;
|
||
|
|
||
|
TestDebugOut("In IDT::Drop\r\n");
|
||
|
|
||
|
UndrawDragFeedback();
|
||
|
|
||
|
if (pDataObj && QueryDrop(grfKeyState,pointl,FALSE,pdwEffect))
|
||
|
{
|
||
|
m_pDoc->m_lpSite = CSimpleSite::Create(m_pDoc);
|
||
|
if (!m_pDoc->m_lpSite)
|
||
|
{
|
||
|
/* memory allocation problem. cannot continue.
|
||
|
*/
|
||
|
return(ResultFromScode(E_OUTOFMEMORY));
|
||
|
}
|
||
|
|
||
|
// keep same aspect as drop source
|
||
|
m_pDoc->m_lpSite->m_dwDrawAspect = m_dwSrcAspect;
|
||
|
|
||
|
// in order to specify a particular drawing Aspect we must
|
||
|
// pass a FORMATETC* to OleCreateFromData
|
||
|
fmtetc.cfFormat = NULL; // use whatever for drawing
|
||
|
fmtetc.ptd = NULL;
|
||
|
fmtetc.lindex = -1;
|
||
|
fmtetc.dwAspect = m_dwSrcAspect; // desired drawing aspect
|
||
|
fmtetc.tymed = TYMED_NULL;
|
||
|
|
||
|
HRESULT hrErr = OleCreateFromData (
|
||
|
pDataObj,
|
||
|
IID_IOleObject,
|
||
|
OLERENDER_DRAW,
|
||
|
&fmtetc,
|
||
|
&m_pDoc->m_lpSite->m_OleClientSite,
|
||
|
m_pDoc->m_lpSite->m_lpObjStorage,
|
||
|
(LPVOID FAR *)&m_pDoc->m_lpSite->m_lpOleObject);
|
||
|
|
||
|
if (hrErr == NOERROR)
|
||
|
{
|
||
|
m_pDoc->m_lpSite->InitObject(FALSE /* fCreateNew */);
|
||
|
m_pDoc->DisableInsertObject();
|
||
|
}
|
||
|
else
|
||
|
sc = GetScode(hrErr);
|
||
|
}
|
||
|
|
||
|
return ResultFromScode(sc);
|
||
|
}
|