DROPTGT.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:13k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * DROPTGT.CPP
  3.  * Patron Chapter 13
  4.  *
  5.  * Implementation of a DropTarget object
  6.  *
  7.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  8.  *
  9.  * Kraig Brockschmidt, Microsoft
  10.  * Internet  :  kraigb@microsoft.com
  11.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  12.  */
  13. #include "patron.h"
  14. /*
  15.  * CDropTarget::CDropTarget
  16.  * CDropTarget::~CDropTarget
  17.  *
  18.  * Constructor Parameters:
  19.  *  pDoc            PCPatronDoc of the window containing us.
  20.  */
  21. CDropTarget::CDropTarget(PCPatronDoc pDoc)
  22.     {
  23.     m_cRef=0;
  24.     m_pDoc=pDoc;
  25.     m_pIDataObject=NULL;
  26.     return;
  27.     }
  28. CDropTarget::~CDropTarget(void)
  29.     {
  30.     return;
  31.     }
  32. /*
  33.  * CDropTarget::QueryInterface
  34.  * CDropTarget::AddRef
  35.  * CDropTarget::Release
  36.  *
  37.  * Purpose:
  38.  *  IUnknown members for CDropTarget object.
  39.  */
  40. STDMETHODIMP CDropTarget::QueryInterface(REFIID riid, PPVOID ppv)
  41.     {
  42.     *ppv=NULL;
  43.     if (IID_IUnknown==riid || IID_IDropTarget==riid)
  44.         *ppv=this;
  45.     if (NULL!=*ppv)
  46.         {
  47.         ((LPUNKNOWN)*ppv)->AddRef();
  48.         return NOERROR;
  49.         }
  50.     return ResultFromScode(E_NOINTERFACE);
  51.     }
  52. STDMETHODIMP_(ULONG) CDropTarget::AddRef(void)
  53.     {
  54.     return ++m_cRef;
  55.     }
  56. STDMETHODIMP_(ULONG) CDropTarget::Release(void)
  57.     {
  58.     if (0!=--m_cRef)
  59.         return m_cRef;
  60.     delete this;
  61.     return 0;
  62.     }
  63. /*
  64.  * CDropTarget::DragEnter
  65.  *
  66.  * Purpose:
  67.  *  Indicates that data in a drag operation has been dragged over
  68.  *  our window that's a potential target.  We are to decide if it's
  69.  *  something in which we're interested.
  70.  *
  71.  * Parameters:
  72.  *  pIDataSource    LPDATAOBJECT providing the source data.
  73.  *  grfKeyState     DWORD flags: states of keys and mouse buttons.
  74.  *  pt              POINTL coordinates in the client space of
  75.  *                  the document.
  76.  *  pdwEffect       LPDWORD into which we'll place the appropriate
  77.  *                  effect flag for this point.
  78.  *
  79.  * Return Value:
  80.  *  HRESULT         NOERROR
  81.  */
  82. STDMETHODIMP CDropTarget::DragEnter(LPDATAOBJECT pIDataSource
  83.     , DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
  84.     {
  85.     PCPages         ppg=m_pDoc->m_pPG;
  86.     HWND            hWnd;
  87.     FORMATETC       fe;
  88.     STGMEDIUM       stm;
  89.     UINT            uRet;
  90.     m_fFeedback=FALSE;
  91.     m_pIDataObject=NULL;
  92.     if (!m_pDoc->FQueryPasteFromData(pIDataSource, &fe, NULL))
  93.         {
  94.         *pdwEffect=DROPEFFECT_NONE;
  95.         return NOERROR;
  96.         }
  97.     //Check if this is a valid drop point.
  98.     uRet=ppg->UTestDroppablePoint(&pt);
  99.     ppg->m_uLastTest=uRet;
  100.     if (UDROP_NONE==uRet)
  101.         *pdwEffect=DROPEFFECT_NONE;
  102.     else
  103.         {
  104.         //Default is move if we can, in fact drop here.
  105.         *pdwEffect=DROPEFFECT_MOVE;
  106.         if (grfKeyState & MK_CONTROL)
  107.             *pdwEffect=DROPEFFECT_COPY;
  108.         }
  109.     m_pIDataObject=pIDataSource;
  110.     m_pIDataObject->AddRef();
  111.     /*
  112.      * Determine the size of the data, if we can.  The default is
  113.      * a small rectangle since we can't easily tell what size
  114.      * something will be if we're pulling in a metafile or bitmap.
  115.      * It's not a good idea to render it here with GetData just to
  116.      * find that out. We only know the size if it's our own object
  117.      * in which case a GetData will be fast.
  118.      */
  119.     if (fe.cfFormat==m_pDoc->m_cf)
  120.         {
  121.         if (SUCCEEDED(pIDataSource->GetData(&fe, &stm)))
  122.             {
  123.             PPATRONOBJECT   ppo;
  124.             RECT            rc;
  125.             ppo=(PPATRONOBJECT)GlobalLock(stm.hGlobal);
  126.             SetRect(&rc, (int)ppo->szl.cx, -(int)ppo->szl.cy, 0, 0);
  127.             RectConvertMappings(&rc, NULL, TRUE);
  128.             SETSIZEL(m_szl, rc.left, rc.top);
  129.             m_ptPick=ppo->ptlPick;
  130.             m_fe=ppo->fe;
  131.             GlobalUnlock(stm.hGlobal);
  132.             ReleaseStgMedium(&stm);
  133.             }
  134.         }
  135.     else
  136.         {
  137.         SETSIZEL(m_szl, 30, 30);
  138.         m_ptPick.x=0;
  139.         m_ptPick.y=0;
  140.         m_fe.cfFormat=0;
  141.         }
  142.     //Bring the document window up front, show what a drop will do.
  143.     hWnd=m_pDoc->Window();
  144.     BringWindowToTop(hWnd);
  145.     UpdateWindow(hWnd);
  146.     ppg->m_uVScrollCode=NOVALUE;
  147.     ppg->m_uHScrollCode=NOVALUE;
  148.     m_fPendingRepaint=FALSE;
  149.     pt.x-=m_ptPick.x;
  150.     pt.y-=m_ptPick.y;
  151.     m_ptLast=pt;
  152.     m_fFeedback=TRUE;
  153.     ppg->DrawDropTargetRect(&pt, &m_szl);
  154.     return NOERROR;
  155.     }
  156. /*
  157.  * CDropTarget::DragOver
  158.  *
  159.  * Purpose:
  160.  *  Indicates that the mouse was moved inside the window represented
  161.  *  by this drop target.  This happens on every WM_MOUSEMOVE, so
  162.  *  this function should be very efficient.
  163.  *
  164.  * Parameters:
  165.  *  grfKeyState     DWORD providing the current keyboard and
  166.  *                  mouse states
  167.  *  pt              POINTL where the mouse currently is.
  168.  *  pdwEffect       LPDWORD in which to store the effect flag
  169.  *                  for this point.
  170.  *
  171.  * Return Value:
  172.  *  HRESULT         NOERROR
  173.  */
  174. STDMETHODIMP CDropTarget::DragOver(DWORD grfKeyState, POINTL pt
  175.     , LPDWORD pdwEffect)
  176.     {
  177.     PCPages     ppg=m_pDoc->m_pPG;
  178.     UINT        uRet, uLast;
  179.     UINT        xPos, yPos;
  180.     *pdwEffect=DROPEFFECT_NONE;
  181.     if (NULL==m_pIDataObject)
  182.         return NOERROR;
  183.     //Check if this is still a valid point.  uRet used below as well
  184.     uRet=ppg->UTestDroppablePoint(&pt);
  185.     if (UDROP_NONE==uRet)
  186.         *pdwEffect=DROPEFFECT_NONE;
  187.     else
  188.         {
  189.         //Store these before possibly ORing in DROPEFFECT_SCROLL
  190.         *pdwEffect=DROPEFFECT_MOVE;
  191.         if (grfKeyState & MK_CONTROL)
  192.             *pdwEffect=DROPEFFECT_COPY;
  193.         }
  194.     //If we haven't moved and we are not scrolling, then we're done.
  195.     if ((pt.x-m_ptPick.x==m_ptLast.x)
  196.         && (pt.y-m_ptPick.y==m_ptLast.y)
  197.         && !((UDROP_INSETHORZ|UDROP_INSETVERT) & ppg->m_uLastTest))
  198.         {
  199.         return NOERROR;
  200.         }
  201.     //Remove the last feedback rectangle.
  202.     if (m_fFeedback)
  203.         ppg->DrawDropTargetRect(&m_ptLast, &m_szl);
  204.     uLast=ppg->m_uLastTest;
  205.     ppg->m_uLastTest=uRet;
  206.     if (UDROP_NONE==uRet)
  207.         {
  208.         //If we're now an invalid point, better repaint as necessary
  209.         if (m_fPendingRepaint)
  210.             {
  211.             UpdateWindow(ppg->m_hWnd);
  212.             m_fPendingRepaint=FALSE;
  213.             }
  214.         ppg->m_uVScrollCode=NOVALUE;
  215.         ppg->m_uHScrollCode=NOVALUE;
  216.         m_fFeedback=FALSE;
  217.         return NOERROR;
  218.         }
  219.     /*
  220.      * Scrolling is a little tricky:  We get a DragOver pulse even
  221.      * if we didn't move.  First we have to delay scrolling for
  222.      * ppg->m_uScrollDelay clock ticks which we can determine using
  223.      * GetTickCount.  Timers do not work here since we may not be
  224.      * yielding to our message loop.
  225.      *
  226.      * Once we know we are scrolling then we determine if we
  227.      * scroll again or if we reset the scrolling state.
  228.      */
  229.     if ((UDROP_INSETHORZ & uLast) && !(UDROP_INSETHORZ & uRet))
  230.         ppg->m_uHScrollCode=NOVALUE;
  231.     if (!(UDROP_INSETHORZ & uLast) && (UDROP_INSETHORZ & uRet))
  232.         {
  233.         ppg->m_dwTimeLast=GetTickCount();
  234.         ppg->m_uHScrollCode=(0!=(UDROP_INSETLEFT & uRet))
  235.             ? SB_LINELEFT : SB_LINERIGHT; //Same as UP & DOWN codes.
  236.         }
  237.     if ((UDROP_INSETVERT & uLast) && !(UDROP_INSETVERT & uRet))
  238.         ppg->m_uVScrollCode=NOVALUE;
  239.     if (!(UDROP_INSETVERT & uLast) && (UDROP_INSETVERT & uRet))
  240.         {
  241.         ppg->m_dwTimeLast=GetTickCount();
  242.         ppg->m_uVScrollCode=(0!=(UDROP_INSETTOP & uRet))
  243.             ? SB_LINEUP : SB_LINEDOWN;
  244.         }
  245.     //Only change the last time if ALL scrolling stops.
  246.     if (NOVALUE==ppg->m_uHScrollCode && NOVALUE==ppg->m_uVScrollCode)
  247.         ppg->m_dwTimeLast=0L;
  248.     //Set the scroll effect on any inset hit.
  249.     if ((UDROP_INSETHORZ | UDROP_INSETVERT) & uRet)
  250.         *pdwEffect |= DROPEFFECT_SCROLL;
  251.     xPos=ppg->m_xPos;
  252.     yPos=ppg->m_yPos;
  253.     //Has the delay elapsed?  We can scroll if so
  254.     if (ppg->m_dwTimeLast!=0
  255.         && (GetTickCount()-ppg->m_dwTimeLast)
  256.         > (DWORD)ppg->m_uScrollDelay)
  257.         {
  258.         if (NOVALUE!=ppg->m_uHScrollCode)
  259.             {
  260.             m_fPendingRepaint=TRUE;
  261.             SendMessage(ppg->m_hWnd, WM_HSCROLL
  262.                 , ppg->m_uHScrollCode, 0L);
  263.             }
  264.         if (NOVALUE!=ppg->m_uVScrollCode)
  265.             {
  266.             m_fPendingRepaint=TRUE;
  267.             SendMessage(ppg->m_hWnd, WM_VSCROLL
  268.                 , ppg->m_uVScrollCode, 0L);
  269.             }
  270.         }
  271.     //If we didn't scroll but have a pending repaint, do it now.
  272.     if (xPos==ppg->m_xPos && yPos==ppg->m_yPos && m_fPendingRepaint)
  273.         {
  274.         UpdateWindow(ppg->m_hWnd);
  275.         m_fPendingRepaint=FALSE;
  276.         }
  277.     pt.x-=m_ptPick.x;
  278.     pt.y-=m_ptPick.y;
  279.     m_ptLast=pt;
  280.     m_fFeedback=TRUE;
  281.     ppg->DrawDropTargetRect(&pt, &m_szl);
  282.     return NOERROR;
  283.     }
  284. /*
  285.  * CDropTarget::DragLeave
  286.  *
  287.  * Purpose:
  288.  *  Informs the drop target that the operation has left its window.
  289.  *
  290.  * Parameters:
  291.  *  None
  292.  *
  293.  * Return Value:
  294.  *  HRESULT         NOERROR
  295.  */
  296. STDMETHODIMP CDropTarget::DragLeave(void)
  297.     {
  298.     PCPages         ppg=m_pDoc->m_pPG;
  299.     if (NULL==m_pIDataObject)
  300.         return NOERROR;
  301.     //Stop scrolling
  302.     ppg->m_uHScrollCode=NOVALUE;
  303.     ppg->m_uVScrollCode=NOVALUE;
  304.     if (m_fPendingRepaint)
  305.         UpdateWindow(ppg->m_hWnd);
  306.     //Remove the last feedback rectangle.
  307.     if (m_fFeedback)
  308.         ppg->DrawDropTargetRect(&m_ptLast, &m_szl);
  309.     m_fFeedback=FALSE;
  310.     m_pIDataObject->Release();
  311.     return NOERROR;
  312.     }
  313. /*
  314.  * CDropTarget::Drop
  315.  *
  316.  * Purpose:
  317.  *  Instructs the drop target to paste the data that was just now
  318.  *  dropped on it.
  319.  *
  320.  * Parameters:
  321.  *  pIDataSource    LPDATAOBJECT from which we'll paste.
  322.  *  grfKeyState     DWORD providing current keyboard/mouse state.
  323.  *  pt              POINTL at which the drop occurred.
  324.  *  pdwEffect       LPDWORD in which to store what you did.
  325.  *
  326.  * Return Value:
  327.  *  HRESULT         NOERROR
  328.  */
  329. STDMETHODIMP CDropTarget::Drop(LPDATAOBJECT pIDataSource
  330.     , DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
  331.     {
  332.     PCPages         ppg=m_pDoc->m_pPG;
  333.     BOOL            fRet=TRUE;
  334.     FORMATETC       fe;
  335.     TENANTTYPE      tType;
  336.     PATRONOBJECT    po;
  337.     POINT           ptS;
  338.     *pdwEffect=DROPEFFECT_NONE;
  339.     if (NULL==m_pIDataObject)
  340.         return ResultFromScode(E_FAIL);
  341.     if (UDROP_NONE==ppg->UTestDroppablePoint(&pt))
  342.         return ResultFromScode(E_FAIL);
  343.     //Stop scrolling
  344.     ppg->m_uHScrollCode=NOVALUE;
  345.     ppg->m_uVScrollCode=NOVALUE;
  346.     if (m_fPendingRepaint)
  347.         UpdateWindow(ppg->m_hWnd);
  348.     //2.  Remove the UI feedback
  349.     if (m_fFeedback)
  350.         ppg->DrawDropTargetRect(&m_ptLast, &m_szl);
  351.     m_pIDataObject->Release();
  352.     /*
  353.      * Check if we can do the paste, and if so, tell our pasting
  354.      * mechanism exactly where to place us.
  355.      */
  356.     pt.x-=m_ptPick.x;
  357.     pt.y-=m_ptPick.y;
  358.     POINTFROMPOINTL(ptS, pt);
  359.     ScreenToClient(ppg->Window(), &ptS);
  360.     POINTLFROMPOINT(po.ptl, ptS);
  361.     //This is true if we didn't see placement data in DragEnter
  362.     if (0!=m_fe.cfFormat)
  363.         {
  364.         po.szl.cx=m_szl.cx;         //We stored these positive
  365.         po.szl.cy=-m_szl.cy;
  366.         }
  367.     else
  368.         SETSIZEL(po.szl, 0, 0); //Ask object for its size.
  369.     //Adjust for scrolling and mapping mode.
  370.     ppg->AdjustPosition(&po.ptl, &po.szl);
  371.     /*
  372.      * If we're in the same document and moving, then we can just
  373.      * stuff the Pages' m_ptDrop which will move us and return.
  374.      */
  375.     if (ppg->m_fDragSource && !(grfKeyState & MK_CONTROL))
  376.         {
  377.         *pdwEffect=DROPEFFECT_MOVE;
  378.         ppg->m_fMoveInPage=TRUE;
  379.         ppg->m_ptDrop=po.ptl;
  380.         return NOERROR;
  381.         }
  382.     /*
  383.      * Otherwise, paste either from another document or from
  384.      * the same document which will always be a copy to the new
  385.      * point.
  386.      */
  387.     ppg->m_fMoveInPage=FALSE;
  388.     fRet=m_pDoc->FQueryPasteFromData(pIDataSource, &fe, &tType);
  389.     if (fRet)
  390.         {
  391.         //Copy the real format if we have placement data.
  392.         po.fe=(m_pDoc->m_cf==fe.cfFormat) ? m_fe : fe;
  393.         fRet=m_pDoc->PasteFromData(pIDataSource, &fe, tType
  394.             , &po, 0);
  395.         }
  396.     if (!fRet)
  397.         return ResultFromScode(E_FAIL);
  398.     *pdwEffect=DROPEFFECT_MOVE;
  399.     if (grfKeyState & MK_CONTROL)
  400.         *pdwEffect=DROPEFFECT_COPY;
  401.     return NOERROR;
  402.     }