/*
*********************************************************************
*
*	The Essence of OLE
*
*	Source code sample
*
*	Copyright (c) 1996, Rolling Thunder Computing, Ipswich MA
*
*	e-mail: essence@rollthunder.com
*	CompuServe: 73540.3430
*	Web: http://www.rollthunder.com
*
*	File Name: CDROPTGT.CPP
*
*	Purpose: Implementation of IDropTarget interface
*
*********************************************************************
*/


#include <windows.h>
#include "cdroptgt.h"

extern HWND hMainWnd ;
extern int xText, yText ;
extern char DisplayText[] ;

/*
Constructor/destructor 
*/

CDropTarget::CDropTarget(void)
{   
	m_RefCount = 1 ;		// calling constructor implies AddRef( )
    return;
}


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


/*
IUnknown methods
*/

HRESULT CDropTarget::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{


    if (riid == IID_IUnknown || riid == IID_IDropTarget)
    {
	    *ppv = (LPVOID)this;  
        AddRef();
        return S_OK ;
    }
    else
    {
    	*ppv = NULL;       
    	return  E_NOINTERFACE ;
    }
}


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


STDMETHODIMP_(ULONG) CDropTarget::Release(void)
{
    ULONG ReleaseCount ;

    m_RefCount -- ;
    ReleaseCount = m_RefCount ;
    
    if (m_RefCount == 0L)
    {   
    	delete this;
    }

    return ReleaseCount ;
}


/*
IDropTarget methods
*/

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

/*                            
Check to see if the data is in a format we can handle (in this case,
only text).  If so, keep a copy of the data object pointer and add to its
reference count.
*/

  	FORMATETC fe ;
    
    fe.cfFormat = CF_TEXT ;
    fe.ptd = NULL ;
    fe.tymed = TYMED_HGLOBAL ;  
    fe.dwAspect = DVASPECT_CONTENT ; 
    fe.lindex = -1 ;
            
    if (pIDataSource->QueryGetData (&fe) == S_OK)
	{                                                                
		m_pIDataSource = pIDataSource ;  
	  	m_pIDataSource->AddRef( ) ;                          
	}          
	else
	{
		m_pIDataSource = NULL ;        
	}
		
/*
Call our own DragOver( ) method to set the effect code.
*/

	DragOver(grfKeyState, pt, pdwEffect) ;

    return S_OK ;
}
                      

STDMETHODIMP CDropTarget::DragOver(DWORD grfKeyState, POINTL pt, 
	LPDWORD pdwEffect)
{

/*
If data is in a format we couldn't handle, then set effect code to
indicate no effect if data dropped here.
*/
	if (m_pIDataSource == NULL)
    {   
    	*pdwEffect = DROPEFFECT_NONE ;
    }

/*
Else if CTRL key is up and permitted effects (supplied by drop source)
allow a move, set that code for output.
*/

    else if (!(grfKeyState & MK_CONTROL) && (*pdwEffect & DROPEFFECT_MOVE))
    {
    	*pdwEffect = DROPEFFECT_MOVE ;	
    }   

/*
Else if effect permits a copy, set that code.
*/

	else if (*pdwEffect & DROPEFFECT_COPY)
    {
    	*pdwEffect = DROPEFFECT_COPY ;
    }

/*
Otherwise, we can't handle it, set the NOEFFECT code.
*/
	else
	{
    	*pdwEffect = DROPEFFECT_NONE ;
	}
        
    return S_OK;
}


/*
Drag operation is leaving our window without dropping.  Release our hold
on the data object.
*/

STDMETHODIMP CDropTarget::DragLeave(void)
{

    if (m_pIDataSource)
    {
    	m_pIDataSource->Release();       
    }

    return S_OK;
}


STDMETHODIMP CDropTarget::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState, 
	POINTL pt, LPDWORD pdwEffect)
{   
	if (m_pIDataSource)
	{           

/*
Get point on screen where data was dropped.  Convert to client coordinates,
store in global variables xText and yText, which will cause main window to
display the text where it was dropped.
*/

		ScreenToClient (hMainWnd, (POINT *)(&pt)) ;
		xText = pt.x ;
		yText = pt.y ;
		
/*
Fetch text from data object and display it
*/

		STGMEDIUM stg ; FORMATETC fe ;

		
    	fe.cfFormat = CF_TEXT ;
    	fe.ptd = NULL ;
		fe.tymed = TYMED_HGLOBAL ;  
    	fe.dwAspect = DVASPECT_CONTENT ; 
    	fe.lindex = -1 ;
                   
		
		m_pIDataSource->GetData (&fe, &stg) ;                    
		
			
/*
Copy data into string for display in main window and Invalidate to cause
a repaint.
*/  
		LPSTR cp = (LPSTR) GlobalLock (stg.hGlobal) ;
		lstrcpyn (DisplayText, cp, 127) ;
		GlobalUnlock (stg.hGlobal) ; 
		InvalidateRect (hMainWnd, NULL,  FALSE) ;
		
/*
Release data object and storage medium
*/

		ReleaseStgMedium (&stg) ;    
		m_pIDataSource->Release( );
		
	}
	
/*
Call our own DragOver( ) method to set the effect code
*/

	DragOver(grfKeyState, pt, pdwEffect) ;
		
	return S_OK;
}
