DROPTGT.CPP

/* 
* DROPTGT.CPP
* Cosmo Chapter 23
*
* Implementation of the IDropTarget interface.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/


#include "cosmo.h"


/*
* CDropTarget::CDropTarget
* CDropTarget::~CDropTarget
*
* Constructor Parameters:
* pDoc PCCosmoDoc of the document containing us.
*/

CDropTarget::CDropTarget(PCCosmoDoc pDoc)
{
m_cRef=0;
m_pDoc=pDoc;

m_pIDataObject=NULL;
return;
}


CDropTarget::~CDropTarget(void)
{
return;
}




/*
* CDropTarget::QueryInterface
* CDropTarget::AddRef
* CDropTarget::Release
*
* Purpose:
* IUnknown members for CDropTarget object.
*/

STDMETHODIMP CDropTarget::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;

if (IID_IUnknown==riid || IID_IDropTarget==riid)
*ppv=this;

if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}

return ResultFromScode(E_NOINTERFACE);
}


STDMETHODIMP_(ULONG) CDropTarget::AddRef(void)
{
return ++m_cRef;
}

STDMETHODIMP_(ULONG) CDropTarget::Release(void)
{
if (0!=--m_cRef)
return m_cRef;

delete this;
return 0;
}





/*
* CDropTarget::DragEnter
*
* Purpose:
* Indicates that data in a drag operation has been dragged over
* our window that's a potential target. We are to decide if it's
* something we're interested in or not.
*
* Parameters:
* pIDataSource LPDATAOBJECT providing the source data.
* grfKeyState DWORD flags: states of keys and mouse buttons.
* pt POINTL coordinates in the document client space.
* pdwEffect LPDWORD into which we'll place the
* appropriate effect flag for this point.
*
* Return Value:
* HRESULT NOERROR
*/

STDMETHODIMP CDropTarget::DragEnter(LPDATAOBJECT pIDataSource
, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
{
HWND hWnd;

/*
* 1. Check if we can paste from the pIDataSource we're
* provided. We already made this nice useful function
* to test.
*/

m_pIDataObject=NULL;

if (!m_pDoc->FQueryPasteFromData(pIDataSource))
{
*pdwEffect=DROPEFFECT_NONE;
return NOERROR;
}


/*
* 2. We can always drop anywhere in our document,
* so pt is uninteresting.
*/


/*
* 3. We return either a COPY or MOVE effect flag, depending on
* the state of the grfKeyState flags. We MOVE on no key or
* Shift key, COPY on Ctrl key.
*/

//Default is move
*pdwEffect=DROPEFFECT_MOVE;

if (grfKeyState & MK_CONTROL)
*pdwEffect=DROPEFFECT_COPY;

/*
* 4. We really don't need to keep the IDataObject around since
* we're not interested in it in DragOver. However, we'll
* save it just for demonstration.
*/
m_pIDataObject=pIDataSource;
m_pIDataObject->AddRef();

/*
* 5. We always accept drops of our data on us, so we only need
* to provide some UI feedback here which we do by inverting
* the edge of the polyline window in this document. We'll
* remove this in DragLeave and in Drop. DragOver won't
* effect it since we can always drop.
*
* Since we're inverting a border, insure that this window is
* on top.
*/

hWnd=m_pDoc->Window();
BringWindowToTop(hWnd);
UpdateWindow(hWnd);
m_pDoc->DropSelectTargetWindow();

return NOERROR;
}






/*
* CDropTarget::DragOver
*
* Purpose:
* Indicates that the mouse was moved inside the window represented
* by this drop target. This happens on every WM_MOUSEMOVE, so this
* function should be very efficient.
*
* Parameters:
* grfKeyState DWORD providing current keyboard/mouse states
* pt POINTL where the mouse currently is.
* pdwEffect LPDWORD to store the effect flag for this point.
*
* Return Value:
* HRESULT NOERROR
*/

STDMETHODIMP CDropTarget::DragOver(DWORD grfKeyState, POINTL pt
, LPDWORD pdwEffect)
{
if (NULL==m_pIDataObject)
{
*pdwEffect=DROPEFFECT_NONE;
return NOERROR;
}

//We can always drop; return effect flags based on keys.
*pdwEffect=DROPEFFECT_MOVE;

if (grfKeyState & MK_CONTROL)
*pdwEffect=DROPEFFECT_COPY;

return NOERROR;
}






/*
* CDropTarget::DragLeave
*
* Purpose:
* Informs the drop target that the operation has left its window.
*
* Parameters:
* None
*
* Return Value:
* HRESULT NOERROR
*/

STDMETHODIMP CDropTarget::DragLeave(void)
{
//1. Remove the UI feedback
m_pDoc->DropSelectTargetWindow();

//2. Release the held IDataObject
ReleaseInterface(m_pIDataObject);

return NOERROR;
}





/*
* CDropTarget::Drop
*
* Purpose:
* Instructs the drop target to paste data that was just now
* dropped on it.
*
* Parameters:
* pIDataSource LPDATAOBJECT from which we'll paste.
* grfKeyState DWORD providing current keyboard/mouse state.
* pt POINTL at which the drop occurred.
* pdwEffect LPDWORD to store what you do with the data.
*
* Return Value:
* HRESULT NOERROR
*/

STDMETHODIMP CDropTarget::Drop(LPDATAOBJECT pIDataSource
, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
{
BOOL fRet=TRUE;

*pdwEffect=DROPEFFECT_NONE;

if (NULL==m_pIDataObject)
return ResultFromScode(E_FAIL);

//1. Remove the UI feedback, release pointer
DragLeave();

//No point in drag-drop to ourselves (for Cosmo, at least)
if (m_pDoc->m_fDragSource)
return ResultFromScode(E_FAIL);

//2. Try a paste
fRet=m_pDoc->PasteFromData(pIDataSource);

//3. Store the effect
if (!fRet)
return ResultFromScode(E_FAIL);

*pdwEffect=DROPEFFECT_MOVE;

if (grfKeyState & MK_CONTROL)
*pdwEffect=DROPEFFECT_COPY;

return NOERROR;
}