home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / pm / dragdrop / dragdrop.c < prev    next >
C/C++ Source or Header  |  1999-05-11  |  30KB  |  897 lines

  1. /**************************************************************************
  2.  *  File name  :  dragdrop.c
  3.  *
  4.  *  Description:  This sample creates a listbox in the client area and
  5.  *                populates it with the members of the current directory.
  6.  *                The user can navigate downward in the directory hierarchy
  7.  *                by using a directory selection dialog or by
  8.  *                double-clicking on a directory in the list.  The user can
  9.  *                navigate upward by using the selection dialog.  Files can
  10.  *                be moved between drives and/or directories by selecting
  11.  *                one or more files from one running instance of the program
  12.  *                (A) and pressing and holding mouse button 2 to drag them
  13.  *                to another running instance of the program (B).  When
  14.  *                button 2 is released over the target program, the files
  15.  *                selected from A are moved to the directory currently
  16.  *                displayed by B.
  17.  *
  18.  *                This source file contains the following functions:
  19.  *
  20.  *                main()
  21.  *                ClientWndProc(hwnd, msg, mp1, mp2)
  22.  *                OpenDlgProc(hwnd, msg, mp1, mp2)
  23.  *                ChangeDir(pszDirectory)
  24.  *                PopulateList(hwndContainer, pszDir)
  25.  *                ListSubclassProc(hwnd, msg, mp1, mp2)
  26.  *                Message(pszMsg)
  27.  *                MessageBox(hwndOwner, idMsg, fsStyle, fBeep)
  28.  *
  29.  *  Concepts   :  listboxes, directory search
  30.  *
  31.  *  API's      :  WinInitialize
  32.  *                DosBeep
  33.  *                WinCreateMsgQueue
  34.  *                WinTerminate
  35.  *                WinLoadString
  36.  *                WinRegisterClass
  37.  *                WinCreateStdWindow
  38.  *                WinGetMsg
  39.  *                WinDispatchMsg
  40.  *                WinDestroyWindow
  41.  *                WinDestroyMsgQueue
  42.  *                DosQueryCurrentDir
  43.  *                WinQuerySysPointer
  44.  *                WinLoadPointer
  45.  *                WinPostMsg
  46.  *                WinSetPointer
  47.  *                WinDestroyPointer
  48.  *                WinSetWindowPos
  49.  *                WinQueryWindowRect
  50.  *                WinCreateWindow
  51.  *                WinSubclassWindow
  52.  *                WinSetFocus
  53.  *                WinWindowFromID
  54.  *                WinBeginPaint
  55.  *                GpiErase
  56.  *                WinEndPaint
  57.  *                WinDlgBox
  58.  *                WinQueryLboxCount
  59.  *                WinQueryLboxItemText
  60.  *                WinDefWindowProc
  61.  *                WinSendDlgItemMsg
  62.  *                WinSetDlgItemText
  63.  *                WinQueryWindowText
  64.  *                WinWindowFromID
  65.  *                WinDismissDlg
  66.  *                WinDefDlgProc
  67.  *                DosSetCurrentDir
  68.  *                WinSetWindowText
  69.  *                WinEnableWindowUpdate
  70.  *                WinShowWindow
  71.  *                WinMessageBox
  72.  *                WinLoadMessage
  73.  *                WinAlarm
  74.  *
  75.  *  Required
  76.  *    Files    :  OS2.H, STRING.H, STDIO.H, STDLIB.H, DRAGDROP.H
  77.  *
  78.  *  Copyright (C) 1991 IBM Corporation
  79.  *
  80.  *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
  81.  *      sample code created by IBM Corporation. This sample code is not
  82.  *      part of any standard or IBM product and is provided to you solely
  83.  *      for  the purpose of assisting you in the development of your
  84.  *      applications.  The code is provided "AS IS", without
  85.  *      warranty of any kind.  IBM shall not be liable for any damages
  86.  *      arising out of your use of the sample code, even if they have been
  87.  *      advised of the possibility of such damages.                                                    *
  88.  *************************************************************************/
  89.  
  90. /*
  91.  *        Include the required sections from the PM header file
  92.  */
  93. #define INCL_DOSFILEMGR
  94. #define INCL_WIN
  95. #define INCL_WINSTDDRAG
  96.  
  97. /*
  98.  *                     Include the PM header file
  99.  */
  100. #include <os2.h>
  101.  
  102. /*
  103.  *                  Include the C library header files
  104.  */
  105. #include <stdio.h>
  106. #include <stdlib.h>
  107. #include <string.h>
  108.  
  109. /*
  110.  *                 Include the application header files
  111.  */
  112. #include "dragdrop.h"
  113.  
  114. /*
  115.  * Variables global to file
  116.  */
  117. static HAB   hab;
  118. static CHAR  szCurrentDir[CCHMAXPATH]; /* always contains the current dir   */
  119. static CHAR  szTemp[CCHMAXPATH];
  120. static CHAR  szClientClass[12];        /* "DragDrop"                        */
  121. static HWND  hwndClient;               /* needed by change dir function     */
  122. static PFNWP pfnwpList;                /* save listbox proc address         */
  123. static HWND  hwndList;                 /* handle to list control            */
  124.  
  125. static HPOINTER hptrBusy;              /* Mouse Pointer to show when a      */
  126.                                        /* drag is in progress               */
  127.  
  128. USHORT cDragFiles;
  129.  
  130. /**************************************************************************
  131.  *
  132.  *  Name       : main()
  133.  *
  134.  *  Description: Initializes the PM environment, calls the
  135.  *               initialization routine, creates the main
  136.  *               window,  and polls the message queue
  137.  *
  138.  *  Concepts   : - obtains anchor block handle and creates message
  139.  *                   queue
  140.  *               - calls the initialization routine
  141.  *               - creates the main frame window which creates the
  142.  *                   main client window
  143.  *               - polls the message queue via Get/Dispatch Msg loop
  144.  *               - upon exiting the loop, exits
  145.  *
  146.  *  API's      :   WinInitialize
  147.  *                 DosBeep
  148.  *                 WinCreateMsgQueue
  149.  *                 WinTerminate
  150.  *                 WinLoadString
  151.  *                 WinRegisterClass
  152.  *                 WinCreateStdWindow
  153.  *                 WinGetMsg
  154.  *                 WinDispatchMsg
  155.  *                 WinDestroyWindow
  156.  *                 WinDestroyMsgQueue
  157.  *
  158.  *  Parameters :  [none]
  159.  *
  160.  *  Return     :  1 - if successful execution completed
  161.  *                0 - if error
  162.  *
  163.  *************************************************************************/
  164. int main(void)
  165. {
  166.    ULONG flFrameFlags = FCF_STANDARD;
  167.    HMQ   hmq;
  168.    HWND  hwndFrame;
  169.    QMSG  qmsg;
  170.  
  171.    hab = WinInitialize (0);
  172.    if(!hab)
  173.    {
  174.       DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
  175.       return(RETURN_ERROR);
  176.    }
  177.  
  178.    hmq = WinCreateMsgQueue (hab, 0);
  179.  
  180.    if(!hmq)
  181.    {
  182.       DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
  183.       WinTerminate(hab);
  184.       return(RETURN_ERROR);
  185.    }
  186.  
  187.    if(!WinLoadString(hab, 0, IDS_CLIENTCLASS,
  188.                     sizeof(szClientClass), szClientClass))
  189.       return 0;
  190.    WinRegisterClass (hab, szClientClass, ClientWndProc, 0L, 0L);
  191.  
  192.    if (0L != (hwndFrame = WinCreateStdWindow(HWND_DESKTOP, WS_VISIBLE,
  193.                                  &flFrameFlags, (PSZ)szClientClass, (PSZ)NULL,
  194.                                  0L, (HMODULE)0L, ID_RESOURCE,
  195.                                  &hwndClient)))
  196.  
  197.                 /* Get/Dispatch Message loop */
  198.    {
  199.       InitHelp(hab, hwndFrame);
  200.       while (WinGetMsg (hab, &qmsg, 0L, 0, 0))
  201.          WinDispatchMsg (hab, &qmsg);
  202.  
  203.       WinDestroyWindow (hwndFrame);
  204.  
  205.     /* destroy the help instance */
  206.       DestroyHelpInstance();
  207.    }
  208.    else
  209.    {
  210.       MessageBox(HWND_DESKTOP,
  211.                  IDMSG_MAINWINCREATEFAILED,
  212.                  MB_OK | MB_ERROR,
  213.                  TRUE);
  214.       return(RETURN_ERROR);
  215.    }
  216.  
  217.    WinDestroyMsgQueue (hmq);
  218.    WinTerminate (hab);
  219. }   /* End of main */
  220.  
  221.  
  222. /**************************************************************************
  223.  *
  224.  *  Name       : ClientWndProc(hwnd, msg, mp1, mp2)
  225.  *
  226.  *  Description: Processes the messages sent to the main client
  227.  *               window.  This routine processes the basic
  228.  *               messages all client windows should process.
  229.  *
  230.  *  Concepts   : Called for each message placed in the main
  231.  *               window's message queue
  232.  *
  233.  *               A switch statement branches to the routines to be
  234.  *               performed for each message processed.  Any messages
  235.  *               not specifically process are passed to the default
  236.  *               window procedure.
  237.  *
  238.  *  API's      : DosQueryCurrentDir
  239.  *               WinQuerySysPointer
  240.  *               WinLoadPointer
  241.  *               WinPostMsg
  242.  *               WinSetPointer
  243.  *               WinDestroyPointer
  244.  *               WinSetWindowPos
  245.  *               WinQueryWindowRect
  246.  *               WinCreateWindow
  247.  *               WinSetFocus
  248.  *               WinBeginPaint
  249.  *               GpiErase
  250.  *               WinEndPaint
  251.  *               WinDlgBox
  252.  *               WinQueryLboxCount
  253.  *               WinQueryLboxItemText
  254.  *               WinDefWindowProc
  255.  *
  256.  *  Parameters :  hwnd = window handle
  257.  *                msg  = message code
  258.  *                mp1  = first message parameter
  259.  *                mp2  = second message parameter
  260.  *
  261.  *  Return     :  values are determined by each message
  262.  *
  263.  *************************************************************************/
  264. MRESULT EXPENTRY ClientWndProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  265. {
  266.    static HPOINTER hptrFile, hptrFolder, hptrMulti;
  267.    SHORT           cxClient, cyClient;
  268.    HPS             hps;
  269.    RECTL           rClient;
  270.    USHORT          Item;
  271.    USHORT          i;
  272.    ULONG           ulDiskNum, ulLogicalDisk;
  273.  
  274.    switch (msg)
  275.    {
  276.    case WM_CREATE:
  277.       hwndClient = hwnd;
  278.  
  279.        /*
  280.         * Initialize strings for title and default directory
  281.         * and change the current directory to the default directory
  282.         */
  283.       DosQueryCurrentDisk(&ulDiskNum, &ulLogicalDisk);
  284.       szCurrentDir[0] = (CHAR)('A' - 1 + ulDiskNum);
  285.       szCurrentDir[1] = ':';
  286.       szCurrentDir[2] = '\\';
  287.  
  288.       {
  289.          PBYTE   pBuf   = szCurrentDir + 3;
  290.          ULONG   cbBuf  = CCHMAXPATH - 3;
  291.          PULONG  pcbBuf = &cbBuf;        
  292.  
  293.          DosQueryCurrentDir(0L, pBuf, pcbBuf);
  294.          if(szCurrentDir[3] == '\\')
  295.             szCurrentDir[3] = '\0';    /*  account for the root, if current */
  296.       }
  297.       ChangeDir(szCurrentDir);
  298.  
  299.        /*
  300.         * Load the standard system pointers for files, folders, multi-files
  301.         * and programs
  302.         */
  303.       hptrFile   = WinQuerySysPointer (HWND_DESKTOP, SPTR_FILE, FALSE);
  304.       hptrFolder = WinQuerySysPointer (HWND_DESKTOP, SPTR_FOLDER, FALSE);
  305.       hptrMulti  = WinQuerySysPointer (HWND_DESKTOP, SPTR_MULTFILE, FALSE);
  306.       hptrBusy   = WinLoadPointer     (HWND_DESKTOP, (HMODULE)0L, ID_BUSY);
  307.  
  308.        /*
  309.         * Post ourselves a message so that the list box can be created
  310.         */
  311.       WinPostMsg(hwnd, WM_CREATELIST, NULL, NULL);
  312.       return ((MRESULT) FALSE);
  313.  
  314.    case WM_MOUSEMOVE:
  315.       if (CheckBusy() || cDragFiles)
  316.       {
  317.          WinSetPointer(HWND_DESKTOP, hptrBusy);
  318.          return ((MRESULT) TRUE);
  319.       }
  320.       break;
  321.  
  322.    case WM_CLOSE:
  323.        /*
  324.         * Check to see if a drag is in progress and do not allow a close if
  325.         * that is the case.
  326.         */
  327.       return (CheckClose (hwnd));
  328.  
  329.    case WM_DESTROY:
  330.       WinDestroyPointer (hptrFile);
  331.       WinDestroyPointer (hptrFolder);
  332.       WinDestroyPointer (hptrMulti);
  333.       WinDestroyPointer (hptrBusy);
  334.       return (NULL);
  335.  
  336.    case WM_SIZE:
  337.        /*
  338.         * Save our size information and re-size the list box.
  339.         */
  340.       if(hwndList != 0L)
  341.       {
  342.          cxClient = SHORT1FROMMP (mp2);
  343.          cyClient = SHORT2FROMMP (mp2);
  344.          WinSetWindowPos(hwndList, HWND_TOP, 0, 0, cxClient, cyClient,
  345.                          SWP_MOVE | SWP_SIZE | SWP_SHOW);
  346.          return ((MRESULT)FALSE);
  347.       }
  348.       break;
  349.  
  350.    case WM_CREATELIST:
  351.        /*
  352.         * Create the list control.
  353.         */
  354.       WinQueryWindowRect(hwnd, &rClient);
  355.       cxClient = (SHORT) (rClient.xRight - rClient.xLeft);
  356.       cyClient = (SHORT) (rClient.yTop - rClient.yBottom);
  357.       hwndList = WinCreateWindow(hwnd, WC_LISTBOX, NULL,
  358.                                    WS_VISIBLE | LS_MULTIPLESEL,
  359.                                    0, 0, cxClient, cyClient,
  360.                                    hwnd, HWND_TOP, LIST_ID, NULL, NULL);
  361.  
  362.        /*
  363.         * If we couldn't create the listbox, display a message.
  364.         */
  365.       if (!hwndList)
  366.       {
  367.          MessageBox(hwnd, IDMSG_CANTCREATELIST, MB_OK | MB_ERROR, TRUE);
  368.       }
  369.  
  370.        /*
  371.         * Otherwise, the list was created successfully.
  372.         */
  373.       else
  374.       {
  375.          /*
  376.           * Subclass the list in the client area in order to intercept
  377.           * the mouse button 2 and drag messages. Then cause the list to
  378.           * be populated by posting ourselves a refresh message.
  379.           */
  380.          pfnwpList = WinSubclassWindow (hwndList, ListSubclassProc);
  381.          WinPostMsg (hwnd, WM_REFRESH, NULL, NULL);
  382.          WinSetFocus (HWND_DESKTOP, hwndList);
  383.       }
  384.       return ((MRESULT)FALSE);
  385.  
  386.    case WM_REFRESH:
  387.        /*
  388.         * Refresh the contents of the list by getting rid of its current
  389.         * contents and repopulating it.
  390.         */
  391.       WinDeleteLboxAll(hwndList);              /*  depopulate list  */
  392.       PopulateList (hwndList, szCurrentDir);
  393.       return ((MRESULT)FALSE);
  394.  
  395.    case WM_PAINT:
  396.        /*
  397.         * Just erase the background as there is no data in the client.
  398.         */
  399.       hps = WinBeginPaint (hwnd, 0L, NULL);
  400.       GpiErase (hps);
  401.       WinEndPaint (hps);
  402.       return ((MRESULT)FALSE);
  403.  
  404.      /*
  405.       * When the application is not minimized, drag messages will be sent to
  406.       * the list box, as it occupies the entire client window. The client
  407.       * window will see these as LN_drag messages. However, when the
  408.       * application is minimized, the client will see DM_drag messages,
  409.       * and must process these in the same way that the LN_drag messages are
  410.       * processed.  Note that a drag cannot be initiated while the application
  411.       * is minimized.
  412.       */
  413.  
  414.    case DM_DROPHELP:
  415.       return (DropHelp (hwnd, (PDRAGINFO) mp1));
  416.  
  417.    case DM_DRAGOVER:
  418.       return (DragOver (hab, (PDRAGINFO) mp1, szCurrentDir));
  419.  
  420.    case DM_DRAGLEAVE:
  421.       return (DragLeave ());
  422.  
  423.    case DM_DROP:
  424.       return (Drop(hab, hwnd, (PDRAGINFO) mp1, szCurrentDir));
  425.  
  426.    case DM_ENDCONVERSATION:
  427.        /*
  428.         * The end conversation message will always be sent to the client
  429.         * window. Just invoke the EndConversation function. It will take
  430.         * care of freeing the draginfo structure when its appropriate.
  431.         */
  432.       return (EndConversation (hab, hwnd, mp1, mp2));
  433.  
  434.    case WM_TARGETCOMPLETE:
  435.        /*
  436.         * This message is posted whenever a target thread has completed
  437.         * its processing. All resources allocated to the drag operation
  438.         * will be freed and the source will be notified that the
  439.         * operation(s) is complete.
  440.         */
  441.       return (EndTarget (hwnd, PVOIDFROMMP (mp1)));
  442.  
  443.    case WM_COMMAND:
  444.        /*
  445.         *  Handle action bar commands.
  446.         */
  447.       switch (SHORT1FROMMP(mp1))
  448.       {
  449.       case IDM_FILEOPEN:
  450.          if (WinDlgBox (HWND_DESKTOP, hwnd, (PFNWP)OpenDlgProc, (HMODULE)0L,
  451.                         IDD_OPEN, NULL))
  452.          {
  453.             ChangeDir (szCurrentDir);
  454.             WinPostMsg (hwnd, WM_REFRESH, NULL, NULL);
  455.          }
  456.          break;
  457.  
  458.       case IDM_WINDOWSELECTALL:
  459.       case IDM_WINDOWDESELECTALL:
  460.       {
  461.          USHORT cItems;
  462.  
  463.          cItems = WinQueryLboxCount (hwndList);
  464.  
  465.          for (i=0; i<cItems; i++)
  466.          {
  467.              WinSelectLboxItem (hwndList, i,
  468.                                ((SHORT1FROMMP(mp1)) == IDM_WINDOWSELECTALL));
  469.          }
  470.          break;
  471.       }
  472.  
  473.       case IDM_WINDOWREFRESH:
  474.          WinPostMsg (hwnd, WM_REFRESH, NULL, NULL);
  475.          break;
  476.  
  477.       case IDM_HELPINDEX:
  478.          HelpIndex(hwnd);
  479.          break;
  480.  
  481.       case IDM_HELPGENERAL:
  482.          HelpGeneral(hwnd);
  483.          break;
  484.  
  485.       case IDM_HELPUSINGHELP:
  486.          HelpUsingHelp(hwnd);
  487.          break;
  488.  
  489.       case IDM_HELPPRODUCTINFO:
  490.          HelpProductInfo(hwnd);
  491.          break;
  492.       }
  493.       break;
  494.  
  495.    case WM_CONTROL:
  496.        /*
  497.         * Handle list notification messages.
  498.         */
  499.       if (SHORT1FROMMP (mp1) == LIST_ID)
  500.       {
  501.          switch (SHORT2FROMMP (mp1))
  502.          {
  503.              case LN_ENTER:
  504.              {
  505.                 CHAR szTemp[CCHMAXPATH];
  506.  
  507.              /*
  508.               * User wishes to open a directory entry
  509.               *   - must be the first item selected
  510.               *   - selected item must be a directory
  511.               */
  512.                 Item = (USHORT) WinQueryLboxSelItemFirst (hwndList);
  513.  
  514.                 if (Item != LIT_NONE)
  515.                 {
  516.                    WinQueryLboxItemText (hwndList, Item, szTemp, sizeof(szTemp));
  517.  
  518.                /*
  519.                 * Is it a subdirectory?
  520.                 */
  521.                    if (szTemp[0] == '\\')
  522.                    {
  523.                  /*
  524.                   * Yes - it's a subdirectory.
  525.                   * Remove final '\\' from current directory, if present
  526.                   * and add the new subdirectory to the current directory.
  527.                   */
  528.                       RemoveFinalBackslash (szCurrentDir);
  529.                       strcat (szCurrentDir, szTemp);
  530.                       ChangeDir (szCurrentDir);
  531.                       WinPostMsg (hwnd, WM_REFRESH, NULL, NULL);
  532.                    }
  533.  
  534.                /*
  535.                 * No, show an error message.
  536.                 */
  537.                    else
  538.                    {
  539.                       MessageBox(HWND_DESKTOP,
  540.                                  IDMSG_NOTSUBDIRECTORY,
  541.                                  MB_OK | MB_ERROR,
  542.                                  TRUE);
  543.                    }
  544.                 }
  545.                 else
  546.                 {
  547.                    MessageBox(HWND_DESKTOP,
  548.                               IDMSG_MUSTBESELECTED,
  549.                               MB_OK | MB_ERROR,
  550.                               TRUE);
  551.                 }
  552.                 break;
  553.              }
  554.  
  555.              case LN_INITDRAG:
  556.                 if(InitDrag(hab, hwnd, hwndList, hptrFile,
  557.                                  hptrFolder, hptrMulti, szCurrentDir))
  558.                    return ((MRESULT)FALSE);
  559.                 else
  560.                    return ((MRESULT)TRUE);
  561.  
  562.              case LN_DROPHELP:
  563.                 return (DropHelp (hwnd, (PDRAGINFO) mp2));
  564.  
  565.              case LN_DRAGOVER:
  566.                 return (DragOver (hab, (PDRAGINFO) mp2, szCurrentDir));
  567.  
  568.              case LN_DRAGLEAVE:
  569.                 return (DragLeave ());
  570.  
  571.              case LN_DROP:
  572.                 return (Drop(hab, hwnd, (PDRAGINFO) mp2, szCurrentDir));
  573.           }
  574.        }
  575.        break;
  576.    }
  577.    return WinDefWindowProc (hwnd, msg, mp1, mp2);
  578. } /* End of ClientWndProc */
  579.  
  580. /**************************************************************************
  581.  *
  582.  *  Name       : OpenDlgProc(hwnd, msg, mp1, mp2)
  583.  *
  584.  * Description: Supports drive and directory navigation through the
  585.  *              file open pull down.  The complete path specification
  586.  *              must be entered by the user.
  587.  *
  588.  *  Concepts   : open dialog
  589.  *
  590.  *  API's      : WinSendDlgItemMsg
  591.  *               WinSetDlgItemText
  592.  *               WinSetFocus
  593.  *               WinWindowFromID
  594.  *               WinQueryWindowText
  595.  *               WinDismissDlg
  596.  *               WinDefDlgProc
  597.  *
  598.  *  Parameters :  hwnd = window handle
  599.  *                msg  = message code
  600.  *                mp1  = first message parameter
  601.  *                mp2  = second message parameter
  602.  *
  603.  *  Return     :  TRUE  - the directory and the title text for the
  604.  *                window have been successfully changed
  605.  *                FALSE - the input directory was invalid or the user
  606.  *                pressed Cancel
  607.  *
  608.  *************************************************************************/
  609. MRESULT EXPENTRY OpenDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  610. {
  611.    static CHAR szOldDir[CCHMAXPATH];
  612.  
  613.    switch (msg)
  614.    {
  615.    case WM_INITDLG:
  616.       SetSysMenu(hwnd);                     /* system menu for this dialog  */
  617.       strcpy (szOldDir, szCurrentDir);          /* save directory in case   */
  618.                                                 /* new directory is invalid */
  619.       WinSendDlgItemMsg (hwnd, IDD_EDIT, EM_SETTEXTLIMIT,
  620.                          MPFROM2SHORT (256, 0), (MPARAM)NULL);
  621.       WinSetDlgItemText (hwnd, IDD_EDIT, szCurrentDir);
  622.       WinSetFocus (HWND_DESKTOP, WinWindowFromID (hwnd, IDD_EDIT));
  623.       return ((MRESULT) TRUE);
  624.  
  625.    case WM_COMMAND:
  626.       switch (SHORT1FROMMP(mp1))
  627.       {
  628.       case DID_OK:
  629.           /*
  630.            * Get and validate the user input directory.
  631.            */
  632.          WinQueryWindowText (WinWindowFromID (hwnd, IDD_EDIT),
  633.                             sizeof (szCurrentDir), szCurrentDir);
  634.  
  635.          if (!ChangeDir(szCurrentDir))
  636.          {
  637.           /*
  638.            * New dir is invalid.
  639.            * Notify user and restore old directory.
  640.            */
  641.             MessageBox(HWND_DESKTOP,
  642.                        IDMSG_BADDIRECTORY,
  643.                        MB_OK | MB_ERROR,
  644.                        TRUE);
  645.             strcpy (szCurrentDir, szOldDir);
  646.          }
  647.  
  648.          WinDismissDlg (hwnd, TRUE);
  649.          return ((MRESULT) TRUE);
  650.  
  651.       case DID_CANCEL:
  652.          WinDismissDlg (hwnd, FALSE);
  653.          return MPFROMSHORT(FALSE);
  654.       }
  655.       break;
  656.    }
  657.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  658. } /*  End of OpenDlgProc  */
  659.  
  660. /**************************************************************************
  661.  *
  662.  *  Name       : ChangeDir(psz)
  663.  *
  664.  *  Description: Changes the current directory to the path specified
  665.  *
  666.  *  Concepts   : path
  667.  *
  668.  *  API's      : DosSetCurrentDir
  669.  *               WinLoadString
  670.  *               WinSetWindowText
  671.  *
  672.  *  Parameters :  pszSubdirectory = subdirectory path
  673.  *
  674.  *  Return     :  TRUE  - the directory and the titlebar have been
  675.  *                changed
  676.  *                FALSE - the directory and titlebar have not been
  677.  *                changed
  678.  *
  679.  *************************************************************************/
  680. BOOL ChangeDir (PSZ pszDirectory)
  681. {
  682.    CHAR  szTitle [CCHMAXPATH + 45];
  683.  
  684.   /*
  685.    * Use DosSetCurrentDir function to determine if input path is valid.
  686.    */
  687.  
  688.    if (!DosSetCurrentDir(pszDirectory))
  689.    {
  690.                      /* load application name from resource file */
  691.       if(!WinLoadString(hab, 0, IDS_APPNAME, CCHMAXPATH, szTitle))
  692.          return FALSE;
  693.       strcat (szTitle, pszDirectory);
  694.       WinSetWindowText (ParentOf (hwndClient), szTitle);
  695.       return TRUE;
  696.    }
  697.    return (FALSE);
  698. }  /*  End of ChangeDir  */
  699.  
  700. /**************************************************************************
  701.  *
  702.  *  Name       : PopulateList(hwndContainer, pszDir)
  703.  *
  704.  *  Description: Add all files in the directory to the list, except
  705.  *               for the current and parent subdirectory entries
  706.  *
  707.  *  Concepts   : directory, list box
  708.  *
  709.  *  API's      : WinEnableWindowUpdate
  710.  *               WinInsertLboxItem
  711.  *               WinShowWindow
  712.  *
  713.  *  Parameters :  hwndContainer = handle of the listbox
  714.  *                pszDir        = directory name string
  715.  *
  716.  *  Return     :  TRUE  - the list has been populated
  717.  *                FALSE - the list was not populated, because the
  718.  *                        directory string was empty
  719.  *
  720.  *************************************************************************/
  721. BOOL PopulateList (HWND hwndContainer, PSZ pszDir)
  722. {
  723.    char            szFilename[CCHMAXPATH];
  724.    PPUBFILEFINDBUF pffbFile;
  725.  
  726.    if (!pszDir || !*pszDir)
  727.    {
  728.       return (FALSE);
  729.    }
  730.  
  731.   /*
  732.    * Create the directory portion of the filename by concatenating a '\'
  733.    * to the input directory, if there is not already a '\' present
  734.    */
  735.    strcpy (szFilename, pszDir);
  736.    RemoveFinalBackslash (szFilename);
  737.  
  738.   /*
  739.    * Search for all files, eliminating:
  740.    * '.'  - current directory
  741.    * '..' - parent  directory
  742.    * and changing directories so that a '\' appears at the front to
  743.    * provide a visual queue to the user and ease forward navigation.
  744.    */
  745.  
  746.    strcat (szFilename, "\\*.*");               /* find all files            */
  747.  
  748.    WinEnableWindowUpdate(hwndContainer, FALSE);  /* disallow painting in   */
  749.                                                  /* the list while it's    */
  750.                                                  /* being populated        */
  751.    pffbFile = FindFileFirst (szFilename,
  752.                              FILE_NORMAL | FILE_SYSTEM | FILE_DIRECTORY);
  753.  
  754.    while (pffbFile != NULL)
  755.    {
  756.       if(strcmp(pffbFile->achName, "\\.") && strcmp(pffbFile->achName, "\\.."))
  757.       /*
  758.        * Anything related to insertion of an item goes here.
  759.        */
  760.          WinInsertLboxItem(hwndContainer, LIT_SORTASCENDING, pffbFile->achName);
  761.  
  762.       pffbFile = FindFileNext (pffbFile);
  763.    }
  764.  
  765.    WinScrollLboxItemToTop (hwndContainer, 0);
  766.    WinShowWindow (hwndContainer, TRUE);       /* allow painting again        */
  767.  
  768.    return TRUE;
  769. } /* End of PopulateList  */
  770.  
  771.  
  772. /**************************************************************************
  773.  *
  774.  *  Name       : ListSubclassProc(hwnd, msg, mp1, mp2)
  775.  *
  776.  *  Description: Intercepts certain messages:
  777.  *
  778.  *       WM_BUTTON2DOWN - sends WM_CONTROL (LN_INITDRAG) to owning window
  779.  *
  780.  *       mp2 in the following messages points to a DRAGINFO structure:
  781.  *
  782.  *       DM_DRAGOVER - sends WM_CONTROL (LN_DRAGOVER)  to owning window
  783.  *       DM_DRAGLEAVE- sends WM_CONTROL (LN_DRAGLEAVE) to owning window
  784.  *       DM_DROP     - sends WM_CONTROL (LN_DROP)      to owning window
  785.  *       DM_DROPHELP - sends WM_CONTROL (LN_DROPHELP)  to owning window
  786.  *
  787.  *  Concepts   : subclassing
  788.  *
  789.  *  API's      : WinSetPointer
  790.  *
  791.  *  Parameters :  hwnd = window handle
  792.  *                msg  = message code
  793.  *                mp1  = first message parameter
  794.  *                mp2  = second message parameter
  795.  *
  796.  *  Return     :  values are determined by each message
  797.  *
  798.  *************************************************************************/
  799. MRESULT EXPENTRY ListSubclassProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  800. {
  801.    switch (msg)
  802.    {
  803.    case WM_MOUSEMOVE:
  804.       if (CheckBusy() || cDragFiles)
  805.       {
  806.          WinSetPointer(HWND_DESKTOP, hptrBusy);
  807.          return ((MRESULT) TRUE);
  808.       }
  809.       break;
  810.  
  811.    case WM_BUTTON2DOWN:
  812.       return (SendOwner(hwnd, LN_INITDRAG, mp1, LIST_ID));
  813.  
  814.    case DM_DRAGOVER:
  815.       return (SendOwner (hwnd, LN_DRAGOVER, mp1, LIST_ID));
  816.  
  817.    case DM_DRAGLEAVE:
  818.       return (SendOwner (hwnd, LN_DRAGLEAVE, mp1, LIST_ID));
  819.  
  820.    case DM_DROPHELP:
  821.       return (SendOwner (hwnd, LN_DROPHELP, mp1, LIST_ID));
  822.  
  823.    case DM_DROP:
  824.       return (SendOwner (hwnd, LN_DROP, mp1, LIST_ID));
  825.    }
  826.    return (pfnwpList (hwnd, msg, mp1, mp2));
  827. } /*  End of ListSubclassProc  */
  828.  
  829. /**************************************************************************
  830.  *
  831.  *  Name       : Message(pszMsg)
  832.  *
  833.  *  Description: Displays the given message text inside a box
  834.  *
  835.  *  Concepts   : message box
  836.  *
  837.  *  API's      : WinMessageBox
  838.  *
  839.  *  Parameters :  pszMsg = the message to be displayed
  840.  *
  841.  *  Return     :  [none]
  842.  *
  843.  *************************************************************************/
  844. VOID Message (PSZ pszMsg)
  845. {
  846.    WinMessageBox (HWND_DESKTOP, hwndClient, pszMsg, szClientClass, 0,
  847.                  MB_MOVEABLE | MB_ICONEXCLAMATION);
  848. } /*  End of Message  */
  849.  
  850. /**************************************************************************
  851.  *
  852.  *  Name       : MessageBox(hwndOwner, nIdMsg, fsStyle, fBeep)
  853.  *
  854.  *  Description: Displays the message box with the message
  855.  *               given in idMsg retrieved from the message table
  856.  *               and using the style flags in fsStyle
  857.  *
  858.  *               Called whenever a MessageBox is to be displayed
  859.  *
  860.  *  Concepts   : message box
  861.  *               - Message string is loaded from the process'
  862.  *                 message table
  863.  *               - Alarm beep is sounded if desired
  864.  *               - Message box with the message is displayed
  865.  *               - WinMessageBox return value is returned
  866.  *
  867.  *  API's      : WinMessageBox
  868.  *
  869.  *  Parameters :  hwndOwner = handle of the owning window
  870.  *                nIdMsg    = id of the message in the message table
  871.  *                fsStyle   = word of style flags
  872.  *                fBeep     = whether the message should also alarm
  873.  *
  874.  *  Return     :  the value returned from WinMwessageBox
  875.  *
  876.  *************************************************************************/
  877. SHORT MessageBox(HWND hwndOwner,   /* handle of the message box's owner    */
  878.                  SHORT idMsg,      /* id of the message in the message table */
  879.                  SHORT fsStyle,    /* style of the message box              */
  880.                  BOOL fBeep)       /* if TRUE, beep before msg is displayed */
  881. {
  882.    CHAR szText[MESSAGELEN];
  883.  
  884.    if(!WinLoadMessage(hab, (HMODULE)0L, idMsg, MESSAGELEN, (PSZ)szText))
  885.    {
  886.        WinAlarm(HWND_DESKTOP, WA_ERROR);
  887.        return MBID_ERROR;
  888.    }
  889.  
  890.    if(fBeep)
  891.        WinAlarm(HWND_DESKTOP, WA_ERROR);
  892.  
  893.    return(WinMessageBox(HWND_DESKTOP, hwndOwner, szText, (PSZ)NULL,
  894.                         MSGBOXID, fsStyle));
  895. }   /* End of MessageBox  */
  896. /***************************  End of dragdrop.c  *************************/
  897.