home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / gdi / showdib / dlgopen.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  23KB  |  516 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. /*******************************************************************************
  13.  *                                                                             *
  14.  *  MODULE      : DLGOPEN.C                                                    *
  15.  *                                                                             *
  16.  *  DESCRIPTION : Routines to display a standard File/Open and File/Save       *
  17.  *                dialog boxes.                                                *
  18.  *                                                                             *
  19.  *  FUNCTIONS   : DlgOpenFile() - Displays a dialog box for opening or saving a*
  20.  *                                file.                                        *
  21.  *                                                                             *
  22.  *                DlgfnOpen()   - Dialog function for the above dialog.        *
  23.  *                                                                             *
  24.  *                AddExt()      - Adds an extension to a filename if not       *
  25.  *                                already present.                             *
  26.  *                                                                             *
  27.  *                FSearchSpec() - Checks if given string contains a wildcard   *
  28.  *                                character.                                   *
  29.  *                                                                             *
  30.  *                FillListBox() - Fills listbox with files that match specs.   *
  31.  *                                                                             *
  32.  *                DlgCheckOkEnable() - Enables <OK> button iff there's text in *
  33.  *                                     the edit control.                       *
  34.  *                                                                             *
  35.  *                NOTE : These routines require that the app. be running       *
  36.  *                       SS = DS since they use near pointers into the stack.  *
  37.  *                                                                             *
  38.  *******************************************************************************/
  39. #include <windows.h>
  40. #include <string.h>
  41. #include "showdib.h"
  42.  
  43. static PSTR         szExt;
  44. static PSTR         szFileName;
  45. static PSTR         szTitle;
  46. static DWORD        flags;
  47. static WORD         fOpt;
  48.  
  49. /* Forward declarations of helper functions */
  50.  
  51. static VOID  NEAR DlgCheckOkEnable(HWND hwnd, INT idEdit, UINT message);
  52. static CHAR *NEAR FillListBox (HWND,CHAR*, UINT);
  53. static BOOL  NEAR FSearchSpec (CHAR*);
  54. static VOID  NEAR AddExt (CHAR*,CHAR*);
  55.  
  56. #define DLGOPEN_UNUSED   0
  57.  
  58. /* Mask to eliminate bogus style and bitcount combinations ...
  59.  * RLE formats, if chosen should be matched with the bitcounts:
  60.  *   RLE4 scheme should be used only for 4 bitcount DIBs.
  61.  *   RLE8   "      "     "   "   "    "  8   "       "
  62.  *
  63.  * BITCOUNTMASK is indexed by DLGOPEN_RLE4 >> 4, DLGOPEN_RLE8 >> 4
  64.  * and DLGOPEN_RLE8 >> 4
  65.  */
  66.  
  67. static WORD BITCOUNTMASK[] = { DLGOPEN_UNUSED,
  68.                                DLGOPEN_1BPP | DLGOPEN_8BPP | DLGOPEN_24BPP,
  69.                                DLGOPEN_1BPP | DLGOPEN_4BPP | DLGOPEN_24BPP,
  70.                                DLGOPEN_UNUSED,
  71.                                0 };
  72.  
  73.  
  74. /*******************************************************************************
  75.  *                                                                             *
  76.  *  FUNCTION   :DlgOpen(LPSTR szFile)                                          *
  77.  *                                                                             *
  78.  *  PURPOSE    :Display dialog box for opening files. Allow user to interact   *
  79.  *              with dialogbox, change directories as necessary, and try to    *
  80.  *              open file if user selects one. Automatically append            *
  81.  *              extension to filename if necessary.                            *
  82.  *              This routine correctly parses filenames containing KANJI       *
  83.  *              characters.                                                    *
  84.  *                                                                             *
  85.  *  RETURNS    :  - Handle to the opened file if legal filename.               *
  86.  *                - 0 if user presses <cancel>                                 *
  87.  *                - 1 if filename entered is illegal                           *
  88.  *                                                                             *
  89.  *******************************************************************************/
  90. HFILE APIENTRY DlgOpenFile (
  91.     HWND          hwndParent,
  92.     CHAR          *szTitleIn,
  93.     DWORD         flagsIn,
  94.     CHAR          *szExtIn,
  95.     CHAR          *szFileNameIn,
  96.     WORD          *pfOpt)
  97. {
  98.     INT      fh;
  99.     FARPROC  lpProc;
  100.     CHAR     achFile[128];
  101.     CHAR     achExt[128];
  102.     HANDLE   hInstance;
  103.     WORD     w;
  104.  
  105.     if (pfOpt == NULL)
  106.         pfOpt = &w;
  107.  
  108.     flags    = flagsIn;
  109.     fOpt     = *pfOpt;
  110.  
  111.     lstrcpy (szFileName = achFile, szFileNameIn);
  112.     lstrcpy (szExt = achExt, szExtIn);
  113.     szTitle = szTitleIn;
  114.  
  115.     hInstance = (HANDLE)GetWindowLong (hwndParent, GWL_HINSTANCE);
  116.  
  117.     /* Show the dialog box */
  118.     lpProc = MakeProcInstance ((FARPROC)DlgfnOpen, hInstance);
  119.     fh = DialogBox (hInstance, "DlgOpenBox", hwndParent, (DLGPROC)lpProc);
  120.     FreeProcInstance (lpProc);
  121.  
  122.     if (fh != 0){
  123.         lstrcpy (szFileNameIn, szFileName);
  124.         *pfOpt = fOpt;
  125.     }
  126.     return fh;
  127. }
  128.  
  129. /****************************************************************************
  130.  *                                                                          *
  131.  *  FUNCTION   :DlgfnOpen (hwnd, msg, wParam, lParam)                       *
  132.  *                                                                          *
  133.  *  PURPOSE    :Dialog function for File/Open dialog.                       *
  134.  *                                                                          *
  135.  ****************************************************************************/
  136. LONG APIENTRY DlgfnOpen (
  137.     HWND hwnd,
  138.     UINT msg,
  139.     UINT wParam,
  140.     LONG lParam)
  141. {
  142.     INT      result = -1;    /* Assume illegal filename initially */
  143.     int      w;
  144.     LPSTR    lpsz;
  145.     WORD     f;
  146.     OFSTRUCT of;
  147.     RECT     rc, rcCtl;
  148.     HWND     hwndT;
  149.     BOOL     fEnable;
  150.     CHAR     lpBuffer[128];
  151.  
  152.     switch (msg) {
  153.         case WM_INITDIALOG:
  154.             if (szTitle && *szTitle)
  155.                 SetWindowText (hwnd, szTitle);
  156.  
  157.             /* Set text on <OK> button according to mode (File/Open or File/Save) */
  158.             if (flags & OF_SAVE) {
  159.                 LoadString(hInst, IDS_SAVESTR, lpBuffer, sizeof(lpBuffer));
  160.                 SetDlgItemText(hwnd, IDOK, lpBuffer);
  161.             }
  162.             if (flags & OF_OPEN) {
  163.                 LoadString(hInst, IDS_OPENSTR, lpBuffer, sizeof(lpBuffer));
  164.                 SetDlgItemText(hwnd, IDOK, lpBuffer);
  165.             }
  166.             if ((flags & OF_NOOPTIONS) &&
  167.                 (hwndT = GetDlgItem(hwnd,DLGOPEN_FOLDOUT)))
  168.                 EnableWindow (hwndT,FALSE);
  169.  
  170.             if (hwndT = GetDlgItem (hwnd, DLGOPEN_SMALL)) {
  171.                 GetWindowRect (hwnd,&rc);
  172.                 GetWindowRect (GetDlgItem(hwnd,DLGOPEN_SMALL),&rcCtl);
  173.  
  174.                 SetWindowPos (hwnd,
  175.                               NULL,
  176.                               0,
  177.                               0,
  178.                               rcCtl.left - rc.left,
  179.                               rc.bottom - rc.top,
  180.                               SWP_NOZORDER | SWP_NOMOVE);
  181.             }
  182.             /* fill list box with filenames that match specifications, and
  183.              * fill static field with path name.
  184.              */
  185.             FillListBox(hwnd,szExt, WM_INITDIALOG);
  186.  
  187.             /* If in Save mode, set the edit control with default (current)
  188.              * file name,and select the corresponding entry in the listbox.
  189.              */
  190.             if ((flags & OF_SAVE) && *szFileName) {
  191.                         SetDlgItemText (hwnd, DLGOPEN_EDIT, szFileName);
  192.                         SendDlgItemMessage (hwnd,
  193.                                     DLGOPEN_FILE_LISTBOX,
  194.                                     LB_SELECTSTRING,
  195.                                     0,
  196.                                     (LONG)(LPSTR)szFileName);
  197.             }
  198.             else {
  199.                 /*  Set the edit field with the default extensions... */
  200.                 if (flags & OF_NOSHOWSPEC)
  201.                     SetDlgItemText (hwnd, DLGOPEN_EDIT, "");
  202.                 else
  203.                     SetDlgItemText (hwnd, DLGOPEN_EDIT, szExt);
  204.             }
  205.             /*  ...and select all text in the edit field */
  206.                 /* JAP added HWND cast*/
  207.             SendMessage((HWND)GetDlgItem(hwnd, DLGOPEN_EDIT), EM_SETSEL, GET_EM_SETSEL_MPS(0, 0x7fff));
  208.  
  209.             /*  check all options that are set */
  210.             for ( f = DLGOPEN_1BPP; f; f<<=1)
  211.                 CheckDlgButton(hwnd, (INT)FID(f), (WORD) (fOpt & f));
  212.  
  213.             break;
  214.  
  215.         case WM_COMMAND:
  216.         switch (LOWORD(wParam)) {
  217.                 case IDOK:
  218.                     if (IsWindowEnabled (GetDlgItem(hwnd, IDOK))) {
  219.                         /* Get contents of edit field and add search spec. if it
  220.                          * does not contain one.
  221.                          */
  222.                         GetDlgItemText (hwnd, DLGOPEN_EDIT, (LPSTR)szFileName, 128);
  223.  
  224.                         lpsz = CharPrev(szFileName, szFileName + lstrlen(szFileName));
  225.                         switch (*lpsz) {
  226.                             case '\\':
  227.                             case '/':
  228.                                 *lpsz = 0;
  229.                             break;
  230.                         }
  231.                         if (SetCurrentDirectory ((LPSTR)szFileName))
  232.                             lstrcpy (szFileName,szExt);
  233.  
  234.                         /*  Try to open path.  If successful, fill listbox with
  235.                          *  contents of new directory.  Otherwise, open datafile.
  236.                          */
  237.                         if (FSearchSpec(szFileName)) {
  238.                             lstrcpy (szExt, FillListBox (hwnd, szFileName, WM_COMMAND));
  239.                             if (flags & OF_NOSHOWSPEC) {
  240.                                 SetDlgItemText (hwnd, DLGOPEN_EDIT, "");
  241.                             } else {
  242.                                 SetDlgItemText (hwnd, DLGOPEN_EDIT, szExt);
  243.                             }
  244.                             break;
  245.                         }
  246.  
  247.                         /*  Make filename upper case and if it's a legal DOS
  248.                          *  name, try to open the file.
  249.                          */
  250.                         CharUpper(szFileName);
  251.                         AddExt(szFileName,szExt);
  252.                         result = (INT)OpenFile(szFileName, &of, (WORD)flags);
  253.  
  254.                         if (result != -1) {
  255.                             lstrcpy(szFileName,of.szPathName);
  256.                         }
  257.                         else if (flags & OF_MUSTEXIST) {
  258.                             MessageBeep(0);
  259.                             return 0L;
  260.                         }
  261.  
  262.                         /*  Get the state of all checked options */
  263.                         for (f = DLGOPEN_1BPP; f; f <<= 1){
  264.                             if (IsDlgButtonChecked (hwnd, FID (f)))
  265.                                 fOpt |= f;
  266.                             else
  267.                                 fOpt &= ~f;
  268.                         }
  269.  
  270.                         EndDialog (hwnd, result);
  271.                     }
  272.                     break;
  273.  
  274.                 case DLGOPEN_OPTION + DLGOPEN_RLE4:
  275.                 case DLGOPEN_OPTION + DLGOPEN_RLE8:
  276.                 case DLGOPEN_OPTION + DLGOPEN_RGB:
  277.                     /* Mask out incompatible bitcount options and gray the
  278.                      * appropriate radiobuttons.
  279.                      */
  280.                     for (f = DLGOPEN_1BPP; f <= DLGOPEN_24BPP; f <<= 1){
  281.                         fEnable = !(f & BITCOUNTMASK [IDF(w) >> 4 ]);
  282.                         EnableWindow (GetDlgItem (hwnd, FID(f)), fEnable);
  283.  
  284.                         /* If the radiobutton is being grayed, uncheck it and
  285.                          * and check an "allowed" option so the bitcount group
  286.                          * is still accessible via the keyboard
  287.                          */
  288.                         if (!fEnable && IsDlgButtonChecked (hwnd, FID (f))){
  289.                             CheckDlgButton(hwnd, FID(f), FALSE);
  290.                             CheckDlgButton(hwnd, FID(IDF(w) >> 3), TRUE);
  291.                         }
  292.                     }
  293.                     break;
  294.  
  295.                 case IDCANCEL:
  296.                     /* User pressed cancel.  Just take down dialog box. */
  297.                     EndDialog (hwnd, 0);
  298.                     break;
  299.  
  300.                 /*  User single clicked or doubled clicked in listbox -
  301.                  *  Single click means fill edit box with selection.
  302.                  *  Double click means go ahead and open the selection.
  303.                  */
  304.                 case DLGOPEN_FILE_LISTBOX:
  305.                 case DLGOPEN_DIR_LISTBOX:
  306.                     switch (GET_WM_COMMAND_CMD(wParam, lParam)) {
  307.                         /* Single click case */
  308.                         case LBN_SELCHANGE:
  309.                             /* Get selection, which may be either a prefix to a
  310.                              * new search path or a filename. DlgDirSelectEx parses
  311.                              * selection, and appends a backslash if selection
  312.                              * is a prefix
  313.                              */
  314.                             DlgDirSelectEx(hwnd, szFileName, 128, LOWORD(wParam));
  315.                             lpsz = CharPrev(szFileName, szFileName + lstrlen(szFileName));
  316.                             switch (*lpsz) {
  317.                                 case ':':
  318.                                     lstrcat (szFileName,".");
  319.                                     break;
  320.                                 case '\\':
  321.                                 case '/':
  322.                                     *lpsz = 0;
  323.                                     break;
  324.                             }
  325.                             SetDlgItemText(hwnd, DLGOPEN_EDIT, szFileName);
  326.                             break;
  327.                         /* Double click case - first click has already been
  328.                          * processed as single click
  329.                          */
  330.                         case LBN_DBLCLK:
  331.                             PostMessage (hwnd,WM_COMMAND,IDOK,0L);
  332.                             break;
  333.                     }
  334.                     break;
  335.  
  336.                 case DLGOPEN_EDIT:
  337.                     DlgCheckOkEnable(hwnd, DLGOPEN_EDIT, HIWORD(lParam));
  338.                     break;
  339.  
  340.                 case DLGOPEN_FOLDOUT:
  341.                     GetWindowRect(hwnd,&rc);
  342.                     GetWindowRect(GetDlgItem(hwnd,DLGOPEN_BIG),&rcCtl);
  343.  
  344.                     if ((rcCtl.left <= rc.right) && (rcCtl.top <= rc.bottom))
  345.                          GetWindowRect (GetDlgItem (hwnd, DLGOPEN_SMALL), &rcCtl);
  346.  
  347.                     SetWindowPos (hwnd,
  348.                                   NULL,
  349.                                   0,
  350.                                   0,
  351.                                   rcCtl.left - rc.left,
  352.                                   rc.bottom - rc.top,
  353.                                   SWP_NOZORDER | SWP_NOMOVE);
  354.                     break;
  355.             }
  356.         default:
  357.             return FALSE;
  358.     }
  359.     return TRUE;
  360. }
  361.  
  362. /****************************************************************************
  363.  *                                                                          *
  364.  *  FUNCTION   : static void NEAR DlgCheckOkEnable(hwnd, idEdit, message)   *
  365.  *                                                                          *
  366.  *  PURPOSE    : Enables the <OK> button in a dialog box iff the edit item  *
  367.  *               contains text.                                             *
  368.  *                                                                          *
  369.  ****************************************************************************/
  370. static VOID NEAR DlgCheckOkEnable(
  371.     HWND        hwnd,
  372.     INT idEdit,
  373.     UINT message)
  374. {
  375.     if (message == EN_CHANGE) {
  376.         EnableWindow ( GetDlgItem (hwnd, IDOK),
  377.                        (BOOL)SendMessage (GetDlgItem (hwnd, idEdit),
  378.                                           WM_GETTEXTLENGTH,
  379.                                           0, 0L));
  380.     }
  381. }
  382.  
  383. /****************************************************************************
  384.  *                                                                          *
  385.  *  FUNCTION   : AddExt (pch, ext)                                          *
  386.  *                                                                          *
  387.  *  PURPOSE    : Add an extension to a filename if none is already specified*
  388.  *                                                                          *
  389.  ****************************************************************************/
  390. static VOID NEAR AddExt (
  391.     CHAR *pch,    /* File name    */
  392.     CHAR *ext)    /* Extension to add */
  393. {
  394.     CHAR acExt[20];
  395.     CHAR *pext = acExt;
  396.  
  397.     while (*ext && *ext != '.') {
  398.         ext = CharNext(ext);
  399.     }
  400.     while (*ext && *ext != ';') {
  401.         if (IsDBCSLeadByte(*ext)) {
  402.             *pext++ = *ext++;
  403.         }
  404.         *pext++ = *ext++;
  405.     }
  406.     *pext = 0;
  407.     pext = acExt;
  408.  
  409.     while (*pch == '.') {
  410.         pch++;
  411.         if ((*pch == '.') && pch[1] == '\\')
  412.             pch += 2;                       /* ..\ */
  413.         if (*pch == '\\')
  414.             pch++;                         /* .\ */
  415.     }
  416.     while (*pch != '\0') {
  417.     if (*pch == '.')
  418.         return;
  419.     pch = CharNext(pch);
  420.     }
  421.  
  422.     // *pch++ = '.';
  423.     do
  424.         *pch++ = *pext;
  425.     while (*pext++ != '\0');
  426. }
  427. /****************************************************************************
  428.  *                                                                          *
  429.  *  FUNCTION   : FSearchSpec (sz)                                           *
  430.  *                                                                          *
  431.  *  PURPOSE    : Checks to see if NULL-terminated strings contains a "*" or *
  432.  *               a "?".                                                     *
  433.  *                                                                          *
  434.  *  RETURNS    : TRUE  - if the above characters are found in the string    *
  435.  *               FALSE - otherwise.                                         *
  436.  *                                                                          *
  437.  ****************************************************************************/
  438. static BOOL NEAR FSearchSpec(CHAR       *sz)
  439. {
  440.     for (; *sz ;sz = CharNext(sz)) {
  441.         if (*sz == '*' || *sz == '?')
  442.             return TRUE;
  443.     }
  444.     return FALSE;
  445. }
  446.  
  447. /****************************************************************************
  448.  *                                                                          *
  449.  *  FUNCTION   : static char * NEAR FillListBox (hDlg,pFile, cmd)                   *
  450.  *                                                                          *
  451.  *  PURPOSE    : Fill list box with filenames that match specifications, and*
  452.  *               fills the static field with the path name.                 *
  453.  *                                                                          *
  454.  *  RETURNS    : A pointer to the pathname.                                                           *
  455.  *                                                                          *
  456.  ****************************************************************************/
  457. static CHAR * NEAR FillListBox (
  458.     HWND  hDlg,
  459.     CHAR  *pFile,  /* [path]{list of file wild cards, separated by ';'} */
  460.     UINT cmd)    /* if initdialog, or WM_COMMAND*/
  461. {
  462.     CHAR  ach[128];
  463.     CHAR  *pch;
  464.     CHAR  *pDir;   /* Directory name or path */
  465.     CHAR  pCurDir[256];
  466.  
  467.     pch  = pFile;
  468.     pDir = ach;
  469.     if(cmd == WM_INITDIALOG){
  470.     while (*pch && *pch != ';')
  471.         pch = CharNext(pch);
  472.     while ((pch > pFile) && (*pch != '/') && (*pch != '\\'))
  473.         pch = CharPrev(pFile, pch);
  474.     if (pch > pFile) {
  475.        *pch = 0;
  476.        lstrcpy (pDir, pFile);
  477.        pFile = pch + 1;
  478.     }
  479.     else {
  480.        lstrcpy (pDir,".");
  481.     }
  482.     }
  483.     else{
  484.         /* since SetCurrentDirectory was called already, I'll use GetCurrentDirectory*/
  485.         /* to get pDir*/
  486.         GetCurrentDirectory(256, pCurDir);
  487.         strcpy(pDir, pCurDir);
  488.     }
  489.     DlgDirList (hDlg, pDir, (INT)DLGOPEN_DIR_LISTBOX, (INT)DLGOPEN_PATH,(WORD)ATTRDIRLIST);
  490.     SendDlgItemMessage (hDlg, DLGOPEN_FILE_LISTBOX, LB_RESETCONTENT, 0, 0L);
  491.     SendDlgItemMessage (hDlg, DLGOPEN_FILE_LISTBOX, WM_SETREDRAW, FALSE, 0L);
  492.     pDir = pFile;            /* save pFile to return */
  493.     while (*pFile) {
  494.         pch = ach;
  495.         while (*pFile==' ')
  496.             pFile++;
  497.         while (*pFile && *pFile != ';') {
  498.             if (IsDBCSLeadByte(*pFile)) {
  499.                 *pch++ = *pFile++;
  500.             }
  501.             *pch++ = *pFile++;
  502.         }
  503.         *pch = 0;
  504.         if (*pFile)
  505.             pFile++;
  506.         SendDlgItemMessage (hDlg,
  507.                             DLGOPEN_FILE_LISTBOX,
  508.                             LB_DIR,ATTRFILELIST,
  509.                             (LONG)(LPSTR)ach);
  510.     }
  511.     SendDlgItemMessage (hDlg, DLGOPEN_FILE_LISTBOX, WM_SETREDRAW, TRUE, 0L);
  512.     InvalidateRect (GetDlgItem (hDlg, DLGOPEN_FILE_LISTBOX), NULL, TRUE);
  513.  
  514.     return pDir;
  515. }
  516.