home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / drgthr.zip / drag.c < prev    next >
C/C++ Source or Header  |  1993-07-20  |  35KB  |  745 lines

  1. /*********************************************************************
  2.  *                                                                   *
  3.  * MODULE NAME :  drag.c                 AUTHOR:  Rick Fishman       *
  4.  * DATE WRITTEN:  07-16-93                                           *
  5.  *                                                                   *
  6.  * MODULE DESCRIPTION:                                               *
  7.  *                                                                   *
  8.  *  Part of the 'DRGTHRND' drag/drop sample program.                 *
  9.  *                                                                   *
  10.  *  This module handles all the Drag/Drop processing for the         *
  11.  *  DRGTHRND.EXE sample program. The rendering code is split into    *
  12.  *  srcrendr.c and trgrendr.c for the source and target respectively.*
  13.  *                                                                   *
  14.  * NOTES:                                                            *
  15.  *                                                                   *
  16.  * FUNCTIONS AVALABLE TO OTHER MODULES:                              *
  17.  *                                                                   *
  18.  *   dragInit                                                        *
  19.  *   dragOver                                                        *
  20.  *   dragDrop                                                        *
  21.  *   dragTargetCleanup                                               *
  22.  *   dragSourceCleanup                                               *
  23.  *                                                                   *
  24.  * HISTORY:                                                          *
  25.  *                                                                   *
  26.  *  07-16-93 - Program coded.                                        *
  27.  *                                                                   *
  28.  *  Rick Fishman                                                     *
  29.  *  Code Blazers, Inc.                                               *
  30.  *  4113 Apricot                                                     *
  31.  *  Irvine, CA. 92720                                                *
  32.  *  CIS ID: 72251,750                                                *
  33.  *                                                                   *
  34.  *********************************************************************/
  35.  
  36. #pragma strings(readonly)   // used for debug version of memory mgmt routines
  37.  
  38. /*********************************************************************/
  39. /*------- Include relevant sections of the OS/2 header files --------*/
  40. /*********************************************************************/
  41.  
  42. #define  INCL_DOSERRORS
  43. #define  INCL_DOSPROCESS
  44. #define  INCL_SHLERRORS
  45. #define  INCL_WINDIALOGS
  46. #define  INCL_WINERRORS
  47. #define  INCL_WINFRAMEMGR
  48. #define  INCL_WININPUT
  49. #define  INCL_WINMENUS
  50. #define  INCL_WINSTDCNR
  51. #define  INCL_WINSTDDRAG
  52. #define  INCL_WINWINDOWMGR
  53.  
  54. /**********************************************************************/
  55. /*----------------------------- INCLUDES -----------------------------*/
  56. /**********************************************************************/
  57.  
  58. #include <os2.h>
  59. #include <stdio.h>
  60. #include <stdlib.h>
  61. #include <string.h>
  62. #include "drgthrnd.h"
  63.  
  64. /*********************************************************************/
  65. /*------------------- APPLICATION DEFINITIONS -----------------------*/
  66. /*********************************************************************/
  67.  
  68.  
  69. /**********************************************************************/
  70. /*---------------------------- STRUCTURES ----------------------------*/
  71. /**********************************************************************/
  72.  
  73.  
  74. /**********************************************************************/
  75. /*----------------------- FUNCTION PROTOTYPES ------------------------*/
  76. /**********************************************************************/
  77.  
  78. int  CountSelectedRecs   ( HWND hwndFrame, PCNRREC pCnrRecUnderMouse,
  79.                            PBOOL pfUseSelectedRecs );
  80. void SetSelectedDragItems( HWND hwndFrame, int cRecs, PDRAGINFO pDragInfo,
  81.                            PDRAGIMAGE pDragImage );
  82. void SetOneDragItem      ( HWND hwndFrame, PCNRREC pCnrRecUnderMouse,
  83.                            PDRAGINFO pDragInfo, PDRAGIMAGE pDragImage,
  84.                            int iOffset );
  85. void RemoveSourceEmphasis( HWND hwndFrame );
  86.  
  87. /**********************************************************************/
  88. /*------------------------ GLOBAL VARIABLES --------------------------*/
  89. /**********************************************************************/
  90.  
  91.  
  92. /**********************************************************************/
  93. /*--------------------------- dragMessage ----------------------------*/
  94. /*                                                                    */
  95. /*  A DM_ MESSAGE WAS RECEIVED BY THE FRAME WINDOW PROCEDURE.         */
  96. /*                                                                    */
  97. /*  PARMS: frame window handle,                                       */
  98. /*         message id,                                                */
  99. /*         mp1 of the message                                         */
  100. /*                                                                    */
  101. /*  NOTES:                                                            */
  102. /*                                                                    */
  103. /*  RETURNS: return code of message                                   */
  104. /*                                                                    */
  105. /*--------------------------------------------------------------------*/
  106. /**********************************************************************/
  107. MRESULT dragMessage( HWND hwndFrame, ULONG msg, MPARAM mp1 )
  108. {
  109.     switch( msg )
  110.     {
  111.         // The target sends this to the source before it sends the DM_RENDER
  112.         // message if the source specified DC_PREPARE in DRAGITEM.fsControl.
  113.  
  114.         case DM_RENDERPREPARE:
  115.  
  116.             // In srcrendr.c
  117.  
  118.             return srcRenderPrepare( hwndFrame, (PDRAGTRANSFER) mp1 );
  119.     }
  120.  
  121.     return 0;
  122. }
  123.  
  124. /**********************************************************************/
  125. /*----------------------------- dragInit -----------------------------*/
  126. /*                                                                    */
  127. /*  PROCESS CN_INITDRAG NOTIFY MESSAGE.                               */
  128. /*                                                                    */
  129. /*  PARMS: frame window handle,                                       */
  130. /*         pointer to the CNRDRAGINIT structure                       */
  131. /*                                                                    */
  132. /*  NOTES: the CN_INITDRAG message is equivalent to the WM_BEGINDRAG  */
  133. /*         message. The reason I mention this is because if the source*/
  134. /*         window in the drag is not a container you will get the     */
  135. /*         WM_BEGINDRAG message.                                      */
  136. /*                                                                    */
  137. /*         WM_BEGINDRAG is sent to windows to allow them to know that */
  138. /*         the user is requesting a drag from their window. This      */
  139. /*         message contains only the x,y coordinates of the mouse at  */
  140. /*         the time of WM_BEGINDRAG.                                  */
  141. /*                                                                    */
  142. /*         The reason for CN_INITDRAG is first so that the container  */
  143. /*         can notify its owner when it gets a WM_BEGINDRAG message   */
  144. /*         and second so that the container can give its owner more   */
  145. /*         info, like what container record the mouse pointer is over.*/
  146. /*         To accomplish this, the container packages up this informa-*/
  147. /*         tion in a CNRDRAGINIT structure and sends that structure   */
  148. /*         along with the CN_INITDRAG message.                        */
  149. /*                                                                    */
  150. /*  RETURNS: nothing                                                  */
  151. /*                                                                    */
  152. /*--------------------------------------------------------------------*/
  153. /**********************************************************************/
  154. void dragInit( HWND hwndFrame, PCNRDRAGINIT pcdi )
  155. {
  156.     PCNRREC     pCnrRecUnderMouse = (PCNRREC) pcdi->pRecord;
  157.     PDRAGIMAGE  pDragImage = NULL;
  158.     PDRAGINFO   pDragInfo = NULL;
  159.     BOOL        fUseSelectedRecs;
  160.     PINSTANCE   pi = INSTDATA( hwndFrame );
  161.     int         cRecs;
  162.  
  163.     if( !pi )
  164.     {
  165.         Msg( "dragInit cant get Inst data RC(%X)", HWNDERR( hwndFrame ) );
  166.         return;
  167.     }
  168.  
  169.     // pSavedDragInfo is used during drop processing. When the drop is complete
  170.     // (the source gets a DM_ENDCONVERSATION message from the target), the
  171.     // source will free the DRAGINFO structure and set this field to NULL.
  172.     // So pSavedDragInfo is non-NULL if a drop has not yet completed. In this
  173.     // case we make it easy on ourselves by not allowing another drag. The
  174.     // reason for this is that if we allow another drag to take place we will
  175.     // need to overwrite this pSavedDragInfo field in which case the drop
  176.     // processing would not free the right DRAGINFO structure. Obviously in a
  177.     // commercial app you'd want to use a different mechanism for storing the
  178.     // DRAGINFO structure, like a linked list, so you could start another drag
  179.     // while the drop is in progress.
  180.  
  181.     if( pi->pSavedDragInfo )
  182.     {
  183.         WinAlarm( HWND_DESKTOP, WA_WARNING );
  184.         return;
  185.     }
  186.  
  187.     // Count the records that have CRA_SELECTED emphasis. Also return whether
  188.     // or not we should process the CRA_SELECTED records. If the container
  189.     // record under the mouse does not have this emphasis, we shouldn't. In that
  190.     // case we would just process the record under the mouse.
  191.  
  192.  
  193.     cRecs = CountSelectedRecs( hwndFrame, pCnrRecUnderMouse, &fUseSelectedRecs);
  194.  
  195.     if( cRecs )
  196.     {
  197.         int iDragImageArraySize = cRecs * sizeof( DRAGIMAGE );
  198.  
  199.         // Allocate an array of DRAGIMAGE structures. Each structure contains
  200.         // info about an image that will be under the mouse pointer during the
  201.         // drag. This image will represent a container record being dragged.
  202.  
  203.         pDragImage = (PDRAGIMAGE) malloc( iDragImageArraySize );
  204.  
  205.         if( pDragImage )
  206.         {
  207.             memset( pDragImage, 0, iDragImageArraySize );
  208.  
  209.             // Let PM allocate enough memory for a DRAGINFO structure as well
  210.             // as a DRAGITEM structure for each record being dragged. It will
  211.             // allocate shared memory so other processes can participate in the
  212.             // drag/drop.
  213.  
  214.             pDragInfo = DrgAllocDraginfo( cRecs );
  215.  
  216.             if( pDragInfo )
  217.             {
  218.                 pi->pSavedDragInfo = pDragInfo;
  219.                 pi->cDragItems = cRecs;
  220.             }
  221.             else
  222.                 Msg( "DrgAllocDraginfo failed. RC(%X)", HWNDERR( hwndFrame ) );
  223.         }
  224.         else
  225.             Msg( "Out of memory in dragInit" );
  226.     }
  227.  
  228.     if( cRecs && pDragInfo && pDragImage )
  229.     {
  230.         // Set the data from the container records into the DRAGITEM and
  231.         // DRAGIMAGE structures. If we are to process CRA_SELECTED container
  232.         // records, do them all in one function. If not, pass a pointer to the
  233.         // container record under the mouse to a different function that will
  234.         // fill in just one DRAGITEM / DRAGIMAGE structure.
  235.  
  236.         if( fUseSelectedRecs )
  237.             SetSelectedDragItems( hwndFrame, cRecs, pDragInfo, pDragImage );
  238.         else
  239.             SetOneDragItem( hwndFrame, pCnrRecUnderMouse, pDragInfo,
  240.                             pDragImage, 0 );
  241.  
  242.         // If DrgDrag returns NULLHANDLE, that means the user hit Esc or F1
  243.         // while the drag was going on so the target didn't have a chance to
  244.         // delete the string handles. So it is up to the source window to do
  245.         // it. Unfortunately there doesn't seem to be a way to determine
  246.         // whether the NULLHANDLE means Esc was pressed as opposed to there
  247.         // being an error in the drag operation. So we don't attempt to figure
  248.         // that out. To us, a NULLHANDLE means Esc was pressed...
  249.  
  250.         if( !DrgDrag( hwndFrame, pDragInfo, pDragImage, cRecs, VK_ENDDRAG,
  251.                       NULL ) )
  252.         {
  253.             if( !DrgDeleteDraginfoStrHandles( pDragInfo ) )
  254.                 Msg( "dragInit DrgDeleteDraginfoStrHandles RC(%X)",
  255.                      HWNDERR( hwndFrame ) );
  256.  
  257.             if( !DrgFreeDraginfo( pDragInfo ) )
  258.                 Msg( "dragInit DrgFreeDraginfo RC(%X)", HWNDERR( hwndFrame ) );
  259.  
  260.             pi->pSavedDragInfo = NULL;
  261.         }
  262.  
  263.         // Take off source emphasis from the records that were dragged
  264.  
  265.         RemoveSourceEmphasis( hwndFrame );
  266.     }
  267.  
  268.     if( pDragImage )
  269.         free( pDragImage );
  270. }
  271.  
  272. /**********************************************************************/
  273. /*----------------------------- dragOver -----------------------------*/
  274. /*                                                                    */
  275. /*  PROCESS CN_DRAGOVER NOTIFY MESSAGE.                               */
  276. /*                                                                    */
  277. /*  PARMS: frame window handle,                                       */
  278. /*         pointer to the CNRDRAGINFO structure                       */
  279. /*                                                                    */
  280. /*  NOTES: The container sends the CN_DRAGOVER message to its owner   */
  281. /*         when it gets a DM_DRAGOVER message. The container takes    */
  282. /*         the info it gets on the DM_DRAGOVER message and combines   */
  283. /*         it with other container-specific dragover info into a      */
  284. /*         CNRDRAGINFO structure, then passes a pointer to that       */
  285. /*         structure to its owner in the CN_DRAGOVER message.         */
  286. /*                                                                    */
  287. /*         In this program, all we care about is that the other       */
  288. /*         window can handle the DRM_FISHMAN protocol and that the    */
  289. /*         window is not trying to drop on itself. Strangely enough,  */
  290. /*         the DRM_FISHMAN protocol is not in widespread use <g>.     */
  291. /*                                                                    */
  292. /*  RETURNS: return value from CN_DRAGOVER processing                 */
  293. /*                                                                    */
  294. /*--------------------------------------------------------------------*/
  295. /**********************************************************************/
  296. MRESULT dragOver( HWND hwndFrame, PCNRDRAGINFO pcdi )
  297. {
  298.     USHORT    usDrop, usDefaultOp;
  299.     PDRAGINFO pDragInfo = pcdi->pDragInfo;
  300.     PDRAGITEM pDragItem;
  301.  
  302.     if( !DrgAccessDraginfo( pDragInfo ) )
  303.     {
  304.         Msg( "dragOver DrgAccessDraginfo RC(%X)", HWNDERR( hwndFrame ) );
  305.         return MRFROM2SHORT( DOR_NEVERDROP, 0 );
  306.     }
  307.  
  308.     // Don't allow a window to drop on itself
  309.  
  310.     if( pDragInfo->hwndSource == hwndFrame )
  311.         return MRFROM2SHORT( DOR_NEVERDROP, 0 );
  312.  
  313.     // We're only concerned with the first item being dragged. We "assume" that
  314.     // if the first item is using the DRM_FISHMAN protocol then all others are.
  315.     // In a real-world program you would want to check all dragitems.
  316.  
  317.     pDragItem = DrgQueryDragitemPtr( pDragInfo, 0 );
  318.  
  319.     if( pDragItem )
  320.     {
  321.         // We will only allow DRM_FISHMAN items to be dropped on us
  322.  
  323.         if( DrgVerifyRMF( pDragItem, "DRM_FISHMAN", NULL ) )
  324.         {
  325.             usDrop = DOR_DROP;
  326.  
  327.             // We only allow a logical 'copy' operation to take place, so this
  328.             // will change the pointer to be a 'copy' (halftoned) pointer
  329.             // during the drag when the pointer is over our window.
  330.  
  331.             usDefaultOp = DO_COPY;
  332.         }
  333.         else
  334.         {
  335.             usDrop = DOR_NEVERDROP;
  336.             usDefaultOp = 0;
  337.         }
  338.     }
  339.     else
  340.         Msg( "dragOver DrgQueryDragitemPtr RC(%X)", HWNDERR( hwndFrame ) );
  341.  
  342.     // Free our handle to the shared memory if the source window is not in our
  343.     // process.
  344.  
  345.     if( !DrgFreeDraginfo( pDragInfo ) &&
  346.         PMERR_SOURCE_SAME_AS_TARGET != HWNDERR( hwndFrame ) )
  347.         Msg( "dragOver DrgFreeDraginfo RC(%X)", HWNDERR( hwndFrame ) );
  348.  
  349.     return MRFROM2SHORT( usDrop, usDefaultOp );
  350. }
  351.  
  352. /**********************************************************************/
  353. /*---------------------------- dragDrop ------------------------------*/
  354. /*                                                                    */
  355. /*  PROCESS CN_DROP NOTIFY MESSAGE.                                   */
  356. /*                                                                    */
  357. /*  PARMS: frame window handle,                                       */
  358. /*         pointer to the CNRDRAGINFO structure                       */
  359. /*                                                                    */
  360. /*  NOTES: The container sends the CN_DROP message to its owner when  */
  361. /*         it gets a DM_DROP message. The container takes the info it */
  362. /*         gets on the DM_DROP message and combines it with other     */
  363. /*         container-specific dragover info into a CNRDRAGINFO        */
  364. /*         structure, then passes a pointer to that structure to its  */
  365. /*         owner in the CN_DROP message.                              */
  366. /*                                                                    */
  367. /*  RETURNS: nothing                                                  */
  368. /*                                                                    */
  369. /*--------------------------------------------------------------------*/
  370. /**********************************************************************/
  371. void dragDrop( HWND hwndFrame, PCNRDRAGINFO pcdi )
  372. {
  373.     PDRAGINFO pDragInfo = pcdi->pDragInfo;
  374.     PINSTANCE pi = INSTDATA( hwndFrame );
  375.  
  376.     if( !pi )
  377.     {
  378.         Msg( "dragDrop cant get Inst data RC(%X)", HWNDERR( hwndFrame ) );
  379.         return;
  380.     }
  381.  
  382.     // Save this info so it can be used on the last DM_RENDERCOMPLETE message.
  383.  
  384.     pi->pSavedDragInfo = pDragInfo;
  385.     pi->cDragItems     = pDragInfo->cditem;
  386.     pi->hwndRender     = targCreateWindow( hwndFrame );
  387.  
  388.     // Post a message to the 'render' window which is in another thread. This
  389.     // will free up the user interface while the rendering is going on.
  390.  
  391.     if( pi->hwndRender )
  392.         WinPostMsg( pi->hwndRender, UM_DO_THE_DROP, MPFROMP( pDragInfo ),
  393.                     NULL );
  394. }
  395.  
  396. /**********************************************************************/
  397. /*------------------------- dragTargetCleanup ------------------------*/
  398. /*                                                                    */
  399. /*  FREE THE RESOURCES USED BY DRAG/DROP PROCESSING FOR THE TARGET    */
  400. /*                                                                    */
  401. /*  PARMS: frame window handle                                        */
  402. /*                                                                    */
  403. /*  NOTES:                                                            */
  404. /*                                                                    */
  405. /*  RETURNS: nothing                                                  */
  406. /*                                                                    */
  407. /*--------------------------------------------------------------------*/
  408. /**********************************************************************/
  409. void dragTargetCleanup( HWND hwndFrame )
  410. {
  411.     PINSTANCE pi = INSTDATA( hwndFrame );
  412.  
  413.     if( !pi )
  414.     {
  415.         Msg( "dragTargetCleanup cant get Inst data RC(%X)", HWNDERR(hwndFrame));
  416.         return;
  417.     }
  418.  
  419.     // It is the target's responsibility to delete the string resources. This
  420.     // one API frees all the strings in all DRAGITEM structures.
  421.  
  422.     if( !DrgDeleteDraginfoStrHandles( pi->pSavedDragInfo ) )
  423.         Msg( "dragTargetCleanup DrgDeleteDraginfoStrHandles RC(%X)",
  424.              HWNDERR( hwndFrame ) );
  425.  
  426.     if( !DrgFreeDraginfo( pi->pSavedDragInfo ) &&
  427.         PMERR_SOURCE_SAME_AS_TARGET != HWNDERR( hwndFrame ) )
  428.         Msg( "dragTargetCleanup DrgFreeDraginfo RC(%X)", HWNDERR( hwndFrame ) );
  429.  
  430.     // Terminate the Render window's thread since rendering is complete.
  431.  
  432.     if( pi->hwndRender )
  433.     {
  434.         WinPostMsg( pi->hwndRender, WM_QUIT, NULL, NULL );
  435.         pi->hwndRender = NULLHANDLE;
  436.     }
  437.  
  438.     pi->pSavedDragInfo = NULL;
  439.     pi->cDragItems     = 0;
  440.  
  441.     // Enable the Close option off the system menu that was disabled when
  442.     // rendering began.
  443.  
  444.     WinSendDlgItemMsg( hwndFrame, FID_SYSMENU, MM_SETITEMATTR,
  445.                        MPFROM2SHORT( SC_CLOSE, TRUE ),
  446.                        MPFROM2SHORT( MIA_DISABLED, 0 ) );
  447. }
  448.  
  449. /**********************************************************************/
  450. /*------------------------- dragSourceCleanup ------------------------*/
  451. /*                                                                    */
  452. /*  FREE THE RESOURCES USED BY DRAG/DROP PROCESSING FOR THE SOURCE    */
  453. /*                                                                    */
  454. /*  PARMS: frame window handle                                        */
  455. /*                                                                    */
  456. /*  NOTES:                                                            */
  457. /*                                                                    */
  458. /*  RETURNS: nothing                                                  */
  459. /*                                                                    */
  460. /*--------------------------------------------------------------------*/
  461. /**********************************************************************/
  462. void dragSourceCleanup( HWND hwndFrame )
  463. {
  464.     PINSTANCE pi = INSTDATA( hwndFrame );
  465.  
  466.     if( !pi )
  467.     {
  468.         Msg( "dragSourceCleanup cant get Inst data RC(%X)", HWNDERR(hwndFrame));
  469.         return;
  470.     }
  471.  
  472.     // Free the shared memory we got access to using DrgAccessDragInfo. If
  473.     // the source process is the same as the target process, we get the
  474.     // PMERR_SOURCE_SAME_AS_TARGET message. It's ok to get that - it just
  475.     // means that we don't need to free the structure because the target
  476.     // process already freed it.
  477.  
  478.     if( !DrgFreeDraginfo( pi->pSavedDragInfo ) &&
  479.         PMERR_SOURCE_SAME_AS_TARGET != HWNDERR( hwndFrame ) )
  480.         Msg( "dragSourceCleanup DrgFreeDraginfo RC(%X)", HWNDERR( hwndFrame ) );
  481.  
  482.     // Terminate the Render window's thread since rendering is complete.
  483.  
  484.     if( pi->hwndRender )
  485.     {
  486.         WinPostMsg( pi->hwndRender, WM_QUIT, NULL, NULL );
  487.         pi->hwndRender = NULLHANDLE;
  488.     }
  489.  
  490.     // This is important because the NULL-ness of pSavedDragInfo lets the main
  491.     // thread know that another drag is now possible.
  492.  
  493.     pi->pSavedDragInfo = NULL;
  494.     pi->cDragItems     = 0;
  495. }
  496.  
  497. /**********************************************************************/
  498. /*------------------------ CountSelectedRecs -------------------------*/
  499. /*                                                                    */
  500. /*  COUNT THE NUMBER OF RECORDS THAT ARE CURRENTLY SELECTED.          */
  501. /*                                                                    */
  502. /*  PARMS: frame window handle,                                       */
  503. /*         pointer to the record that was under the pointer,          */
  504. /*         address of BOOL - should we process selected records?      */
  505. /*                                                                    */
  506. /*  NOTES:                                                            */
  507. /*                                                                    */
  508. /*  RETURNS: number of records to process                             */
  509. /*                                                                    */
  510. /*--------------------------------------------------------------------*/
  511. /**********************************************************************/
  512. int CountSelectedRecs( HWND hwndFrame, PCNRREC pCnrRecUnderMouse,
  513.                        PBOOL pfUseSelectedRecs )
  514. {
  515.     int cRecs = 0;
  516.  
  517.     *pfUseSelectedRecs = FALSE;
  518.  
  519.     // If the record under the mouse is NULL, we must be over whitespace, in
  520.     // which case we don't want to drag any records.
  521.  
  522.     if( pCnrRecUnderMouse )
  523.     {
  524.         PCNRREC pCnrRec = (PCNRREC) CMA_FIRST;
  525.  
  526.         // Count the records with 'selection' emphasis. These are the records
  527.         // we want to drag, unless the container record under the mouse does
  528.         // not have selection emphasis. If that is the case, we only want to
  529.         // process that one.
  530.  
  531.         while( pCnrRec )
  532.         {
  533.             pCnrRec = (PCNRREC) WinSendDlgItemMsg( hwndFrame, FID_CLIENT,
  534.                                                    CM_QUERYRECORDEMPHASIS,
  535.                                                    MPFROMP( pCnrRec ),
  536.                                                    MPFROMSHORT( CRA_SELECTED ));
  537.  
  538.             if( pCnrRec == (PCNRREC) -1 )
  539.                 Msg( "CountSelectedRecs..CM_QUERYRECORDEMPHASIS RC(%X)",
  540.                      HWNDERR( hwndFrame ) );
  541.             else if( pCnrRec )
  542.             {
  543.                 if( pCnrRec == pCnrRecUnderMouse )
  544.                     *pfUseSelectedRecs = TRUE;
  545.  
  546.                 cRecs++;
  547.             }
  548.         }
  549.  
  550.         if( !(*pfUseSelectedRecs) )
  551.             cRecs = 1;
  552.     }
  553.  
  554.     return cRecs;
  555. }
  556.  
  557. /**********************************************************************/
  558. /*----------------------- SetSelectedDragItems -----------------------*/
  559. /*                                                                    */
  560. /*  FILL THE DRAGINFO STRUCT WITH DRAGITEM STRUCTS FOR SELECTED RECS. */
  561. /*                                                                    */
  562. /*  PARMS: frame window handle,                                       */
  563. /*         count of selected records,                                 */
  564. /*         pointer to allocated DRAGINFO struct,                      */
  565. /*         pointer to allocated DRAGIMAGE array                       */
  566. /*                                                                    */
  567. /*  NOTES:                                                            */
  568. /*                                                                    */
  569. /*  RETURNS: nothing                                                  */
  570. /*                                                                    */
  571. /*--------------------------------------------------------------------*/
  572. /**********************************************************************/
  573. void SetSelectedDragItems( HWND hwndFrame, int cRecs, PDRAGINFO pDragInfo,
  574.                            PDRAGIMAGE pDragImage )
  575. {
  576.     PCNRREC pCnrRec = (PCNRREC) CMA_FIRST;
  577.     int     i;
  578.  
  579.     for( i = 0; i < cRecs; i++, pDragImage++ )
  580.     {
  581.         pCnrRec = (PCNRREC) WinSendDlgItemMsg( hwndFrame, FID_CLIENT,
  582.                                                CM_QUERYRECORDEMPHASIS,
  583.                                                MPFROMP( pCnrRec ),
  584.                                                MPFROMSHORT( CRA_SELECTED ) );
  585.  
  586.         if( pCnrRec == (PCNRREC) -1 )
  587.             Msg( "SetSelectedDragItems..CM_QUERYRECORDEMPHASIS RC(%X)",
  588.                  HWNDERR( hwndFrame ) );
  589.         else
  590.             SetOneDragItem( hwndFrame, pCnrRec, pDragInfo, pDragImage, i );
  591.     }
  592. }
  593.  
  594. /**********************************************************************/
  595. /*-------------------------- SetOneDragItem --------------------------*/
  596. /*                                                                    */
  597. /*  SET ONE DRAGITEM STRUCT INTO A DRAGINFO STRUCT.                   */
  598. /*                                                                    */
  599. /*  PARMS: frame window handle,                                       */
  600. /*         pointer to CNRREC that contains current container record,  */
  601. /*         pointer to allocated DRAGINFO struct,                      */
  602. /*         pointer to allocated DRAGIMAGE array,                      */
  603. /*         record offset into DRAGINFO struct to place DRAGITEM       */
  604. /*                                                                    */
  605. /*  NOTES:                                                            */
  606. /*                                                                    */
  607. /*  RETURNS: nothing                                                  */
  608. /*                                                                    */
  609. /*--------------------------------------------------------------------*/
  610. /**********************************************************************/
  611. void SetOneDragItem( HWND hwndFrame, PCNRREC pCnrRec, PDRAGINFO pDragInfo,
  612.                      PDRAGIMAGE pDragImage, int iOffset )
  613. {
  614.     DRAGITEM DragItem;
  615.     PCH      pchColon = NULL;
  616.  
  617.     memset( &DragItem, 0, sizeof DragItem );
  618.  
  619.     // hwndDragItem is the window that will get the DM_RENDER and
  620.     // DM_RENDERCOMPLETE messages.
  621.  
  622.     DragItem.hwndItem = hwndFrame;
  623.  
  624.     // ulItemID is used to store information that can be used at drop time. Here
  625.     // we store the container record pointer.
  626.  
  627.     DragItem.ulItemID = (ULONG) pCnrRec;
  628.  
  629.     // hstrType identifies 'types' when it is necessary to differentiate. A
  630.     // good example is if you are dragging file names (DRM_OS2FILE) and need to
  631.     // pass the file type to the target (i.e. DRT_BITMAP would mean the file
  632.     // contained a bitmap, DRT_TEXT is an ascii file, etc. )
  633.  
  634.     DragItem.hstrType = DrgAddStrHandle( DRT_UNKNOWN );
  635.  
  636.     // This is the rendering mechanism/format. This establishes the protocol
  637.     // that we will be using during the Drag/Drop operation. In this program we
  638.     // only use DRM_FISHMAN which means rendering will take place after the
  639.     // drop using a predefined and agreed-upon mechanism. Any target objects
  640.     // that OK this type of protocol must know how to handle themselves after
  641.     // the drop.
  642.  
  643.     DragItem.hstrRMF = DrgAddStrHandle( DRAG_RMF );
  644.  
  645.     // This will contain our 'database file' name. We have multiple 'database'
  646.     // files, each with their own set of 'tables'. This field identifies the
  647.     // 'database' name. The text for each container record has been set (in the
  648.     // InsertRecords function in drgthrnd.c) to "database:table". So we
  649.     // temporarily set the colon to a null-terminator for the database name so
  650.     // we can create a stringhandle for the database name.
  651.  
  652.     pchColon = strchr( pCnrRec->szTableName, ':' );
  653.     if( pchColon )
  654.         *pchColon = 0;
  655.     else                  // This should never happen! Play it safe though.
  656.         pchColon = pCnrRec->szTableName;
  657.  
  658.     DragItem.hstrContainerName = DrgAddStrHandle( pCnrRec->szTableName );
  659.  
  660.     // This will contain the table name (minus the database name)
  661.  
  662.     DragItem.hstrSourceName = DrgAddStrHandle( pchColon + 1 );
  663.  
  664.     if( pchColon != pCnrRec->szTableName )
  665.         *pchColon = ':';
  666.  
  667.     // Suggested target name is the same as the source name. We *could* ask the
  668.     // target to call it something else but we don't need that functionality
  669.     // in this program.
  670.  
  671.     DragItem.hstrTargetName = DragItem.hstrSourceName;
  672.  
  673.     // Allow the user to only 'copy' this item. 'Move doesn't make sense since
  674.     // the records will always stay in the source container.
  675.  
  676.     DragItem.fsSupportedOps = DO_COPYABLE;
  677.  
  678.     // This tells the target to send a DC_RENDERPREPARE message before it
  679.     // sends a DM_RENDER message.
  680.  
  681.     DragItem.fsControl = DC_PREPARE;
  682.  
  683.     // Set the DRAGITEM struct into the memory allocated by
  684.     // DrgAllocDraginfo()
  685.  
  686.     DrgSetDragitem( pDragInfo, &DragItem, sizeof DragItem, iOffset );
  687.  
  688.     // Fill in the DRAGIMAGE structure
  689.  
  690.     pDragImage->cb       = sizeof( DRAGIMAGE );
  691.     pDragImage->hImage   = pCnrRec->mrc.hptrIcon; // DragImage under mouse
  692.     pDragImage->fl       = DRG_ICON;              // hImage is an HPOINTER
  693.     pDragImage->cxOffset = 5 * iOffset;           // Image offset from mouse ptr
  694.     pDragImage->cyOffset = 5 * iOffset;           // Image offset from mouse ptr
  695.  
  696.     // Set source emphasis for this container record
  697.  
  698.     if( !WinSendDlgItemMsg( hwndFrame, FID_CLIENT, CM_SETRECORDEMPHASIS,
  699.                         MPFROMP( pCnrRec ), MPFROM2SHORT( TRUE, CRA_SOURCE ) ) )
  700.         Msg( "SetOneDragItem..CM_SETRECORDEMPHASIS RC(%X)",
  701.              HWNDERR( hwndFrame ) );
  702. }
  703.  
  704. /**********************************************************************/
  705. /*----------------------- RemoveSourceEmphasis -----------------------*/
  706. /*                                                                    */
  707. /*  REMOVE SOURCE EMPHASIS FROM THE DRAGGED RECORDS.                  */
  708. /*                                                                    */
  709. /*  PARMS: frame window handle                                        */
  710. /*                                                                    */
  711. /*  NOTES:                                                            */
  712. /*                                                                    */
  713. /*  RETURNS: nothing                                                  */
  714. /*                                                                    */
  715. /*--------------------------------------------------------------------*/
  716. /**********************************************************************/
  717. void RemoveSourceEmphasis( HWND hwndFrame )
  718. {
  719.     PCNRREC pCnrRec = (PCNRREC) CMA_FIRST;
  720.  
  721.     // For every record with source emphasis, remove it.
  722.  
  723.     while( pCnrRec )
  724.     {
  725.         pCnrRec = (PCNRREC) WinSendDlgItemMsg( hwndFrame, FID_CLIENT,
  726.                                             CM_QUERYRECORDEMPHASIS,
  727.                                             MPFROMP( pCnrRec ),
  728.                                             MPFROMSHORT( CRA_SOURCE ) );
  729.  
  730.         if( pCnrRec == (PCNRREC) -1 )
  731.             Msg( "RemoveSourceEmphasis..CM_QUERYRECORDEMPHASIS RC(%X)",
  732.                  HWNDERR( hwndFrame ) );
  733.         else if( pCnrRec )
  734.             if( !WinSendDlgItemMsg( hwndFrame, FID_CLIENT,
  735.                                     CM_SETRECORDEMPHASIS, MPFROMP( pCnrRec ),
  736.                                     MPFROM2SHORT( FALSE, CRA_SOURCE ) ) )
  737.                 Msg( "RemoveSourceEmphasis..CM_SETRECORDEMPHASIS RC(%X)",
  738.                      HWNDERR( hwndFrame ) );
  739.     }
  740. }
  741.  
  742. /*************************************************************************
  743.  *                     E N D     O F     S O U R C E                     *
  744.  *************************************************************************/
  745.