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

  1. /*********************************************************************
  2.  *                                                                   *
  3.  * MODULE NAME :  drgrendr.c             AUTHOR:  Rick Fishman       *
  4.  * DATE WRITTEN:  07-15-93                                           *
  5.  *                                                                   *
  6.  * HOW TO RUN THIS PROGRAM:                                          *
  7.  *                                                                   *
  8.  *  Just enter DRGRENDR on the command line.                         *
  9.  *                                                                   *
  10.  * MODULE DESCRIPTION:                                               *
  11.  *                                                                   *
  12.  *  Root module for DRGRENDR.EXE, a program that demonstrates using  *
  13.  *  source rendering on the drop during a Drag/Drop operation. This  *
  14.  *  program creates 2 windows, a 'drag' 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 contains icons that each represent a table in    *
  20.  *  a pseudo-database (actually ASCII files that simulate a          *
  21.  *  database).                                                       *
  22.  *                                                                   *
  23.  *  The drop window starts out empty and allows you to drag an icon  *
  24.  *  from the 'drag' window to it. If you do, rendering is done       *
  25.  *  during the drop that writes the rows in the selected table to a  *
  26.  *  temporary file and adds an icon representing that temporary file *
  27.  *  to the drop window. You can then double-click on the icon in the *
  28.  *  drop window to display the contents of the temporary file.       *
  29.  *                                                                   *
  30.  *  The source window (the drag window) is the one that does the     *
  31.  *  actual rendering. By rendering, I mean it 'renders' the contents *
  32.  *  of a table in the database to a file.                            *
  33.  *                                                                   *
  34.  *  The target window (the drop window) is the one that adds the icon*
  35.  *  to its container when the source window indicates that the       *
  36.  *  rendering is complete.                                           *
  37.  *                                                                   *
  38.  *  All rendering is done on thread 1. To see an example where the   *
  39.  *  drop and rendering takes place in separate threads, have a look  *
  40.  *  at my DRGTHRND.EXE sample.
  41.  *                                                                   *
  42.  *  When the drag window is created, it goes thru all database files *
  43.  *  and inserts an icon into the container for each 'table' that it  *
  44.  *  finds.                                                           *
  45.  *                                                                   *
  46.  *  To get an idea of how these 'database' files are structured,     *
  47.  *  have a look at the dbase_?.db files provided with this sample.   *
  48.  *                                                                   *
  49.  * OTHER MODULES:                                                    *
  50.  *                                                                   *
  51.  *  dbaccess.c - contains the code used to access the 'database'.    *
  52.  *  drag.c     - contains all drag/drop processing code.             *
  53.  *                                                                   *
  54.  * NOTES:                                                            *
  55.  *                                                                   *
  56.  *  I hope this code proves useful for other PM programmers. The     *
  57.  *  more of us the better!                                           *
  58.  *                                                                   *
  59.  * HISTORY:                                                          *
  60.  *                                                                   *
  61.  *  07-15-93 - Program coding started.                               *
  62.  *                                                                   *
  63.  *  Rick Fishman                                                     *
  64.  *  Code Blazers, Inc.                                               *
  65.  *  4113 Apricot                                                     *
  66.  *  Irvine, CA. 92720                                                *
  67.  *  CIS ID: 72251,750                                                *
  68.  *                                                                   *
  69.  *********************************************************************/
  70.  
  71. #pragma strings(readonly)   // used for debug version of memory mgmt routines
  72.  
  73. /*********************************************************************/
  74. /*------- Include relevant sections of the OS/2 header files --------*/
  75. /*********************************************************************/
  76.  
  77. #define  INCL_WINERRORS
  78. #define  INCL_WINDIALOGS
  79. #define  INCL_WINFRAMEMGR
  80. #define  INCL_WINLISTBOXES
  81. #define  INCL_WINPOINTERS
  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 "drgrendr.h"
  99.  
  100. /*********************************************************************/
  101. /*------------------- APPLICATION DEFINITIONS -----------------------*/
  102. /*********************************************************************/
  103.  
  104. #define PROGRAM_TITLE               "Drag/Drop Rendering Sample"
  105.  
  106. #define MESSAGE_SIZE                1024
  107.  
  108. #define TITLE_FOR_DROPCNR_FRAME     "'Drop' Container"
  109. #define TITLE_FOR_DRAGCNR_FRAME     "'Drag' Container"
  110.  
  111. #define FRAME_FLAGS                 (FCF_TASKLIST   | FCF_TITLEBAR | \
  112.                                      FCF_SYSMENU    | FCF_MINMAX   | \
  113.                                      FCF_SIZEBORDER | FCF_ICON     | \
  114.                                      FCF_ACCELTABLE)
  115.  
  116. #define CONTAINER_STYLES            (CCS_EXTENDSEL | CCS_MINIRECORDCORE | \
  117.                                      CCS_AUTOPOSITION)
  118.  
  119. /**********************************************************************/
  120. /*---------------------------- STRUCTURES ----------------------------*/
  121. /**********************************************************************/
  122.  
  123. typedef struct _LBFRAMEDATA         // LISTBOX FRAME'S WINDOW WORD DATA
  124. {
  125.     HWND    hwndCnr;                // Container window handle
  126.     PCNRREC pCnrRec;                // Record whose table is being displayed in
  127. } LBFRAMEDATA, *PLBFRAMEDATA;       //    the listbox
  128.  
  129. /**********************************************************************/
  130. /*----------------------- FUNCTION PROTOTYPES ------------------------*/
  131. /**********************************************************************/
  132.  
  133. int  main             ( void );
  134. void GetCurrentPath   ( void );
  135. BOOL CreateWindows    ( HAB hab );
  136. HWND CreateWindow     ( HAB hab, PFRAMECDATA pfcdata, ULONG idWindow,
  137.                         PSZ pszWindow, PSZ pszCnrTitle );
  138. BOOL InsertRecords    ( HWND hwndCnr );
  139. void DisplayTable     ( HWND hwndCnr, PCNRREC pCnrRec );
  140. void DestroyWindows   ( void );
  141. void DeleteTempFiles  ( void );
  142.  
  143. FNWP wpFrame, wpLBFrame;
  144.  
  145. /**********************************************************************/
  146. /*------------------------ GLOBAL VARIABLES --------------------------*/
  147. /**********************************************************************/
  148.  
  149. PFNWP pfnwpFrame, pfnwpLBFrame;
  150.  
  151. HWND hwndDrag,           // Window that is the source of the drag
  152.      hwndDrop;           // Window that is the target of the drop
  153.  
  154. char szDragCnrTitle[] = "Take a 'table' and drop it on the other window";
  155. char szDropCnrTitle[] = "Go ahead. Drag one of those tables on me!";
  156.  
  157. /**********************************************************************/
  158. /*------------------------------ MAIN --------------------------------*/
  159. /*                                                                    */
  160. /*  PROGRAM ENTRYPOINT                                                */
  161. /*                                                                    */
  162. /*  PARMS: nothing                                                    */
  163. /*                                                                    */
  164. /*  NOTES:                                                            */
  165. /*                                                                    */
  166. /*  RETURNS: return code                                              */
  167. /*                                                                    */
  168. /*--------------------------------------------------------------------*/
  169. /**********************************************************************/
  170. int main( void )
  171. {
  172.     HAB  hab;
  173.     HMQ  hmq = NULLHANDLE;
  174.     QMSG qmsg;
  175.  
  176.     // This macro is defined for the debug version of the C Set/2 Memory
  177.     // Management routines. Since the debug version writes to stderr, we
  178.     // send all stderr output to a debuginfo file.
  179.  
  180. #ifdef __DEBUG_ALLOC__
  181.     freopen( DEBUG_FILENAME, "w", stderr );
  182. #endif
  183.  
  184.     GetCurrentPath();
  185.  
  186.     hab = WinInitialize( 0 );
  187.  
  188.     if( hab )
  189.         hmq = WinCreateMsgQueue( hab, 0 );
  190.     else
  191.     {
  192.         DosBeep( 1000, 100 );
  193.         fprintf( stderr, "WinInitialize failed!" );
  194.     }
  195.  
  196.     if( hmq )
  197.     {
  198.         if( CreateWindows( hab ) )
  199.         {
  200.             while( WinGetMsg( hab, &qmsg, NULLHANDLE, 0, 0 ) )
  201.                 WinDispatchMsg( hab, &qmsg );
  202.  
  203.             DestroyWindows();
  204.         }
  205.     }
  206.     else if( hab )
  207.         Msg( "WinCreateMsgQueue RC(%X)", HABERR( hab ) );
  208.  
  209.     if( hmq )
  210.         WinDestroyMsgQueue( hmq );
  211.  
  212.     if( hab )
  213.         WinTerminate( hab );
  214.  
  215.     DeleteTempFiles();
  216.  
  217. #ifdef __DEBUG_ALLOC__
  218.     _dump_allocated( -1 );
  219. #endif
  220.  
  221.     return 0;
  222. }
  223.  
  224. /**********************************************************************/
  225. /*------------------------- GetCurrentPath ---------------------------*/
  226. /*                                                                    */
  227. /*  STORE THE CURRENT DRIVE/DIRECTORY.                                */
  228. /*                                                                    */
  229. /*  PARMS: nothing                                                    */
  230. /*                                                                    */
  231. /*  NOTES: This stores the current drive:\directory\  that is used    */
  232. /*         to create temporary files in.                              */
  233. /*                                                                    */
  234. /*  RETURNS: nothing                                                  */
  235. /*                                                                    */
  236. /*--------------------------------------------------------------------*/
  237. /**********************************************************************/
  238. void GetCurrentPath()
  239. {
  240.     PBYTE  pbCurrent = szCurrentPath;
  241.     INT    cbBuf = sizeof szCurrentPath, cbUsed;
  242.     ULONG  ulDrive, ulCurrDriveNo, ulDriveMap, cbPath;
  243.     APIRET rc;
  244.  
  245.     // Fill in the drive letter, colon, and backslash
  246.  
  247.     rc = DosQueryCurrentDisk( &ulCurrDriveNo, &ulDriveMap );
  248.  
  249.     if( !rc )                                // Use 'current' drive
  250.     {
  251.         *(pbCurrent++) = (BYTE) (ulCurrDriveNo + ('A' - 1));
  252.         *(pbCurrent++) = ':';
  253.         *(pbCurrent++) = '\\';
  254.     }
  255.     else
  256.     {                                        // API failed - use drive C:
  257.         strcpy( pbCurrent, "C:\\" );
  258.         pbCurrent += 3;                      // Incr our place in the buffer
  259.     }
  260.  
  261.     cbUsed = pbCurrent - szCurrentPath;      // How many bytes left?
  262.  
  263.     // Fill in the current directory
  264.  
  265.     ulDrive = *szCurrentPath - 'A' + 1;      // Get drive number from letter
  266.     cbPath = cbBuf - cbUsed;                 // How many bytes left?
  267.  
  268.     rc = DosQueryCurrentDir( ulDrive, pbCurrent, &cbPath );
  269.                                              // Get 'current' directory
  270.     if( szCurrentPath[ strlen( szCurrentPath ) - 1 ] != '\\' )
  271.         strcat( szCurrentPath, "\\" );       // Add trailing backslash
  272. }
  273.  
  274. /**********************************************************************/
  275. /*------------------------- CreateWindows ----------------------------*/
  276. /*                                                                    */
  277. /*  CREATE BOTH THE SOURCE AND TARGET WINDOWS.                        */
  278. /*                                                                    */
  279. /*  PARMS: anchor block handle                                        */
  280. /*                                                                    */
  281. /*  NOTES:                                                            */
  282. /*                                                                    */
  283. /*  RETURNS: TRUE or FALSE if successful or not                       */
  284. /*                                                                    */
  285. /*--------------------------------------------------------------------*/
  286. /**********************************************************************/
  287. BOOL CreateWindows( HAB hab )
  288. {
  289.     BOOL       fSuccess = TRUE;
  290.     FRAMECDATA fcdata;
  291.  
  292.     memset( &fcdata, 0, sizeof fcdata );
  293.     fcdata.cb            = sizeof( FRAMECDATA );
  294.     fcdata.flCreateFlags = FRAME_FLAGS;
  295.  
  296.     // Create 2 windows. One will act as the 'drag' window, the other as the
  297.     // 'drop' window. The user will then be able to drag the windows from the
  298.     // 'drag' window to the 'drop' window.
  299.  
  300.     hwndDrag = CreateWindow( hab, &fcdata, ID_DRAGCNR, TITLE_FOR_DRAGCNR_FRAME,
  301.                              szDragCnrTitle );
  302.     if( hwndDrag )
  303.     {
  304.         hwndDrop = CreateWindow( hab, &fcdata, ID_DROPCNR,
  305.                                  TITLE_FOR_DROPCNR_FRAME, szDropCnrTitle );
  306.         if( !hwndDrop )
  307.             fSuccess = FALSE;
  308.     }
  309.     else
  310.         fSuccess = FALSE;
  311.  
  312.     // Load the icons that will be used for the container records.
  313.  
  314.     hptrDragMe = WinLoadPointer( HWND_DESKTOP, 0, ID_DRAGCNR );
  315.     hptrOpenMe = WinLoadPointer( HWND_DESKTOP, 0, ID_DROPCNR );
  316.  
  317.     // Insert the records into the 'drag' container.
  318.  
  319.     if( fSuccess )
  320.         fSuccess = InsertRecords( WinWindowFromID( hwndDrag, FID_CLIENT ) );
  321.  
  322.     if( fSuccess )
  323.     {
  324.         LONG cxDesktop = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
  325.         LONG cyDesktop = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
  326.  
  327.         // Set the windows up so they split the bottom half of the display. The
  328.         // left window will be the 'drag' window, the right one will be the
  329.         // 'drop' window.
  330.  
  331.         if( !WinSetWindowPos( hwndDrag, HWND_TOP, 0, 0,
  332.                               cxDesktop /2, cyDesktop / 2,
  333.                   SWP_SIZE | SWP_ZORDER | SWP_MOVE | SWP_SHOW | SWP_ACTIVATE ) )
  334.         {
  335.             fSuccess = FALSE;
  336.             Msg( "WinSetWindowPos( hwndDrag ) RC(%X)", HABERR( hab ) );
  337.         }
  338.  
  339.         if( fSuccess &&
  340.             !WinSetWindowPos( hwndDrop, HWND_TOP, cxDesktop / 2, 0,
  341.                               cxDesktop /2, cyDesktop / 2,
  342.                               SWP_SIZE | SWP_ZORDER | SWP_MOVE | SWP_SHOW ) )
  343.         {
  344.             fSuccess = FALSE;
  345.             Msg( "WinSetWindowPos( hwndDrop ) RC(%X)", HABERR( hab ) );
  346.         }
  347.  
  348.         if( fSuccess )
  349.         {
  350.             // The container was set up as the client window of the frame. We
  351.             // need to set focus to it - otherwise it will not accept keystrokes
  352.             // right away.
  353.  
  354.             WinSetFocus( HWND_DESKTOP,
  355.                          WinWindowFromID( hwndDrag, FID_CLIENT ) );
  356.         }
  357.     }
  358.  
  359.     if( !fSuccess )
  360.     {
  361.         if( hwndDrag )
  362.         {
  363.             WinDestroyWindow( hwndDrag );
  364.             hwndDrag = NULLHANDLE;
  365.         }
  366.  
  367.         if( hwndDrop )
  368.         {
  369.             WinDestroyWindow( hwndDrop );
  370.             hwndDrop = NULLHANDLE;
  371.         }
  372.     }
  373.  
  374.     return fSuccess;
  375. }
  376.  
  377. /**********************************************************************/
  378. /*-------------------------- CreateWindow ----------------------------*/
  379. /*                                                                    */
  380. /*  CREATE A FRAME WINDOW WITH A CONTAINER AS ITS CLIENT WINDOW       */
  381. /*                                                                    */
  382. /*  PARMS: anchor block handle,                                       */
  383. /*         pointer to frame control data,                             */
  384. /*         id of the frame window,                                    */
  385. /*         window title of the frame window,                          */
  386. /*         container title                                            */
  387. /*                                                                    */
  388. /*  NOTES:                                                            */
  389. /*                                                                    */
  390. /*  RETURNS: frame window handle or NULLHANDLE if not successful      */
  391. /*                                                                    */
  392. /*--------------------------------------------------------------------*/
  393. /**********************************************************************/
  394. HWND CreateWindow( HAB hab, PFRAMECDATA pfcdata, ULONG idWindow, PSZ pszWindow,
  395.                    PSZ pszCnrTitle )
  396. {
  397.     HWND hwndFrame = NULLHANDLE, hwndCnr = NULLHANDLE;
  398.  
  399.     pfcdata->idResources = idWindow;  // Let the frame know its icon id
  400.  
  401.     // Create the container as the client window of the frame. There is no
  402.     // need for a normal client window. Because of this we must subclass the
  403.     // frame window so we can catch the messages that the container sends to
  404.     // its owner.
  405.  
  406.     hwndFrame = WinCreateWindow( HWND_DESKTOP, WC_FRAME, NULL,
  407.                                  FS_NOBYTEALIGN | WS_CLIPCHILDREN,
  408.                                  0, 0, 0, 0, NULLHANDLE, HWND_TOP,
  409.                                  idWindow, pfcdata, NULL );
  410.     if( hwndFrame )
  411.     {
  412.         pfnwpFrame = WinSubclassWindow( hwndFrame, wpFrame );
  413.  
  414.         if( pfnwpFrame )
  415.         {
  416.             hwndCnr = WinCreateWindow( hwndFrame, WC_CONTAINER, NULL,
  417.                                        WS_VISIBLE | CONTAINER_STYLES,
  418.                                        0, 0, 0, 0, hwndFrame, HWND_TOP,
  419.                                        FID_CLIENT, NULL, NULL );
  420.             if( hwndCnr )
  421.                 WinSetWindowText( hwndFrame, pszWindow );
  422.             else
  423.             {
  424.                 WinDestroyWindow( hwndFrame );
  425.                 hwndFrame = NULLHANDLE;
  426.                 Msg( "WinCreateWindow(hwndCnr,%s) RC(%X)", pszWindow,
  427.                      HABERR( hab ) );
  428.             }
  429.         }
  430.         else
  431.         {
  432.             WinDestroyWindow( hwndFrame );
  433.             hwndFrame = NULLHANDLE;
  434.             Msg( "WinSubclassWindow(%s) RC(%X)", pszWindow, HABERR( hab ) );
  435.         }
  436.     }
  437.     else
  438.         Msg( "WinCreateWindow(%s) RC(%X)", pszWindow, HABERR( hab ) );
  439.  
  440.     if( hwndFrame )
  441.     {
  442.         CNRINFO cnri;
  443.  
  444.         // Set container into Icon view and give it a read-only title
  445.  
  446.         cnri.cb           = sizeof( CNRINFO );
  447.         cnri.pszCnrTitle  = pszCnrTitle;
  448.         cnri.flWindowAttr = CV_ICON | CA_CONTAINERTITLE | CA_TITLESEPARATOR |
  449.                             CA_TITLEREADONLY;
  450.  
  451.         if( !WinSendMsg( hwndCnr, CM_SETCNRINFO, MPFROMP( &cnri ),
  452.                          MPFROMLONG( CMA_FLWINDOWATTR | CMA_CNRTITLE ) ) )
  453.         {
  454.             WinDestroyWindow( hwndFrame );
  455.             hwndFrame = NULLHANDLE;
  456.             Msg( "CM_SETCNRINFO(%S) RC(%X)", pszWindow, HABERR( hab ) );
  457.         }
  458.     }
  459.  
  460.     if( hwndFrame )
  461.     {
  462.         PINSTANCE pi;
  463.  
  464.         // Allocate memory for the instance data and set it into the
  465.         // Frame window's QWL_USER window word.
  466.  
  467.         pi = (PINSTANCE) malloc( sizeof *pi );
  468.         if( pi )
  469.         {
  470.             memset( pi, 0, sizeof *pi );
  471.             WinSetWindowPtr( hwndFrame, QWL_USER, pi );
  472.         }
  473.         else
  474.         {
  475.             WinDestroyWindow( hwndFrame );
  476.             hwndFrame = NULLHANDLE;
  477.             Msg( "Out of memory in CreateWindow!" );
  478.         }
  479.     }
  480.  
  481.     return hwndFrame;
  482. }
  483.  
  484. /**********************************************************************/
  485. /*-------------------------- InsertRecords ---------------------------*/
  486. /*                                                                    */
  487. /*  INSERT RECORDS INTO A CONTAINER                                   */
  488. /*                                                                    */
  489. /*  PARMS: container window handle                                    */
  490. /*                                                                    */
  491. /*  NOTES: We use the enumeration functions in dbaccess.c to enumerate*/
  492. /*         all the tables in all the database files (dbase_?.db).     */
  493. /*         We insert a record into the container for each table that  */
  494. /*         we find.                                                   */
  495. /*                                                                    */
  496. /*  RETURNS: TRUE if successful, FALSE if not                         */
  497. /*                                                                    */
  498. /*--------------------------------------------------------------------*/
  499. /**********************************************************************/
  500. BOOL InsertRecords( HWND hwndCnr )
  501. {
  502.     HENUMTABLES  henum = dbBeginEnumTables();
  503.     BOOL         fSuccess = TRUE;
  504.     RECORDINSERT ri;
  505.     PCNRREC      pCnrRec;
  506.     char         szTableName[ CCHMAXPATH ];
  507.  
  508.     memset( &ri, 0, sizeof( RECORDINSERT ) );
  509.     ri.cb                 = sizeof( RECORDINSERT );
  510.     ri.pRecordOrder       = (PRECORDCORE) CMA_END;
  511.     ri.pRecordParent      = (PRECORDCORE) NULL;
  512.     ri.zOrder             = (USHORT) CMA_TOP;
  513.     ri.cRecordsInsert     = 1;
  514.     ri.fInvalidateRecord  = FALSE;
  515.  
  516.     if( henum )
  517.     {
  518.         while( fSuccess )
  519.         {
  520.             if( dbGetNextTable( henum, szTableName, sizeof szTableName ) )
  521.             {
  522.                 pCnrRec = WinSendMsg( hwndCnr, CM_ALLOCRECORD,
  523.                                       MPFROMLONG( EXTRA_BYTES ),
  524.                                       MPFROMLONG( 1 ) );
  525.  
  526.                 if( pCnrRec )
  527.                 {
  528.                     strcpy( pCnrRec->szTableName, szTableName );
  529.  
  530.                     pCnrRec->flAttr       = RECATTR_DRAGGABLE;
  531.                     pCnrRec->mrc.pszIcon  = (PSZ) &pCnrRec->szTableName;
  532.                     pCnrRec->mrc.hptrIcon = hptrDragMe;
  533.  
  534.                     if( !WinSendMsg( hwndCnr, CM_INSERTRECORD,
  535.                                      MPFROMP( pCnrRec ), MPFROMP( &ri ) ) )
  536.                         Msg( "InsertRecords CM_INSERTRECORD RC(%X)",
  537.                              HWNDERR( hwndCnr ) );
  538.                 }
  539.                 else
  540.                     Msg( "InsertRecords CM_ALLOCRECORD RC(%X)",
  541.                          HWNDERR( hwndCnr ) );
  542.             }
  543.             else
  544.                 break;
  545.         }
  546.  
  547.         dbEndEnumTables( henum );
  548.  
  549.         // By setting ri.fInvalidateRecord to FALSE, we are saying not to
  550.         // display the records yet. We display them only when they are all
  551.         // inserted by waiting until we get here and do an invalidate of all
  552.         // the records at once.
  553.  
  554.         if( !WinSendMsg( hwndCnr, CM_INVALIDATERECORD, NULL, NULL ) )
  555.             Msg( "InsertRecords CM_INVALIDATERECORD RC(%X)", HWNDERR(hwndCnr) );
  556.     }
  557.  
  558.     return fSuccess;
  559. }
  560.  
  561. /**********************************************************************/
  562. /*----------------------------- wpFrame ------------------------------*/
  563. /*                                                                    */
  564. /*  SUBCLASSED FRAME WINDOW PROCEDURE.                                */
  565. /*                                                                    */
  566. /*  PARMS: normal winproc parms                                       */
  567. /*                                                                    */
  568. /*  NOTES:                                                            */
  569. /*                                                                    */
  570. /*  RETURNS: MRESULT value                                            */
  571. /*                                                                    */
  572. /*--------------------------------------------------------------------*/
  573. /**********************************************************************/
  574. MRESULT EXPENTRY wpFrame( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  575. {
  576.     // Route all DM_ messages to drag.c
  577.  
  578.     if( msg == UM_DO_THE_RENDERING ||
  579.         (msg >= WM_DRAGFIRST && msg <= WM_DRAGLAST) )
  580.         return dragMessage( hwnd, msg, mp1, mp2 );
  581.  
  582.     switch( msg )
  583.     {
  584.         // Don't let the message queue be destroyed until the user has closed
  585.         // *both* windows. If SC_CLOSE gets processed by the default window
  586.         // proc, a WM_QUIT message will get posted to the queue which will in
  587.         // effect end this program.
  588.  
  589.         case WM_SYSCOMMAND:
  590.             if( SHORT1FROMMP( mp1 ) == SC_CLOSE )
  591.                 if( (hwnd == hwndDrag) && hwndDrop )
  592.                 {
  593.                     WinDestroyWindow( hwndDrag );
  594.                     hwndDrag = NULLHANDLE;
  595.                     WinSetActiveWindow( HWND_DESKTOP, hwndDrop );
  596.                     return 0;
  597.                 }
  598.                 else if( (hwnd == hwndDrop) && hwndDrag )
  599.                 {
  600.                     WinDestroyWindow( hwndDrop );
  601.                     hwndDrop = NULLHANDLE;
  602.                     WinSetActiveWindow( HWND_DESKTOP, hwndDrag );
  603.                     return 0;
  604.                 }
  605.  
  606.             break;
  607.  
  608.         // From the F3 accelerator key
  609.         case WM_COMMAND:
  610.             if( SHORT1FROMMP( mp1 ) == IDM_EXIT )
  611.             {
  612.                 WinPostMsg( hwnd, WM_SYSCOMMAND, MPFROMSHORT( SC_CLOSE ),
  613.                             MPFROM2SHORT( CMDSRC_ACCELERATOR, FALSE ) );
  614.                 return 0;
  615.             }
  616.  
  617.             break;
  618.  
  619.         case WM_DESTROY:
  620.         {
  621.             PINSTANCE pi = INSTDATA( hwnd );
  622.  
  623.             // Free the window word memory
  624.  
  625.             if( pi )
  626.                 free( pi );
  627.  
  628.             // Free all container resources associated with any records that
  629.             // were inserted (note that the container is actually the client
  630.             // window.
  631.  
  632.             WinSendDlgItemMsg( hwnd, FID_CLIENT, CM_REMOVERECORD, NULL,
  633.                                MPFROM2SHORT( 0, CMA_FREE ) );
  634.             break;
  635.         }
  636.  
  637.         case WM_CONTROL:
  638.             if( SHORT1FROMMP( mp1 ) == FID_CLIENT )
  639.                 switch( SHORT2FROMMP( mp1 ) )
  640.                 {
  641.                     case CN_ENTER:
  642.                     {
  643.                         PNOTIFYRECORDENTER pnre = (PNOTIFYRECORDENTER) mp2;
  644.                         if( pnre->pRecord &&
  645.                             (((PCNRREC)pnre->pRecord)->flAttr &
  646.                                                     RECATTR_OPENABLE ))
  647.                             DisplayTable( WinWindowFromID( hwnd, FID_CLIENT ),
  648.                                           (PCNRREC) pnre->pRecord );
  649.                         return 0;
  650.                     }
  651.  
  652.                     case CN_INITDRAG:
  653.                     {
  654.                         PCNRDRAGINIT pcdi = (PCNRDRAGINIT) mp2;
  655.                         if( pcdi->pRecord &&
  656.                             (((PCNRREC)pcdi->pRecord)->flAttr &
  657.                                                     RECATTR_DRAGGABLE ))
  658.                             dragInit( hwnd, pcdi );
  659.                         return 0;
  660.                     }
  661.  
  662.                     case CN_DRAGOVER:
  663.                         return dragOver( hwnd, (PCNRDRAGINFO) mp2 );
  664.  
  665.                     case CN_DROP:
  666.                         dragDrop( hwnd, (PCNRDRAGINFO) mp2 );
  667.                         return 0;
  668.                 }
  669.  
  670.             break;
  671.     }
  672.  
  673.     return pfnwpFrame( hwnd, msg, mp1, mp2 );
  674. }
  675.  
  676. /**********************************************************************/
  677. /*-------------------------- DisplayTable ----------------------------*/
  678. /*                                                                    */
  679. /*  DISPLAY A FILE (TABLE DATA) IN A LISTBOX WITHIN A FRAME WINDOW    */
  680. /*                                                                    */
  681. /*  PARMS: container window handle,                                   */
  682. /*         pointer to container record that has info for table        */
  683. /*                                                                    */
  684. /*  NOTES: We create a frame window with a listbox as its client      */
  685. /*         window and insert all records found in a file into the     */
  686. /*         listbox. This acts as a simple file viewer.                */
  687. /*                                                                    */
  688. /*         The files being displayed are files created during the     */
  689. /*         rendering operation that occurred as a result of dragging  */
  690. /*         an icon from the drag container to the drop container.     */
  691. /*                                                                    */
  692. /*  RETURNS: nothing                                                  */
  693. /*                                                                    */
  694. /*--------------------------------------------------------------------*/
  695. /**********************************************************************/
  696. void DisplayTable( HWND hwndCnr, PCNRREC pCnrRec )
  697. {
  698.     FRAMECDATA  fcdata;
  699.     HWND        hwndFrame, hwndLB;
  700.  
  701.     // If the container record that the user double-clicked on is currently
  702.     // being displayed, set focus to that window and exit.
  703.  
  704.     if( pCnrRec->hwndDisplay )
  705.     {
  706.         WinSetActiveWindow( HWND_DESKTOP, pCnrRec->hwndDisplay );
  707.         return;
  708.     }
  709.  
  710.     (void) memset( &fcdata, 0, sizeof( FRAMECDATA ) );
  711.     fcdata.cb            = sizeof( FRAMECDATA );
  712.     fcdata.flCreateFlags = FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER |
  713.                            FCF_MINMAX;
  714.  
  715.     hwndFrame = WinCreateWindow( HWND_DESKTOP, WC_FRAME, NULL,
  716.                                  WS_CLIPCHILDREN, 100, 100, 400, 200,
  717.                                  NULLHANDLE, HWND_TOP, 1, &fcdata, NULL );
  718.     if( hwndFrame )
  719.     {
  720.         WinSetWindowPtr( hwndFrame, QWL_USER, pCnrRec );
  721.  
  722.         hwndLB = WinCreateWindow( hwndFrame, WC_LISTBOX, NULL,
  723.                                   WS_VISIBLE | LS_HORZSCROLL | LS_NOADJUSTPOS,
  724.                                   0, 0, 0, 0, hwndFrame, HWND_TOP, FID_CLIENT,
  725.                                   NULL, NULL );
  726.         if( hwndLB )
  727.         {
  728.             pfnwpLBFrame = WinSubclassWindow( hwndFrame, wpLBFrame );
  729.  
  730.             if( pfnwpLBFrame )
  731.             {
  732.                 FILE *fh;
  733.                 PLBFRAMEDATA plbfd = (PLBFRAMEDATA) malloc( sizeof *plbfd );
  734.  
  735.                 if( plbfd )
  736.                 {
  737.                     plbfd->hwndCnr = hwndCnr;
  738.                     plbfd->pCnrRec = pCnrRec;
  739.                     WinSetWindowPtr( hwndFrame, QWL_USER, plbfd );
  740.  
  741.                     WinSendMsg( hwndFrame, WM_UPDATEFRAME, NULL, NULL );
  742.                     WinSetWindowText( hwndFrame, pCnrRec->szTableName );
  743.  
  744.                     fh = fopen( pCnrRec->szRenderedFileName, "r" );
  745.                     if( fh )
  746.                     {
  747.                         char szLine[ CCHMAXPATH ];
  748.  
  749.                         while( fgets( szLine, sizeof szLine, fh ) )
  750.                         {
  751.                             if( szLine[ strlen( szLine ) - 1 ] == '\n' )
  752.                                 szLine[ strlen( szLine ) - 1 ] = 0;
  753.  
  754.                             WinSendMsg( hwndLB, LM_INSERTITEM,
  755.                                         MPFROMSHORT(LIT_END), MPFROMP(szLine) );
  756.                         }
  757.  
  758.                         fclose( fh );
  759.                     }
  760.                     else
  761.                         WinSendMsg( hwndLB, LM_INSERTITEM, MPFROMSHORT(LIT_END),
  762.                                     "Could not open file!" );
  763.  
  764.                     pCnrRec->hwndDisplay = hwndFrame;
  765.  
  766.                     // Set on the In-Use emphasis to the container record that
  767.                     // represents the table so the user knows that a listbox
  768.                     // is on his desktop that represents the table.
  769.  
  770.                     WinSendMsg( hwndCnr, CM_SETRECORDEMPHASIS,
  771.                                 MPFROMP( pCnrRec ),
  772.                                 MPFROM2SHORT( TRUE, CRA_INUSE ) );
  773.  
  774.                     WinSetWindowPos( hwndFrame, HWND_TOP, 0, 0, 0, 0,
  775.                                      SWP_SHOW | SWP_ACTIVATE | SWP_ZORDER );
  776.                 }
  777.                 else
  778.                     WinDestroyWindow( hwndFrame );
  779.             }
  780.             else
  781.                 WinDestroyWindow( hwndFrame );
  782.         }
  783.         else
  784.             WinDestroyWindow( hwndFrame );
  785.     }
  786. }
  787.  
  788. MRESULT EXPENTRY wpLBFrame( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  789. {
  790.     switch( msg )
  791.     {
  792.         case WM_SYSCOMMAND:
  793.             if( SHORT1FROMMP( mp1 ) == SC_CLOSE )
  794.                 WinDestroyWindow( hwnd );
  795.  
  796.             return 0;
  797.  
  798.         case WM_DESTROY:
  799.         {
  800.             PLBFRAMEDATA plbfd =
  801.                     (PLBFRAMEDATA) WinQueryWindowPtr( hwnd, QWL_USER );
  802.  
  803.             if( plbfd )
  804.             {
  805.                 // Take off the In-Use emphasis that was set on for the
  806.                 // container record when this listbox-frame was created.
  807.  
  808.                 WinSendMsg( plbfd->hwndCnr, CM_SETRECORDEMPHASIS,
  809.                             MPFROMP( plbfd->pCnrRec ),
  810.                             MPFROM2SHORT( FALSE, CRA_INUSE ) );
  811.                 plbfd->pCnrRec->hwndDisplay = NULLHANDLE;
  812.                 free( plbfd );
  813.             }
  814.         }
  815.     }
  816.  
  817.     return pfnwpLBFrame( hwnd, msg, mp1, mp2 );
  818. }
  819.  
  820. /**********************************************************************/
  821. /*------------------------- DeleteTempFiles --------------------------*/
  822. /*                                                                    */
  823. /*  DELETE THE TEMPORARY FILES USED BY THIS PROGRAM.                  */
  824. /*                                                                    */
  825. /*  PARMS: nothing                                                    */
  826. /*                                                                    */
  827. /*  NOTES: A temporary file is created in the current directory each  */
  828. /*         time an icon is dragged from the 'drag' container to the   */
  829. /*         'drop' container. Here we delete all those temporary files.*/
  830. /*                                                                    */
  831. /*  RETURNS: nothing                                                  */
  832. /*                                                                    */
  833. /*--------------------------------------------------------------------*/
  834. /**********************************************************************/
  835. void DeleteTempFiles()
  836. {
  837.     FILEFINDBUF3 ffb;
  838.     HDIR         hdir = HDIR_SYSTEM;
  839.     ULONG        cFiles = 1;
  840.     char         szTempFileSpec[ CCHMAXPATH ];
  841.     APIRET       rc;
  842.  
  843.     strcpy( szTempFileSpec, szCurrentPath );
  844.     strcat( szTempFileSpec, BASE_TEMPFILE_NAME );
  845.     strcat( szTempFileSpec, ".*" );
  846.  
  847.     rc = DosFindFirst( szTempFileSpec, &hdir, FILE_NORMAL,
  848.                        &ffb, sizeof ffb, &cFiles, FIL_STANDARD );
  849.     while( !rc )
  850.     {
  851.         DosDelete( ffb.achName );
  852.         rc = DosFindNext( hdir, &ffb, sizeof ffb, &cFiles );
  853.     }
  854. }
  855.  
  856. /**********************************************************************/
  857. /*------------------------- DestroyWindows ---------------------------*/
  858. /*                                                                    */
  859. /*  DESTROY THE WINDOWS AND RESOURCES USED IN THIS PROGRAM.           */
  860. /*                                                                    */
  861. /*  PARMS: nothing                                                    */
  862. /*                                                                    */
  863. /*  NOTES:                                                            */
  864. /*                                                                    */
  865. /*  RETURNS: nothing                                                  */
  866. /*                                                                    */
  867. /*--------------------------------------------------------------------*/
  868. /**********************************************************************/
  869. void DestroyWindows()
  870. {
  871.     WinDestroyWindow( hwndDrag );
  872.     WinDestroyWindow( hwndDrop );
  873.  
  874.     WinDestroyPointer( hptrDragMe );
  875.     WinDestroyPointer( hptrOpenMe );
  876. }
  877.  
  878. /**********************************************************************/
  879. /*------------------------------- Msg --------------------------------*/
  880. /*                                                                    */
  881. /*  DISPLAY A MESSAGE TO THE USER.                                    */
  882. /*                                                                    */
  883. /*  PARMS: a message in printf format with its parms                  */
  884. /*                                                                    */
  885. /*  NOTES:                                                            */
  886. /*                                                                    */
  887. /*  RETURNS: nothing                                                  */
  888. /*                                                                    */
  889. /*--------------------------------------------------------------------*/
  890. /**********************************************************************/
  891. void Msg( PSZ szFormat,... )
  892. {
  893.     PSZ     szMsg;
  894.     va_list argptr;
  895.  
  896.     szMsg = (PSZ) malloc( MESSAGE_SIZE );
  897.     if( szMsg )
  898.     {
  899.         va_start( argptr, szFormat );
  900.         vsprintf( szMsg, szFormat, argptr );
  901.         va_end( argptr );
  902.  
  903.         szMsg[ MESSAGE_SIZE - 1 ] = 0;
  904.  
  905.         WinAlarm( HWND_DESKTOP, WA_WARNING );
  906.         WinMessageBox(  HWND_DESKTOP, HWND_DESKTOP, szMsg,
  907.                         "Container Drag/Drop Sample Program", 1,
  908.                         MB_OK | MB_MOVEABLE );
  909.         free( szMsg );
  910.     }
  911.     else
  912.     {
  913.         DosBeep( 1000, 1000 );
  914.         return;
  915.     }
  916. }
  917.  
  918. /*************************************************************************
  919.  *                     E N D     O F     S O U R C E                     *
  920.  *************************************************************************/
  921.