File:  [WindowsNT SDKs] / mstools / ole20 / samples / outline / dragdrop.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:24:38 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-jul-1993, HEAD
Microsoft Windows NT Build 511 (SDK Final Release) 07-24-1993

/*************************************************************************
** 
**    OLE 2 Sample Code
**    
**    dragdrop.c
**    
**    This file contains the major interfaces, methods and related support
**    functions for implementing Drag/Drop. The code contained in this
**    file is used by BOTH the Container and Server (Object) versions
**    of the Outline sample code.
**    The Drag/Drop support includes the following implementation objects: 
**    
**    OleDoc Object
**      exposed interfaces:
**          IDropSource
**          IDropTarget
**    
**    (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
**
*************************************************************************/

#include "outline.h"

OLEDBGDATA

extern LPOUTLINEAPP             g_lpApp;


#if defined( USE_DRAGDROP )

/* OleDoc_QueryDrag
 * ----------------
 * Check to see if Drag operation should be initiated. A Drag operation
 * should be initiated when the mouse in either the top 10 pixels of the
 * selected list box entry or in the bottom 10 pixels of the last selected
 * item.
 */

BOOL OleDoc_QueryDrag(LPOLEDOC lpOleDoc, int y)
{
    LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
    LINERANGE LineRange;

    if ( LineList_GetSel( lpLL,  (LPLINERANGE)&LineRange) ) {
        RECT rect;

        if (!LineList_GetLineRect(lpLL,LineRange.m_nStartLine,(LPRECT)&rect))
            return FALSE ;

        if ( rect.top <= y && y <= rect.top + DD_SEL_THRESH )
            return TRUE;

        LineList_GetLineRect( lpLL, LineRange.m_nEndLine, (LPRECT)&rect );
        if ( rect.bottom >= y && y >= rect.bottom - DD_SEL_THRESH )
            return TRUE;

    }

    return FALSE;
}

/* OleDoc_DoDragScroll
 * -------------------
 * Check to see if Drag scroll operation should be initiated. 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 OleDoc_DoDragScroll(LPOLEDOC lpOleDoc, POINTL pointl)
{
    LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
    LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
    HWND hWndListBox = LineList_GetWindow(lpLL);
    DWORD dwScrollDir = SCROLLDIR_NULL;
    DWORD      dwTime = GetCurrentTime();
    POINT point;
    RECT rect;

    if ( lpLL->m_nNumLines == 0 )
        return FALSE;

    point.x = (int)pointl.x;
    point.y = (int)pointl.y;

    ScreenToClient( hWndListBox, &point);
    GetClientRect ( hWndListBox, (LPRECT) &rect );

    if (rect.top <= point.y && point.y<=(rect.top+lpOleApp->m_nScrollInset))
        dwScrollDir = SCROLLDIR_UP;
    else if ( (rect.bottom - lpOleApp->m_nScrollInset) <= point.y &&
                                                    point.y <= rect.bottom )
        dwScrollDir = SCROLLDIR_DOWN;

    if (lpOleDoc->m_dwTimeEnterScrollArea) {

        /* cursor was already in Scroll Area */

        if (! dwScrollDir) {
            /* cusor moved OUT of scroll area.
            **      clear "EnterScrollArea" time.
            */
            lpOleDoc->m_dwTimeEnterScrollArea = 0;
            lpOleDoc->m_lastdwScrollDir = SCROLLDIR_NULL;
        } else if (dwScrollDir != lpOleDoc->m_lastdwScrollDir) {
            /* cusor moved into a different direction scroll area.
            **      reset "EnterScrollArea" time to start a new 50ms delay.
            */
            lpOleDoc->m_dwTimeEnterScrollArea = dwTime;
            lpOleDoc->m_lastdwScrollDir = dwScrollDir;
        } else if ((dwTime - lpOleDoc->m_dwTimeEnterScrollArea)
                                        >= (DWORD)lpOleApp->m_nScrollDelay) {

            LineList_Scroll ( lpLL, dwScrollDir );
        }
    } else {
        if (dwScrollDir) {
            /* cusor moved INTO a scroll area.
            **      reset "EnterScrollArea" time to start a new 50ms delay.
            */
            lpOleDoc->m_dwTimeEnterScrollArea = dwTime;
            lpOleDoc->m_lastdwScrollDir = dwScrollDir;
        }
    }

    return (dwScrollDir ? TRUE : FALSE);
}


/* OleDoc_QueryDrop
** ----------------
**    Check if the desired drop operation (identified by the given key
**    state) is possible at the current mouse position (pointl).
*/
BOOL OleDoc_QueryDrop (
    LPOLEDOC        lpOleDoc,
    DWORD           grfKeyState,
    POINTL          pointl,
    BOOL            fDragScroll,
    LPDWORD         lpdwEffect
)
{
    LPLINELIST lpLL   = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
    LINERANGE  linerange;
    short      nIndex = LineList_GetLineIndexFromPointl( lpLL, pointl );
    DWORD      dwScrollEffect = 0L;

    /* 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 (! lpOleDoc->m_fCanDropCopy && ! lpOleDoc->m_fCanDropLink)
        goto dropeffect_none;

    /* if the Drag/Drop is local to our document, we can NOT accept a
    **    drop in the middle of the current selection (which is the exact
    **    data that is being dragged!).
    */
    if (lpOleDoc->m_fLocalDrag) {
        LineList_GetSel( lpLL, (LPLINERANGE)&linerange );

        if (linerange.m_nStartLine <= nIndex && nIndex<linerange.m_nEndLine) 
            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
    **          CTRL        -- DROPEFFECT_COPY
    **          CTRL-SHIFT  -- DROPEFFECT_LINK
    */
    *lpdwEffect = OleStdGetDropEffect(grfKeyState);
    if (*lpdwEffect == 0) 
        *lpdwEffect = DROPEFFECT_MOVE;  // no modifier given => MOVE

    if ( (*lpdwEffect == DROPEFFECT_COPY || *lpdwEffect == DROPEFFECT_MOVE)
            && ! lpOleDoc->m_fCanDropCopy )
        goto dropeffect_none;

    if ( *lpdwEffect == DROPEFFECT_LINK && ! lpOleDoc->m_fCanDropLink )
        goto dropeffect_none;

    *lpdwEffect |= dwScrollEffect;
    return TRUE;

dropeffect_none:

    *lpdwEffect = DROPEFFECT_NONE;
    return FALSE;
}

/* OleDoc_DoDragDrop
 * -----------------
 *  Actually perform a drag/drop operation with the current selection in
 *      the source document (lpSrcOleDoc).
 *
 *  returns the result effect of the drag/drop operation:
 *      DROPEFFECT_NONE,
 *      DROPEFFECT_COPY,
 *      DROPEFFECT_MOVE, or
 *      DROPEFFECT_LINK
 */

DWORD OleDoc_DoDragDrop (LPOLEDOC lpSrcOleDoc)
{
    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
    LPOUTLINEDOC lpSrcOutlineDoc = (LPOUTLINEDOC)lpSrcOleDoc;
    LPOLEDOC lpDragDoc;
    LPLINELIST  lpSrcLL =
                    (LPLINELIST)&((LPOUTLINEDOC)lpSrcOleDoc)->m_LineList;
    DWORD       dwEffect     = 0;
    LPLINE      lplineStart, lplineEnd;
    LINERANGE   linerange;

    OLEDBG_BEGIN3("OleDoc_DoDragDrop\r\n")

    /* squirrel away a copy of the current selection to the ClipboardDoc */
    lpDragDoc = (LPOLEDOC)OutlineDoc_CreateDataTransferDoc(lpSrcOutlineDoc);
    if ( ! lpDragDoc) {
        dwEffect = DROPEFFECT_NONE;
        goto error;
    }

    /* OLE2NOTE: initially the Doc object is created with a 0 ref
    **    count. in order to have a stable Doc object during the
    **    process of initializing the Doc instance and performing the
    **    drag operation, we intially AddRef the Doc ref cnt and later
    **    Release it. This initial AddRef is artificial; it is simply
    **    done to guarantee that a harmless QueryInterface followed by
    **    a Release does not inadvertantly force our object to destroy
    **    itself prematurely.
    */
    OleDoc_AddRef(lpDragDoc);

    //NOTE: we need to keep the LPLINE pointers
    //      rather than the indexes because the
    //      indexes will not be the same after the
    //      drop occurs  -- the drop adds new
    //      entries to the list thereby shifting
    //      the whole list.
    LineList_GetSel( lpSrcLL, (LPLINERANGE)&linerange );
    lplineStart = LineList_GetLine ( lpSrcLL, linerange.m_nStartLine );
    lplineEnd   = LineList_GetLine ( lpSrcLL, linerange.m_nEndLine );

    lpSrcOleDoc->m_fLocalDrop     = FALSE;
    lpSrcOleDoc->m_fLocalDrag     = TRUE;

    OLEDBG_BEGIN2("DoDragDrop called\r\n")
    DoDragDrop ( (LPDATAOBJECT) &lpDragDoc->m_DataObject,
                 (LPDROPSOURCE) &lpSrcOleDoc->m_DropSource,
                 DROPEFFECT_MOVE | DROPEFFECT_COPY,
                 (LPDWORD) &dwEffect
    );
    OLEDBG_END2

    lpSrcOleDoc->m_fLocalDrag     = FALSE;

    /* if after the Drag/Drop modal (mouse capture) loop is finished
    **    and a drag MOVE operation was performed, then we must delete
    **    the lines that were dragged.
    */
    if ( (dwEffect & DROPEFFECT_MOVE) != 0 ) {

        int i,j,iEnd;
        LPLINE lplineFocusLine;

        /* disable repainting and sending data changed notifications
        **    until after all lines have been deleted.
        */
        OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpSrcOleDoc, FALSE );

        /* if the drop was local to our document, then we must take
        **    into account that the line indices of the original source
        **    of the drag could have shifted because the dropped lines
        **    have been inserted into our document. thus we will
        **    re-determine the source line indices.
        */
        if (lpSrcOleDoc->m_fLocalDrop) {
            i = LineList_GetFocusLineIndex ( lpSrcLL );
            lplineFocusLine = LineList_GetLine ( lpSrcLL, i );
        }

        for ( i = j = LineList_GetLineIndex(lpSrcLL,lplineStart ) ,
              iEnd  = LineList_GetLineIndex(lpSrcLL,lplineEnd ) ;
              i <= iEnd ;
              i++
        ) OutlineDoc_DeleteLine ((LPOUTLINEDOC)lpSrcOleDoc, j );

        LineList_RecalcMaxLineWidthInHimetric(lpSrcLL, 0);

        if (lpSrcOleDoc->m_fLocalDrop) {
            i = LineList_GetLineIndex ( lpSrcLL, lplineFocusLine );
            LineList_SetFocusLine ( lpSrcLL, (WORD)i );
        }

        OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpSrcOleDoc, TRUE );

		/* if it is a local Drag/Drop move, we need to balance the
        **    SetRedraw(FALSE) call that was made in the implementation
        **    of IDropTarget::Drop.
        */
        if (lpSrcOleDoc->m_fLocalDrop)
            OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpSrcOleDoc, TRUE );

        LineList_ForceRedraw ( lpSrcLL, FALSE );
    }

    OleDoc_Release(lpDragDoc);  // rel artificial AddRef above

    OLEDBG_END3
    return dwEffect;

error:
    OLEDBG_END3
    return dwEffect;
}



/*************************************************************************
** OleDoc::IDropSource interface implementation
*************************************************************************/

STDMETHODIMP OleDoc_DropSource_QueryInterface(
    LPDROPSOURCE            lpThis,
    REFIID                  riid,
    LPVOID FAR*             lplpvObj
)
{
    LPOLEDOC lpOleDoc = ((struct CDocDropSourceImpl FAR*)lpThis)->lpOleDoc;

    return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
}


STDMETHODIMP_(ULONG) OleDoc_DropSource_AddRef( LPDROPSOURCE lpThis )
{
    LPOLEDOC lpOleDoc = ((struct CDocDropSourceImpl FAR*)lpThis)->lpOleDoc;

    OleDbgAddRefMethod(lpThis, "IDropSource");

    return OleDoc_AddRef(lpOleDoc);
}


STDMETHODIMP_(ULONG) OleDoc_DropSource_Release ( LPDROPSOURCE lpThis)
{
    LPOLEDOC lpOleDoc = ((struct CDocDropSourceImpl FAR*)lpThis)->lpOleDoc;

    OleDbgReleaseMethod(lpThis, "IDropSource");

    return OleDoc_Release(lpOleDoc);
}


STDMETHODIMP    OleDoc_DropSource_QueryContinueDrag (
    LPDROPSOURCE            lpThis,
    BOOL                    fEscapePressed,
    DWORD                   grfKeyState
){
    if (fEscapePressed)
        return ResultFromScode(DRAGDROP_S_CANCEL);
    else if (!(grfKeyState & MK_LBUTTON))
        return ResultFromScode(DRAGDROP_S_DROP);
    else
        return NOERROR;
}


STDMETHODIMP    OleDoc_DropSource_GiveFeedback (
    LPDROPSOURCE            lpThis,
    DWORD                   dwEffect
)
{
    // Tell OLE to use the standard drag/drop feedback cursors
    return ResultFromScode(DRAGDROP_S_USEDEFAULTCURSORS);

#if defined( IF_SPECIAL_DD_CURSORS_NEEDED )
    switch (dwEffect) {

        case DROPEFFECT_NONE:
            SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragNone );
            break;

        case DROPEFFECT_COPY:
            SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragCopy );
            break;

        case DROPEFFECT_MOVE:
            SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragMove );
            break;

        case DROPEFFECT_LINK:
            SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragLink );
            break;

    }

    return NOERROR;
#endif

}

/*************************************************************************
** OleDoc::IDropTarget interface implementation
*************************************************************************/

STDMETHODIMP OleDoc_DropTarget_QueryInterface(
        LPDROPTARGET        lpThis,
        REFIID              riid,
        LPVOID FAR*         lplpvObj
)
{
    LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;

    return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
}


STDMETHODIMP_(ULONG) OleDoc_DropTarget_AddRef(LPDROPTARGET lpThis)
{
    LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;

    OleDbgAddRefMethod(lpThis, "IDropTarget");

    return OleDoc_AddRef(lpOleDoc);
}


STDMETHODIMP_(ULONG) OleDoc_DropTarget_Release ( LPDROPTARGET lpThis)
{
    LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;

    OleDbgReleaseMethod(lpThis, "IDropTarget");

    return OleDoc_Release(lpOleDoc);
}


STDMETHODIMP    OleDoc_DropTarget_DragEnter (
    LPDROPTARGET            lpThis,
    LPDATAOBJECT            lpDataObj,
    DWORD                   grfKeyState,
    POINTL                  pointl,
    LPDWORD                 lpdwEffect
)
{
    LPOLEAPP   lpOleApp = (LPOLEAPP)g_lpApp;
    LPOLEDOC   lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;
    LPLINELIST lpLL     = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
    BOOL       fDragScroll;

    OLEDBG_BEGIN2("OleDoc_DropTarget_DragEnter\r\n")

    lpOleDoc->m_fDragLeave              = FALSE;
    lpOleDoc->m_dwTimeEnterScrollArea   = 0;
    lpOleDoc->m_lastdwScrollDir         = SCROLLDIR_NULL;


    /* Determine if the drag source data object offers a data format
    **    that we can copy and/or link to.
    */

    lpOleDoc->m_fCanDropCopy = OleDoc_QueryPasteFromData(
            lpOleDoc,
            lpDataObj,
            FALSE   /* fLink */
    );

    lpOleDoc->m_fCanDropLink = OleDoc_QueryPasteFromData(
            lpOleDoc,
            lpDataObj,
            TRUE   /* fLink */
    );

    fDragScroll = OleDoc_DoDragScroll ( lpOleDoc, pointl );

    if (OleDoc_QueryDrop(lpOleDoc,grfKeyState,pointl,fDragScroll,lpdwEffect))
        LineList_SetDragOverLineFromPointl( lpLL, pointl );

    OLEDBG_END2
    return NOERROR;

}

STDMETHODIMP OleDoc_DropTarget_DragOver (
    LPDROPTARGET            lpThis,
    DWORD                   grfKeyState,
    POINTL                  pointl,
    LPDWORD                 lpdwEffect
)
{
    LPOLEAPP   lpOleApp = (LPOLEAPP)g_lpApp;
    LPOLEDOC   lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;
    LPLINELIST lpLL   = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
    BOOL       fDragScroll;

    fDragScroll = OleDoc_DoDragScroll ( lpOleDoc, pointl );

    if (OleDoc_QueryDrop(lpOleDoc,grfKeyState, pointl,fDragScroll,lpdwEffect))
        LineList_SetDragOverLineFromPointl( lpLL, pointl );
    else
        LineList_RestoreDragFeedback( lpLL );

    return NOERROR;
}


STDMETHODIMP    OleDoc_DropTarget_DragLeave ( LPDROPTARGET lpThis)
{
    LPOLEDOC   lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;
    LPLINELIST lpLL     = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;

    OLEDBG_BEGIN2("OleDoc_DropTarget_DragLeave\r\n")

    lpOleDoc->m_fDragLeave = TRUE;

    LineList_RestoreDragFeedback( lpLL );

    OLEDBG_END2
    return NOERROR;

}

STDMETHODIMP    OleDoc_DropTarget_Drop (
    LPDROPTARGET            lpThis,
    LPDATAOBJECT            lpDataObj,
    DWORD                   grfKeyState,
    POINTL                  pointl,
    LPDWORD                 lpdwEffect
)
{
    LPOLEDOC   lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;
    LPLINELIST lpLL     = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;

    OLEDBG_BEGIN2("OleDoc_DropTarget_Drop\r\n")

    lpOleDoc->m_fDragLeave = TRUE;
    lpOleDoc->m_fLocalDrop = TRUE;

    LineList_RestoreDragFeedback( lpLL );
    SetFocus( LineList_GetWindow( lpLL) );

    if (OleDoc_QueryDrop(lpOleDoc, grfKeyState, pointl, FALSE, lpdwEffect)) {
        BOOL fLink     = (*lpdwEffect == DROPEFFECT_LINK);
        int iFocusLine = LineList_GetFocusLineIndex( lpLL );
        BOOL fStatus;

        OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpOleDoc, FALSE );
        LineList_SetFocusLineFromPointl ( lpLL, pointl );

        fStatus = OleDoc_PasteFromData(
                lpOleDoc,
                lpDataObj,
                lpOleDoc->m_fLocalDrag, /* data source is local to app */
                fLink
        );

        // if drop was unsuccessfull, restore the original focus line
        if (! fStatus)
            LineList_SetFocusLine( lpLL, (WORD)iFocusLine );

#if defined( INPLACE_CNTR )
        {
            LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;

            /* OLE2NOTE: if there is currently a UIActive OLE object,
            **    then we must tell it to UIDeactivate after
            **    the drop has completed.
            */
            if (lpContainerDoc->m_lpLastUIActiveLine) {
                ContainerLine_UIDeactivate(
                        lpContainerDoc->m_lpLastUIActiveLine);
            }
        }
#endif

#if defined( INPLACE_SVR )
        {
            /* OLE2NOTE: if the drop was into a in-place visible
            **    (in-place active but NOT UIActive object), then we
            **    want to UIActivate the object after the drop is
            **    complete. 
            */
            ServerDoc_UIActivate((LPSERVERDOC) lpOleDoc);
        }
#endif


		/* if it is a local Drag/Drop move, don't enable redraw.
        **    after the source is done deleting the moved lines, it
        **    will re-enable redraw
        */
        if (! (lpOleDoc->m_fLocalDrag
            && (*lpdwEffect & DROPEFFECT_MOVE) != 0 ))
            OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpOleDoc, TRUE );
    }

    OLEDBG_END2
    return NOERROR;
}


#endif  // USE_DRAGDROP

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.