home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / drgmon.zip / drgdrop.c < prev    next >
C/C++ Source or Header  |  1993-07-28  |  40KB  |  946 lines

  1. /*********************************************************************
  2.  *                                                                   *
  3.  * MODULE NAME :  drgdrop.c              AUTHOR:  Rick Fishman       *
  4.  * DATE WRITTEN:  07-20-93                                           *
  5.  *                                                                   *
  6.  * HOW TO RUN THIS PROGRAM:                                          *
  7.  *                                                                   *
  8.  *  Just enter DRGDROP on the command line.                          *
  9.  *                                                                   *
  10.  * MODULE DESCRIPTION:                                               *
  11.  *                                                                   *
  12.  *  Root module for DRGDROP.EXE, a program that demonstrates using   *
  13.  *  Drag/Drop on OS/2 2.x. This program creates 2 windows, a 'drag'  *
  14.  *  window and a 'drop' window.                                      *
  15.  *                                                                   *
  16.  *  Each window is actually a frame window with a container control  *
  17.  *  as its client window.                                            *
  18.  *                                                                   *
  19.  *  The drag window starts out with some records in it that can be   *
  20.  *  dragged. The drop window starts out empty. Once you drag some    *
  21.  *  icons from the drag window to the drop window, both function the *
  22.  *  same (i.e. you can drag from either and drop on either.          *
  23.  *                                                                   *
  24.  *  You can also drag from other windows on the desktop and to other *
  25.  *  windows on the desktop.                                          *
  26.  *                                                                   *
  27.  *  Each of the 2 windows created in this program have a 'debug'     *
  28.  *  window associated with them. This debug window is a frame window *
  29.  *  with a listbox as its client window. As Drag/Drop activity       *
  30.  *  happens from or to the Drag/Drop window, it is recorded in the   *
  31.  *  debug window. All Drag/Drop messages will be listed and the      *
  32.  *  contents of the relevant Drag/Drop structures will be listed.    *
  33.  *                                                                   *
  34.  *  There is also a modeless dialog box that allows you to change    *
  35.  *  the way the Drag/Drop operates by changing the values that drag.c*
  36.  *  uses when setting up the drag and reacting to the drop. You can  *
  37.  *  minimize hide this window at any time and bring it back using the*
  38.  *  task list.                                                       *
  39.  *                                                                   *
  40.  *  The records that are originally inserted into the container      *
  41.  *  represent some temporary files. Those temporary files are        *
  42.  *  created so that they can be dragged and dropped on other windows *
  43.  *  and those other windows actually are manipulating something.     *
  44.  *  These temporary files are created in the InsertRecords function  *
  45.  *  and destroyed at the end of the program.                         *
  46.  *                                                                   *
  47.  *                                                                   *
  48.  * OTHER MODULES:                                                    *
  49.  *                                                                   *
  50.  *  drag.c    - contains all drag/drop processing code.              *
  51.  *  cbdebug.c - contains the code for the 'debug' frame/listbox.     *
  52.  *                                                                   *
  53.  * NOTES:                                                            *
  54.  *                                                                   *
  55.  *  I hope this code proves useful for other PM programmers. The     *
  56.  *  more of us the better!                                           *
  57.  *                                                                   *
  58.  * HISTORY:                                                          *
  59.  *                                                                   *
  60.  *  07-20-93 - Program coding started.                               *
  61.  *                                                                   *
  62.  *  Rick Fishman                                                     *
  63.  *  Code Blazers, Inc.                                               *
  64.  *  4113 Apricot                                                     *
  65.  *  Irvine, CA. 92720                                                *
  66.  *  CIS ID: 72251,750                                                *
  67.  *                                                                   *
  68.  *********************************************************************/
  69.  
  70. #pragma strings(readonly)   // used for debug version of memory mgmt routines
  71.  
  72. /*********************************************************************/
  73. /*------- Include relevant sections of the OS/2 header files --------*/
  74. /*********************************************************************/
  75.  
  76. #define  INCL_SHLERRORS
  77. #define  INCL_WINERRORS
  78. #define  INCL_WINDIALOGS
  79. #define  INCL_WINFRAMEMGR
  80. #define  INCL_WINPOINTERS
  81. #define  INCL_WINSHELLDATA
  82. #define  INCL_WINSTDCNR
  83. #define  INCL_WINSTDDRAG
  84. #define  INCL_WINSYS
  85. #define  INCL_WINWINDOWMGR
  86.  
  87. #define  GLOBALS_DEFINED    // extern globals instantiated
  88.  
  89. /**********************************************************************/
  90. /*----------------------------- INCLUDES -----------------------------*/
  91. /**********************************************************************/
  92.  
  93. #include <os2.h>
  94. #include <stdarg.h>
  95. #include <stdio.h>
  96. #include <stdlib.h>
  97. #include <string.h>
  98. #include "drgdrop.h"
  99.  
  100. /*********************************************************************/
  101. /*------------------- APPLICATION DEFINITIONS -----------------------*/
  102. /*********************************************************************/
  103.  
  104. #define PROGRAM_TITLE               "Drag/Drop Sample"
  105.  
  106. #define MESSAGE_SIZE                1024
  107.  
  108. #define FRAME_FLAGS                 (FCF_TASKLIST   | FCF_TITLEBAR | \
  109.                                      FCF_SYSMENU    | FCF_MINMAX   | \
  110.                                      FCF_SIZEBORDER | FCF_ICON   | \
  111.                                      FCF_ACCELTABLE)
  112.  
  113. #define CONTAINER_STYLES            (CCS_EXTENDSEL | CCS_MINIRECORDCORE | \
  114.                                      CCS_AUTOPOSITION)
  115.  
  116. /**********************************************************************/
  117. /*---------------------------- STRUCTURES ----------------------------*/
  118. /**********************************************************************/
  119.  
  120.  
  121. /**********************************************************************/
  122. /*----------------------- FUNCTION PROTOTYPES ------------------------*/
  123. /**********************************************************************/
  124.  
  125. int  main              ( void );
  126. void ProgInit          ( HAB hab );
  127. void GetCurrentPath    ( void );
  128. BOOL CreateWindows     ( HAB hab );
  129. HWND CreateWindow      ( HAB hab, PFRAMECDATA pfcdata, ULONG idWindow,
  130.                          PSZ pszWindow, PSZ pszCnrTitle );
  131. BOOL InsertRecords     ( HWND hwndCnr );
  132. BOOL SizeAndShowWindows( HAB hab );
  133. void ProgTerm          ( HAB hab );
  134. void DeleteTempFiles   ( void );
  135.  
  136. FNWP wpFrame;
  137.  
  138. /**********************************************************************/
  139. /*------------------------ GLOBAL VARIABLES --------------------------*/
  140. /**********************************************************************/
  141.  
  142. PFNWP pfnwpFrame;
  143.  
  144. char szDragCnrTitle[] = "Drag or drop - it's your choice!\n"
  145.                         "Use context menu to change default settings.";
  146. char szDropCnrTitle[] = "Go ahead. Drag one of those icons on me.\n"
  147.                         "Use context menu to change default settings.";
  148.  
  149. /**********************************************************************/
  150. /*------------------------------ MAIN --------------------------------*/
  151. /*                                                                    */
  152. /*  PROGRAM ENTRYPOINT                                                */
  153. /*                                                                    */
  154. /*  PARMS: nothing                                                    */
  155. /*                                                                    */
  156. /*  NOTES:                                                            */
  157. /*                                                                    */
  158. /*  RETURNS: return code                                              */
  159. /*                                                                    */
  160. /*--------------------------------------------------------------------*/
  161. /**********************************************************************/
  162. int main( void )
  163. {
  164.     HAB  hab;
  165.     HMQ  hmq = NULLHANDLE;
  166.     QMSG qmsg;
  167.  
  168.     // This macro is defined for the debug version of the C Set/2 Memory
  169.     // Management routines. Since the debug version writes to stderr, we
  170.     // send all stderr output to a debuginfo file.
  171.  
  172. #ifdef __DEBUG_ALLOC__
  173.     freopen( DEBUG_FILENAME, "w", stderr );
  174. #endif
  175.  
  176.     hab = WinInitialize( 0 );
  177.  
  178.     if( hab )
  179.         hmq = WinCreateMsgQueue( hab, 0 );
  180.     else
  181.     {
  182.         DosBeep( 1000, 100 );
  183.         fprintf( stderr, "WinInitialize failed!" );
  184.     }
  185.  
  186.     if( hmq )
  187.     {
  188.         ProgInit( hab );
  189.  
  190.         if( CreateWindows( hab ) )
  191.             while( WinGetMsg( hab, &qmsg, NULLHANDLE, 0, 0 ) )
  192.                 WinDispatchMsg( hab, &qmsg );
  193.     }
  194.     else if( hab )
  195.         Msg( "WinCreateMsgQueue RC(%X)", HABERR( hab ) );
  196.  
  197.     ProgTerm( hab );
  198.  
  199.     if( hmq )
  200.         WinDestroyMsgQueue( hmq );
  201.  
  202.     if( hab )
  203.         WinTerminate( hab );
  204.  
  205. #ifdef __DEBUG_ALLOC__
  206.     _dump_allocated( -1 );
  207. #endif
  208.  
  209.     return 0;
  210. }
  211.  
  212. /**********************************************************************/
  213. /*---------------------------- ProgInit ------------------------------*/
  214. /*                                                                    */
  215. /*  PERFORM PROGRAM INITIALIZATION.                                   */
  216. /*                                                                    */
  217. /*  PARMS: anchor block handle                                        */
  218. /*                                                                    */
  219. /*  NOTES:                                                            */
  220. /*                                                                    */
  221. /*  RETURNS: nothing                                                  */
  222. /*                                                                    */
  223. /*--------------------------------------------------------------------*/
  224. /**********************************************************************/
  225. void ProgInit( HAB hab )
  226. {
  227.     GetCurrentPath();
  228.  
  229.     // Initialize structure counts so all modules can use them
  230.  
  231.     cOperations         = OP_TYPES;
  232.     cControlTypes       = CONTROL_TYPES;
  233.     cSupportedOps       = OPERATION_TYPES;
  234.     cRenderReplyTypes   = RENDERREPLY_TYPES;
  235.     cPrintReplyTypes    = PRINTREPLY_TYPES;
  236.     cDragoverReplyTypes = DRAGOVERREPLY_TYPES;
  237.     cMechanisms         = MECHANISM_TYPES;
  238.     cFormats            = FORMAT_TYPES;
  239.     cTypes              = TYPE_TYPES;
  240.  
  241.     // Initialize the Settings notebook dialog box defaults
  242.  
  243.     if( !RetrieveDlgInfo( hab, &dlgInfo ) )
  244.         dlgInfo = dlgInfoDefaults;
  245. }
  246.  
  247. /**********************************************************************/
  248. /*------------------------- GetCurrentPath ---------------------------*/
  249. /*                                                                    */
  250. /*  STORE THE CURRENT DRIVE/DIRECTORY.                                */
  251. /*                                                                    */
  252. /*  PARMS: nothing                                                    */
  253. /*                                                                    */
  254. /*  NOTES: This stores the current drive:\directory\  that is used    */
  255. /*         to create temporary files in.                              */
  256. /*                                                                    */
  257. /*  RETURNS: nothing                                                  */
  258. /*                                                                    */
  259. /*--------------------------------------------------------------------*/
  260. /**********************************************************************/
  261. void GetCurrentPath()
  262. {
  263.     PBYTE  pbCurrent = szCurrentPath;
  264.     INT    cbBuf = sizeof szCurrentPath, cbUsed;
  265.     ULONG  ulDrive, ulCurrDriveNo, ulDriveMap, cbPath;
  266.     APIRET rc;
  267.  
  268.     // Fill in the drive letter, colon, and backslash
  269.  
  270.     rc = DosQueryCurrentDisk( &ulCurrDriveNo, &ulDriveMap );
  271.  
  272.     if( !rc )                                // Use 'current' drive
  273.     {
  274.         *(pbCurrent++) = (BYTE) (ulCurrDriveNo + ('A' - 1));
  275.         *(pbCurrent++) = ':';
  276.         *(pbCurrent++) = '\\';
  277.     }
  278.     else
  279.     {                                        // API failed - use drive C:
  280.         strcpy( pbCurrent, "C:\\" );
  281.         pbCurrent += 3;                      // Incr our place in the buffer
  282.     }
  283.  
  284.     cbUsed = pbCurrent - szCurrentPath;      // How many bytes left?
  285.  
  286.     // Fill in the current directory
  287.  
  288.     ulDrive = *szCurrentPath - 'A' + 1;      // Get drive number from letter
  289.     cbPath = cbBuf - cbUsed;                 // How many bytes left?
  290.  
  291.     rc = DosQueryCurrentDir( ulDrive, pbCurrent, &cbPath );
  292.                                              // Get 'current' directory
  293.     if( szCurrentPath[ strlen( szCurrentPath ) - 1 ] != '\\' )
  294.         strcat( szCurrentPath, "\\" );       // Add trailing backslash
  295. }
  296.  
  297. /**********************************************************************/
  298. /*------------------------- CreateWindows ----------------------------*/
  299. /*                                                                    */
  300. /*  CREATE ALL APPLICATION WINDOWS                                    */
  301. /*                                                                    */
  302. /*  PARMS: anchor block handle                                        */
  303. /*                                                                    */
  304. /*  NOTES:                                                            */
  305. /*                                                                    */
  306. /*  RETURNS: TRUE or FALSE if successful or not                       */
  307. /*                                                                    */
  308. /*--------------------------------------------------------------------*/
  309. /**********************************************************************/
  310. BOOL CreateWindows( HAB hab )
  311. {
  312.     BOOL       fSuccess = TRUE;
  313.     FRAMECDATA fcdata;
  314.  
  315.     memset( &fcdata, 0, sizeof fcdata );
  316.     fcdata.cb            = sizeof( FRAMECDATA );
  317.     fcdata.idResources   = ID_RESOURCES;
  318.     fcdata.flCreateFlags = FRAME_FLAGS;
  319.  
  320.     // Create 2 windows. One will act as the 'drag' window, the other as the
  321.     // 'drop' window. The user will then be able to drag the icons from the
  322.     // 'drag' window to the 'drop' window.
  323.  
  324.     hwndDrag = CreateWindow( hab, &fcdata, ID_DRAGCNR, TITLE_FOR_DRAGCNR_FRAME,
  325.                              szDragCnrTitle );
  326.     if( hwndDrag )
  327.     {
  328.         hwndDrop = CreateWindow( hab, &fcdata, ID_DROPCNR,
  329.                                  TITLE_FOR_DROPCNR_FRAME, szDropCnrTitle );
  330.         if( !hwndDrop )
  331.             fSuccess = FALSE;
  332.     }
  333.     else
  334.         fSuccess = FALSE;
  335.  
  336.     // Load the icon that will be used for the container records.
  337.  
  338.     if( fSuccess )
  339.         hptrCnrRec = WinLoadPointer( HWND_DESKTOP, 0, ID_RESOURCES );
  340.  
  341.     // Insert the records into the 'drag' container.
  342.  
  343.     if( fSuccess )
  344.         fSuccess = InsertRecords( WinWindowFromID( hwndDrag, FID_CLIENT ) );
  345.  
  346.     if( fSuccess )
  347.         fSuccess = SizeAndShowWindows( hab );
  348.  
  349.     if( !fSuccess )
  350.     {
  351.         if( hwndDrag )
  352.         {
  353.             WinDestroyWindow( hwndDrag );
  354.             hwndDrag = NULLHANDLE;
  355.         }
  356.  
  357.         if( hwndDrop )
  358.         {
  359.             WinDestroyWindow( hwndDrop );
  360.             hwndDrop = NULLHANDLE;
  361.         }
  362.     }
  363.  
  364.     return fSuccess;
  365. }
  366.  
  367. /**********************************************************************/
  368. /*-------------------------- CreateWindow ----------------------------*/
  369. /*                                                                    */
  370. /*  CREATE A FRAME WINDOW WITH A CONTAINER AS ITS CLIENT WINDOW       */
  371. /*                                                                    */
  372. /*  PARMS: anchor block handle,                                       */
  373. /*         pointer to frame control data,                             */
  374. /*         id of the frame window,                                    */
  375. /*         window title of the frame window,                          */
  376. /*         container title                                            */
  377. /*                                                                    */
  378. /*  NOTES:                                                            */
  379. /*                                                                    */
  380. /*  RETURNS: frame window handle or NULLHANDLE if not successful      */
  381. /*                                                                    */
  382. /*--------------------------------------------------------------------*/
  383. /**********************************************************************/
  384. HWND CreateWindow( HAB hab, PFRAMECDATA pfcdata, ULONG idWindow, PSZ pszWindow,
  385.                    PSZ pszCnrTitle )
  386. {
  387.     HWND hwndFrame = NULLHANDLE, hwndCnr = NULLHANDLE;
  388.  
  389.     // Create the container as the client window of the frame. There is no
  390.     // need for a normal client window. Because of this we must subclass the
  391.     // frame window so we can catch the messages that the container sends to
  392.     // its owner.
  393.  
  394.     hwndFrame = WinCreateWindow( HWND_DESKTOP, WC_FRAME, NULL,
  395.                                  FS_NOBYTEALIGN | WS_CLIPCHILDREN,
  396.                                  0, 0, 0, 0, NULLHANDLE, HWND_TOP,
  397.                                  idWindow, pfcdata, NULL );
  398.     if( hwndFrame )
  399.     {
  400.         pfnwpFrame = WinSubclassWindow( hwndFrame, wpFrame );
  401.  
  402.         if( pfnwpFrame )
  403.         {
  404.             hwndCnr = WinCreateWindow( hwndFrame, WC_CONTAINER, NULL,
  405.                                        WS_VISIBLE | CONTAINER_STYLES,
  406.                                        0, 0, 0, 0, hwndFrame, HWND_TOP,
  407.                                        FID_CLIENT, NULL, NULL );
  408.             if( hwndCnr )
  409.             {
  410.                 WinSetPresParam( hwndCnr, PP_FONTNAMESIZE,
  411.                                  strlen( CONTAINER_FONT ) + 1, CONTAINER_FONT );
  412.                 WinSetWindowText( hwndFrame, pszWindow );
  413.             }
  414.             else
  415.             {
  416.                 WinDestroyWindow( hwndFrame );
  417.                 hwndFrame = NULLHANDLE;
  418.                 Msg( "WinCreateWindow(hwndCnr,%s) RC(%X)", pszWindow,
  419.                      HABERR( hab ) );
  420.             }
  421.         }
  422.         else
  423.         {
  424.             WinDestroyWindow( hwndFrame );
  425.             hwndFrame = NULLHANDLE;
  426.             Msg( "WinSubclassWindow(%s) RC(%X)", pszWindow, HABERR( hab ) );
  427.         }
  428.     }
  429.     else
  430.         Msg( "WinCreateWindow(%s) RC(%X)", pszWindow, HABERR( hab ) );
  431.  
  432.     if( hwndFrame )
  433.     {
  434.         CNRINFO cnri;
  435.  
  436.         // Set container into Icon view and give it a read-only title
  437.  
  438.         cnri.cb           = sizeof( CNRINFO );
  439.         cnri.pszCnrTitle  = pszCnrTitle;
  440.         cnri.flWindowAttr = CV_ICON | CA_CONTAINERTITLE | CA_TITLESEPARATOR |
  441.                             CA_TITLEREADONLY;
  442.  
  443.         if( !WinSendMsg( hwndCnr, CM_SETCNRINFO, MPFROMP( &cnri ),
  444.                          MPFROMLONG( CMA_FLWINDOWATTR | CMA_CNRTITLE ) ) )
  445.         {
  446.             WinDestroyWindow( hwndFrame );
  447.             hwndFrame = NULLHANDLE;
  448.             Msg( "CM_SETCNRINFO(%S) RC(%X)", pszWindow, HABERR( hab ) );
  449.         }
  450.     }
  451.  
  452.     if( hwndFrame )
  453.     {
  454.         PINSTANCE pi;
  455.  
  456.         // Allocate memory for the instance data and set it into the
  457.         // Frame window's QWL_USER window word.
  458.  
  459.         pi = (PINSTANCE) malloc( sizeof *pi );
  460.         if( pi )
  461.         {
  462.             char szDbgTitle[ 100 ];
  463.  
  464.             memset( pi, 0, sizeof *pi );
  465.             WinSetWindowPtr( hwndFrame, QWL_USER, pi );
  466.  
  467.             // Create the debug window associated with this window
  468.  
  469.             sprintf( szDbgTitle, "%s activity", pszWindow );
  470.             pi->hwndDebug = dbgCreateWin( szDbgTitle );
  471.             if( !pi->hwndDebug )
  472.             {
  473.                 WinDestroyWindow( hwndFrame );
  474.                 hwndFrame = NULLHANDLE;
  475.             }
  476.         }
  477.         else
  478.         {
  479.             WinDestroyWindow( hwndFrame );
  480.             hwndFrame = NULLHANDLE;
  481.             Msg( "Out of memory in CreateWindow!" );
  482.         }
  483.     }
  484.  
  485.     return hwndFrame;
  486. }
  487.  
  488. /**********************************************************************/
  489. /*-------------------------- InsertRecords ---------------------------*/
  490. /*                                                                    */
  491. /*  INSERT RECORDS INTO A CONTAINER                                   */
  492. /*                                                                    */
  493. /*  PARMS: container window handle                                    */
  494. /*                                                                    */
  495. /*  NOTES: We just insert a few records to start us off. Each record  */
  496. /*         represents a temp file that we create.                     */
  497. /*                                                                    */
  498. /*  RETURNS: TRUE if successful, FALSE if not                         */
  499. /*                                                                    */
  500. /*--------------------------------------------------------------------*/
  501. /**********************************************************************/
  502. #define INITIAL_CONTAINER_RECS 5
  503.  
  504. BOOL InsertRecords( HWND hwndCnr )
  505. {
  506.     BOOL         fSuccess = TRUE;
  507.     RECORDINSERT ri;
  508.     PCNRREC      pCnrRec, pCnrRecSave;
  509.  
  510.     pCnrRec = WinSendMsg( hwndCnr, CM_ALLOCRECORD, MPFROMLONG( EXTRA_BYTES ),
  511.                           MPFROMLONG( INITIAL_CONTAINER_RECS ) );
  512.  
  513.     if( pCnrRec )
  514.     {
  515.         FILE     *fh;
  516.         int      i;
  517.         PSZ      pszFileExt;
  518.         ICONINFO iconinfo;
  519.  
  520.         memset( &iconinfo, 0, sizeof iconinfo );
  521.  
  522.         pCnrRecSave = pCnrRec;
  523.  
  524.         for( i = 0; fSuccess && (i < INITIAL_CONTAINER_RECS); i++ )
  525.         {
  526.             // Create a temporary filename (zero-length).
  527.  
  528.             strcpy( pCnrRec->szFileName, BASE_TEMPFILE_NAME );
  529.             strcat( pCnrRec->szFileName, "." );
  530.             pszFileExt = pCnrRec->szFileName + strlen( pCnrRec->szFileName );
  531.             _itoa( i + 1, pszFileExt, 10 );
  532.  
  533.             strcpy( pCnrRec->szFullFileName, szCurrentPath );
  534.             strcat( pCnrRec->szFullFileName, pCnrRec->szFileName );
  535.  
  536.             fh = fopen( pCnrRec->szFileName, "w" );
  537.             if( fh )
  538.             {
  539.                 fclose( fh );
  540.  
  541.                 // Set the icon attached to the temporary file so it will show
  542.                 // up when dropped onto other containers.
  543.  
  544.                 iconinfo.fFormat     = ICON_FILE;
  545.                 iconinfo.pszFileName = DRGDROP_ICON_FILENAME;
  546.                 WinSetFileIcon( pCnrRec->szFileName, &iconinfo );
  547.  
  548.                 pCnrRec->mrc.pszIcon  = (PSZ) &pCnrRec->szFileName;
  549.                 pCnrRec->mrc.hptrIcon = hptrCnrRec;
  550.             }
  551.             else
  552.             {
  553.                 fSuccess = FALSE;
  554.                 Msg( "Could not create %s file", pCnrRec->szFileName );
  555.             }
  556.  
  557.             pCnrRec = (PCNRREC) pCnrRec->mrc.preccNextRecord;
  558.         }
  559.  
  560.         memset( &ri, 0, sizeof( RECORDINSERT ) );
  561.         ri.cb                 = sizeof( RECORDINSERT );
  562.         ri.pRecordOrder       = (PRECORDCORE) CMA_END;
  563.         ri.pRecordParent      = (PRECORDCORE) NULL;
  564.         ri.zOrder             = (USHORT) CMA_TOP;
  565.         ri.cRecordsInsert     = INITIAL_CONTAINER_RECS;
  566.         ri.fInvalidateRecord  = TRUE;
  567.  
  568.         if( !WinSendMsg( hwndCnr, CM_INSERTRECORD, MPFROMP( pCnrRecSave ),
  569.                          MPFROMP( &ri ) ) )
  570.         {
  571.             fSuccess = FALSE;
  572.             Msg( "InsertRecords CM_INSERTRECORD RC(%X)", HWNDERR( hwndCnr ) );
  573.         }
  574.     }
  575.     else
  576.     {
  577.         fSuccess = FALSE;
  578.         Msg( "InsertRecords CM_ALLOCRECORD RC(%X)", HWNDERR( hwndCnr ) );
  579.     }
  580.  
  581.     return fSuccess;
  582. }
  583.  
  584. /**********************************************************************/
  585. /*----------------------- SizeAndShowWindows -------------------------*/
  586. /*                                                                    */
  587. /*  SIZE AND SHOW ALL WINDOWS AT THE SAME TIME.                       */
  588. /*                                                                    */
  589. /*  PARMS: anchor block handle                                        */
  590. /*                                                                    */
  591. /*  NOTES:                                                            */
  592. /*                                                                    */
  593. /*  RETURNS: TRUE or FALSE if successful or not                       */
  594. /*                                                                    */
  595. /*--------------------------------------------------------------------*/
  596. /**********************************************************************/
  597. BOOL SizeAndShowWindows( HAB hab )
  598. {
  599.     SWP  aswp[ 4 ];
  600.     BOOL fSuccess;
  601.     LONG cxDesktop = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
  602.     LONG cyDesktop = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
  603.  
  604.     memset( &aswp, 0, sizeof aswp );
  605.  
  606.     // Set the windows up so they are on the left and right halves of the
  607.     // display. The debug window will be on the top third of the display and
  608.     // the container window will be on the bottom third of the display.
  609.  
  610.     // Left-hand 'drag' container window
  611.     aswp[ 0 ].hwnd = hwndDrag;
  612.     aswp[ 0 ].x    = 0;
  613.     aswp[ 0 ].y    = 0;
  614.     aswp[ 0 ].cx   = cxDesktop / 2;
  615.     aswp[ 0 ].cy   = cyDesktop / 3;
  616.     aswp[ 0 ].hwndInsertBehind = HWND_TOP;
  617.     aswp[ 0 ].fl   = SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ACTIVATE | SWP_ZORDER;
  618.  
  619.     // Left-hand debug window
  620.     aswp[ 1 ].hwnd = INSTDATA( hwndDrag )->hwndDebug;
  621.     aswp[ 1 ].x    = 0;
  622.     aswp[ 1 ].y    = cyDesktop - (cyDesktop / 3);
  623.     aswp[ 1 ].cx   = cxDesktop / 3;
  624.     aswp[ 1 ].cy   = cyDesktop / 3;
  625.     aswp[ 1 ].fl   = SWP_MOVE | SWP_SIZE | SWP_SHOW;
  626.  
  627.     // Right-hand 'drop' container window
  628.     aswp[ 2 ].hwnd = hwndDrop;
  629.     aswp[ 2 ].x    = cxDesktop / 2;
  630.     aswp[ 2 ].y    = 0;
  631.     aswp[ 2 ].cx   = cxDesktop / 2;
  632.     aswp[ 2 ].cy   = cyDesktop / 3;
  633.     aswp[ 2 ].fl   = SWP_MOVE | SWP_SIZE | SWP_SHOW;
  634.  
  635.     // Right-hand debug window
  636.     aswp[ 3 ].hwnd = INSTDATA( hwndDrop )->hwndDebug;
  637.     aswp[ 3 ].x    = cxDesktop - (cxDesktop / 3);
  638.     aswp[ 3 ].y    = cyDesktop - (cyDesktop / 3);
  639.     aswp[ 3 ].cx   = cxDesktop / 3;
  640.     aswp[ 3 ].cy   = cyDesktop / 3;
  641.     aswp[ 3 ].fl   = SWP_MOVE | SWP_SIZE | SWP_SHOW;
  642.  
  643.     fSuccess = WinSetMultWindowPos( hab, aswp, 4 );
  644.     if( fSuccess )
  645.     {
  646.         // The container was set up as the client window of the frame. We
  647.         // need to set focus to it - otherwise it will not accept keystrokes
  648.         // right away.
  649.  
  650.         WinSetFocus( HWND_DESKTOP,
  651.                      WinWindowFromID( hwndDrag, FID_CLIENT ) );
  652.     }
  653.  
  654.     return fSuccess;
  655. }
  656.  
  657. /**********************************************************************/
  658. /*----------------------------- wpFrame ------------------------------*/
  659. /*                                                                    */
  660. /*  SUBCLASSED FRAME WINDOW PROCEDURE.                                */
  661. /*                                                                    */
  662. /*  PARMS: normal winproc parms                                       */
  663. /*                                                                    */
  664. /*  NOTES:                                                            */
  665. /*                                                                    */
  666. /*  RETURNS: MRESULT value                                            */
  667. /*                                                                    */
  668. /*--------------------------------------------------------------------*/
  669. /**********************************************************************/
  670. MRESULT EXPENTRY wpFrame( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  671. {
  672.     // Route all DM_ messages to drag.c
  673.  
  674.     if( msg >= WM_DRAGFIRST && msg <= WM_DRAGLAST )
  675.         return dragMessage( hwnd, msg, mp1, mp2 );
  676.  
  677.     switch( msg )
  678.     {
  679.         // Don't let the message queue be destroyed until the user has closed
  680.         // *both* windows. If SC_CLOSE gets processed by the default window
  681.         // proc, a WM_QUIT message will get posted to the queue which will in
  682.         // effect end this program.
  683.  
  684.         case WM_SYSCOMMAND:
  685.             if( SHORT1FROMMP( mp1 ) == SC_CLOSE )
  686.                 if( (hwnd == hwndDrag) && hwndDrop )
  687.                 {
  688.                     WinDestroyWindow( hwndDrag );
  689.                     hwndDrag = NULLHANDLE;
  690.                     WinSetActiveWindow( HWND_DESKTOP, hwndDrop );
  691.                     return 0;
  692.                 }
  693.                 else if( (hwnd == hwndDrop) && hwndDrag )
  694.                 {
  695.                     WinDestroyWindow( hwndDrop );
  696.                     hwndDrop = NULLHANDLE;
  697.                     WinSetActiveWindow( HWND_DESKTOP, hwndDrag );
  698.                     return 0;
  699.                 }
  700.  
  701.             break;
  702.  
  703.         case WM_COMMAND:
  704.             menuCommand( hwnd, SHORT1FROMMP( mp1 ) );
  705.             return 0;
  706.  
  707.         case WM_MENUEND:
  708.             menuEnd( hwnd, SHORT1FROMMP( mp1 ), (HWND) mp2 );
  709.             break;
  710.  
  711.         case WM_DESTROY:
  712.         {
  713.             PINSTANCE pi = INSTDATA( hwnd );
  714.  
  715.             // Free the window word memory after destroying the debug window
  716.             // associated with this frame/container window.
  717.  
  718.             if( pi )
  719.             {
  720.                 if( pi->hwndDebug )
  721.                     WinDestroyWindow( pi->hwndDebug );
  722.  
  723.                 free( pi );
  724.             }
  725.  
  726.             // Free all container resources associated with any records that
  727.             // were inserted (note that the container is actually the client
  728.             // window.
  729.  
  730.             WinSendDlgItemMsg( hwnd, FID_CLIENT, CM_REMOVERECORD, NULL,
  731.                                MPFROM2SHORT( 0, CMA_FREE ) );
  732.             break;
  733.         }
  734.  
  735.         case WM_CONTROL:
  736.             if( SHORT1FROMMP( mp1 ) == FID_CLIENT )
  737.                 switch( SHORT2FROMMP( mp1 ) )
  738.                 {
  739.                     case CN_INITDRAG:
  740.                         dragInit( hwnd, (PCNRDRAGINIT) mp2 );
  741.                         return 0;
  742.  
  743.                     case CN_DRAGOVER:
  744.                         return dragOver( hwnd, (PCNRDRAGINFO) mp2 );
  745.  
  746.                     case CN_DRAGLEAVE:
  747.                         dragLeave( hwnd, (PCNRDRAGINFO) mp2 );
  748.                         return 0;
  749.  
  750.                     case CN_DROP:
  751.                         dragDrop( hwnd, (PCNRDRAGINFO) mp2 );
  752.                         return 0;
  753.  
  754.                     case CN_CONTEXTMENU:
  755.                         menuCreate( hwnd );
  756.                         return 0;
  757.                 }
  758.  
  759.             break;
  760.     }
  761.  
  762.     return pfnwpFrame( hwnd, msg, mp1, mp2 );
  763. }
  764.  
  765. /**********************************************************************/
  766. /*---------------------------- ProgTerm ------------------------------*/
  767. /*                                                                    */
  768. /*  PERFORM TERMINATION PROCESSING FOR THIS PROGRAM.                  */
  769. /*                                                                    */
  770. /*  PARMS: nothing                                                    */
  771. /*                                                                    */
  772. /*  NOTES:                                                            */
  773. /*                                                                    */
  774. /*  RETURNS: nothing                                                  */
  775. /*                                                                    */
  776. /*--------------------------------------------------------------------*/
  777. /**********************************************************************/
  778. void ProgTerm()
  779. {
  780.     if( hwndDrag )
  781.         WinDestroyWindow( hwndDrag );
  782.  
  783.     if( hwndDrop )
  784.         WinDestroyWindow( hwndDrop );
  785.  
  786.     if( hwndBook )
  787.         WinDestroyWindow( hwndBook );
  788.  
  789.     if( hptrCnrRec )
  790.         WinDestroyPointer( hptrCnrRec );
  791.  
  792.     DeleteTempFiles();
  793. }
  794.  
  795. /**********************************************************************/
  796. /*------------------------- RetrieveDlgInfo --------------------------*/
  797. /*                                                                    */
  798. /*  GET THE DLGINFO STRUCTURE FROM THE INI FILE.                      */
  799. /*                                                                    */
  800. /*  PARMS: anchor block handle                                        */
  801. /*  PARMS: address of a DLGINFO structure                             */
  802. /*                                                                    */
  803. /*  NOTES:                                                            */
  804. /*                                                                    */
  805. /*  RETURNS: TRUE or FALSE if successful or not.                      */
  806. /*                                                                    */
  807. /*--------------------------------------------------------------------*/
  808. /**********************************************************************/
  809. BOOL RetrieveDlgInfo( HAB hab, PDLGINFO pDlgInfo )
  810. {
  811.     BOOL  fSuccess = TRUE;
  812.     HINI  hini;
  813.     ULONG cbWrite = sizeof( DLGINFO );
  814.  
  815.     hini = PrfOpenProfile( hab, INI_FILE_NAME );
  816.     if( hini )
  817.     {
  818.         if( !PrfQueryProfileData( hini, INI_APPLICATION_NAME, DLGINFO_DEFAULTS,
  819.                                   pDlgInfo, &cbWrite ) )
  820.         {
  821.             USHORT usErr = HABERR( hab );
  822.  
  823.             if( usErr != PMERR_NOT_IN_IDX )
  824.                 Msg( "Problem reading the Settings notebook values that were "
  825.                      "saved the last time you ran this program. The return "
  826.                     "code was %X from PrfQueryProfileData on the %s file. The "
  827.                     "defaults will be used.", usErr, INI_FILE_NAME );
  828.  
  829.             fSuccess = FALSE;
  830.         }
  831.  
  832.         PrfCloseProfile( hini );
  833.     }
  834.  
  835.     return fSuccess;
  836. }
  837.  
  838. /**********************************************************************/
  839. /*--------------------------- SaveDlgInfo ----------------------------*/
  840. /*                                                                    */
  841. /*  STORE THE DIALOG INFORMATION FROM THE SETTINGS NOTEBOOK           */
  842. /*                                                                    */
  843. /*  PARMS: anchor block handle                                        */
  844. /*                                                                    */
  845. /*  NOTES:                                                            */
  846. /*                                                                    */
  847. /*  RETURNS: nothing                                                  */
  848. /*                                                                    */
  849. /*--------------------------------------------------------------------*/
  850. /**********************************************************************/
  851. void SaveDlgInfo( HAB hab )
  852. {
  853.     HINI hini;
  854.  
  855.     hini = PrfOpenProfile( hab, INI_FILE_NAME );
  856.     if( hini )
  857.     {
  858.         if( !PrfWriteProfileData( hini, INI_APPLICATION_NAME, DLGINFO_DEFAULTS,
  859.                                   &dlgInfo, sizeof dlgInfo ) )
  860.             Msg( "Problem writing the Settings notebook values to the %s "
  861.                  "file. The return code was %X from PrfWriteProfileData.",
  862.                  INI_FILE_NAME, HABERR( hab ) );
  863.  
  864.         PrfCloseProfile( hini );
  865.     }
  866. }
  867.  
  868. /**********************************************************************/
  869. /*------------------------- DeleteTempFiles --------------------------*/
  870. /*                                                                    */
  871. /*  DELETE THE TEMPORARY FILES USED BY THIS PROGRAM.                  */
  872. /*                                                                    */
  873. /*  PARMS: nothing                                                    */
  874. /*                                                                    */
  875. /*  NOTES: A temporary file is created in the current directory each  */
  876. /*         time an icon is dragged from the 'drag' container to the   */
  877. /*         'drop' container. Here we delete all those temporary files.*/
  878. /*                                                                    */
  879. /*  RETURNS: nothing                                                  */
  880. /*                                                                    */
  881. /*--------------------------------------------------------------------*/
  882. /**********************************************************************/
  883. void DeleteTempFiles()
  884. {
  885.     FILEFINDBUF3 ffb;
  886.     HDIR         hdir = HDIR_SYSTEM;
  887.     ULONG        cFiles = 1;
  888.     char         szTempFileSpec[ CCHMAXPATH ];
  889.     APIRET       rc;
  890.  
  891.     strcpy( szTempFileSpec, BASE_TEMPFILE_NAME );
  892.     strcat( szTempFileSpec, ".*" );
  893.  
  894.     rc = DosFindFirst( szTempFileSpec, &hdir, FILE_NORMAL,
  895.                        &ffb, sizeof ffb, &cFiles, FIL_STANDARD );
  896.     while( !rc )
  897.     {
  898.         DosDelete( ffb.achName );
  899.         rc = DosFindNext( hdir, &ffb, sizeof ffb, &cFiles );
  900.     }
  901. }
  902.  
  903. /**********************************************************************/
  904. /*------------------------------- Msg --------------------------------*/
  905. /*                                                                    */
  906. /*  DISPLAY A MESSAGE TO THE USER.                                    */
  907. /*                                                                    */
  908. /*  PARMS: a message in printf format with its parms                  */
  909. /*                                                                    */
  910. /*  NOTES:                                                            */
  911. /*                                                                    */
  912. /*  RETURNS: nothing                                                  */
  913. /*                                                                    */
  914. /*--------------------------------------------------------------------*/
  915. /**********************************************************************/
  916. void Msg( PSZ szFormat,... )
  917. {
  918.     PSZ     szMsg;
  919.     va_list argptr;
  920.  
  921.     szMsg = (PSZ) malloc( MESSAGE_SIZE );
  922.     if( szMsg )
  923.     {
  924.         va_start( argptr, szFormat );
  925.         vsprintf( szMsg, szFormat, argptr );
  926.         va_end( argptr );
  927.  
  928.         szMsg[ MESSAGE_SIZE - 1 ] = 0;
  929.  
  930.         WinAlarm( HWND_DESKTOP, WA_WARNING );
  931.         WinMessageBox(  HWND_DESKTOP, HWND_DESKTOP, szMsg,
  932.                         "Container Drag/Drop Sample Program", 1,
  933.                         MB_OK | MB_MOVEABLE );
  934.         free( szMsg );
  935.     }
  936.     else
  937.     {
  938.         DosBeep( 1000, 1000 );
  939.         return;
  940.     }
  941. }
  942.  
  943. /*************************************************************************
  944.  *                     E N D     O F     S O U R C E                     *
  945.  *************************************************************************/
  946.