home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / cmddlg / cdtest / open.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-17  |  33.1 KB  |  1,260 lines

  1. /************************************************************************
  2.  
  3.   File: open.c
  4.  
  5.   Purpose:
  6.  
  7.     This file contains the routines to control the CDTEST.EXE "Open" dialog
  8.     box.  The "Open" dialog box allows the user to enter values into an
  9.     OPENFILENAME structure and then create GetOpenFileName() dialog boxes
  10.     on the fly.
  11.  
  12.   Functions:
  13.  
  14.     DoOpenDialog()                   -- starts off the main dialog for "open"
  15.  
  16.     OpenFunc()                       -- Callback function for main dialog
  17.  
  18.     InitOpenStruct()                 -- Fills initial OPENFILENAME structure.
  19.  
  20.     FillOpenDlg()                    -- Fills the dialog with the values from
  21.                                         the OPENFILENAME structure.
  22.  
  23.     GetOpenDlg()                     -- Retrieves the users entries from the
  24.                                         main dialog and puts them in the
  25.                                         OPENFILENAME structure.
  26.  
  27.     InitFilterString()               -- Creates filter string
  28.  
  29.     InitCustFiltString()             -- Creates custom filter string
  30.  
  31.     InterpretCustomFilterString()    -- Parses custom filter string returned
  32.                                         from GetOpenFileName()
  33.  
  34.     GetCorrectResourceHandle()       -- Loads custom templates from file
  35.                                         as resource handles
  36.  
  37.     OpenSaveHookProc()               -- The hook function that will be
  38.                                         called if GetOpen/Save is called
  39.                                         with the OFN_ENABLEHOOK flag set.
  40.  
  41.     MultiThreadOpenSave()            -- Creates two Open/Save dialogs that
  42.                                         the user can simultaneously access
  43.  
  44.     OpenSaveThread1Proc()            -- The starting address of thread 1
  45.  
  46.     OpenSaveThread2Proc()            -- The starting address of thread 2
  47.  
  48.     DoOpenSaveStuff()                -- Does the actuall calling of
  49.                                         GetOpen/SaveFileName()
  50.  
  51.     OpenMultiThreadEnableButtons()   -- Enables and disables buttons in
  52.                                         main dialog.  Needed when multi-
  53.                                         threading.
  54.  
  55. ************************************************************************/
  56.  
  57. #include <windows.h>
  58. #include <commdlg.h>
  59. #include <stdlib.h>
  60. #include <winnls.h>
  61. #include "cdtest.h"
  62. #include "open.h"
  63. #include "save.h"
  64. #include "dlgs.h"     //include file that contains all #defines for the
  65.                       //commdlg dialog templates.
  66.  
  67.  
  68. /* All functions defined in this file + 1 external function
  69.    and one external variable */
  70.  
  71. extern UINT uMode ;                               //see cdtest.c
  72. extern LONG MyAtol(LPTSTR, BOOL, LPBOOL) ;
  73. void InterpretCustomFilterString(void) ;
  74. HANDLE GetCorrectResourceHandle(void) ;
  75. void DoOpenSaveStuff(LPOPENFILENAME) ;
  76. UINT APIENTRY OpenSaveHookProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam) ;
  77. DWORD OpenSaveThread1Proc(LPDWORD) ;
  78. DWORD OpenSaveThread2Proc(LPDWORD) ;
  79. void MultiThreadOpenSave(void) ;
  80. void OpenMultiThreadEnableButtons(BOOL, HWND) ;
  81.  
  82.  
  83. /* All global variables defined in this file */
  84.  
  85. HWND hwndMainDialog ;   //global handle for open dialog.
  86.  
  87. HANDLE hRes ;           //handles to the resource and dialog for
  88. HANDLE hDialog ;        //ofn_enabletemplatehandle
  89.  
  90. HBRUSH hBrushDlg ;
  91. HBRUSH hBrushEdit ;     //brush handles for new colors done with hook proc
  92. HBRUSH hBrushButton ;
  93.  
  94. HANDLE hOpenSaveThread1, hOpenSaveThread2 ;   //variables for the
  95. DWORD dwThreadID1, dwThreadID2 ;              //multithreading part
  96. DWORD dwThreadParm1, dwThreadParm2 ;
  97. OPENFILENAME ofnThread1, ofnThread2 ;
  98. int nOpenDialogCount ;
  99.  
  100.  
  101.  
  102.  
  103.  
  104. /************************************************************************
  105.  
  106.   Function: DoOpenDialog(HWND)
  107.  
  108.   Purpose: To create the GetOpenFileName() and GetSaveFileName()
  109.            creation dialog.
  110.  
  111.   Returns: Nothing.
  112.  
  113.   Comments:
  114.  
  115.     GetOpenFileName() and GetSaveFileName() are similiar enough so that
  116.     the same dialog can be used to edit their creation structure elements,
  117.     so a global variable "bDoOpenDlg" keeps track of which one to create
  118.     when the user clicks the OK or Multithread buttons...
  119.  
  120. ************************************************************************/
  121.  
  122.  
  123. void DoOpenDialog(HWND hwnd)
  124. {
  125.  
  126.   bDoOpenDlg = TRUE ;
  127.  
  128.  
  129.   DialogBox(hInst, MAKEINTRESOURCE(ID_OPENDIALOG), hwnd, OpenFunc) ;
  130.  
  131. }
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138. /************************************************************************
  139.  
  140.  
  141.   Function: OpenFunc(HWND, UINT, UINT, LONG)
  142.  
  143.   Purpose:
  144.  
  145.     This is the callback function for the dialog box containing the
  146.     GetOpenFileName() and the GetSaveFileName() creation options.
  147.  
  148.     This function will handle the messages for this dialog and create
  149.     either a GetOpenFileName() dialog or a GetSaveFileName() dialog
  150.     depending on the state of the bDoOpenDlg variable.
  151.  
  152.   Returns: TRUE or FALSE depending on the situation.
  153.  
  154.   Comments:
  155.  
  156.  
  157. ************************************************************************/
  158.  
  159.  
  160. BOOL APIENTRY OpenFunc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  161. {
  162.   switch (msg)
  163.   {
  164.  
  165.     case WM_INITDIALOG:
  166.  
  167.       if (bDoOpenDlg)
  168.         SetWindowText(hwnd, TEXT("GetOpenFileName()")) ;
  169.       else
  170.         SetWindowText(hwnd, TEXT("GetSaveFileName()")) ;
  171.  
  172.  
  173.       /* initialize the OPENFILENAME structure members */
  174.  
  175.       InitOpenStruct(hwnd, &ofn) ;
  176.  
  177.  
  178.       /* Fill these values into the creation dialog */
  179.  
  180.       FillOpenDlg(hwnd, &ofn) ;
  181.  
  182.  
  183.       /* There are three separate OPENFILENAME structures.  One for
  184.          the main Open/Save dialog and one for each multithreaded dialog.
  185.          Set them equal to begin with */
  186.  
  187.       *(&ofnThread1) = *(&ofnThread2) = *(&ofn) ;
  188.  
  189.       hwndMainDialog = hwnd ;
  190.  
  191.       SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEO)) ;
  192.  
  193.       break ;
  194.  
  195.  
  196.  
  197.     case UMSG_DECREMENTDLGCOUNT:  //user defined message indicating
  198.                                   //the closure of a multithreaded dialog
  199.  
  200.       /* When we are multithreading, there is nothing to prevent the
  201.          user from interacting with the creation dialog once the first
  202.          GetOpen(Save) file name dialog has returned.  So, in order
  203.          to prevent the Multithread" button from being pressed again
  204.          before the previous two multithreaded dialogs have been canceled,
  205.          disable the controls until we get a message from each thread
  206.          that the dialog has ended */
  207.  
  208.  
  209.       nOpenDialogCount-- ;
  210.  
  211.       if (nOpenDialogCount == 0)
  212.         OpenMultiThreadEnableButtons(TRUE, hwnd) ;
  213.  
  214.       break ;
  215.  
  216.  
  217.     case WM_COMMAND:
  218.     {
  219.       switch (LOWORD(wParam))
  220.       {
  221.  
  222.         case IDOK:
  223.           GetOpenDlg(hwnd, &ofn) ;          //get the user's input
  224.           DoOpenSaveStuff(&ofn) ;           //do the dialog
  225.           break ;
  226.  
  227.  
  228.         case IDCANCEL:
  229.           EndDialog(hwnd, FALSE) ;
  230.           break ;
  231.  
  232.  
  233.         case ID_RESETOPEN:
  234.  
  235.           SendDlgItemMessage(hwnd, ID_FILTERO, CB_RESETCONTENT,
  236.             (WPARAM) 0, (LPARAM) 0) ;
  237.  
  238.           InitOpenStruct(hwnd, &ofn) ;
  239.  
  240.           FillOpenDlg(hwnd, &ofn) ;
  241.  
  242.           SendDlgItemMessage(hwnd, ID_NULLSTRUCTO, BM_SETCHECK, (WPARAM)0, (LPARAM)0) ;
  243.           SendDlgItemMessage(hwnd, ID_USEHINSTO, BM_SETCHECK, (WPARAM)0, (LPARAM)0) ;
  244.  
  245.           *(&ofnThread1) = *(&ofnThread2) = *(&ofn) ;
  246.  
  247.           SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEO)) ;
  248.  
  249.           break ;
  250.  
  251.  
  252.         case ID_ADD1O:
  253.  
  254.           GetDlgItemText(hwnd, ID_FILTERO, szTemp, 100) ;
  255.  
  256.           if (*szTemp)
  257.           {
  258.             SendDlgItemMessage(hwnd, ID_FILTERO, CB_ADDSTRING, (WPARAM) 0,
  259.                               (LPARAM) (LPTSTR) szTemp) ;
  260.             SetWindowText(GetDlgItem(hwnd, ID_FILTERO), TEXT("")) ;
  261.           }
  262.           break ;
  263.  
  264.  
  265.         case ID_ADD2O:
  266.  
  267.           GetDlgItemText(hwnd, ID_CUSTFILTO, szTemp, 100) ;
  268.  
  269.           if (*szTemp)
  270.           {
  271.             SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_ADDSTRING, (WPARAM) 0,
  272.                               (LPARAM) (LPTSTR) szTemp) ;
  273.             SetWindowText(GetDlgItem(hwnd, ID_CUSTFILTO), TEXT("")) ;
  274.           }
  275.           break ;
  276.  
  277.  
  278.         case ID_CLEAR1O:
  279.           SendDlgItemMessage(hwnd, ID_FILTERO, CB_RESETCONTENT,
  280.                              (WPARAM) 0, (LPARAM) 0) ;
  281.           break ;
  282.  
  283.         case ID_CLEAR2O:
  284.           SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_RESETCONTENT,
  285.                              (WPARAM) 0, (LPARAM) 0) ;
  286.           break ;
  287.  
  288.         case ID_MULTIOPEN:
  289.  
  290.         /* First, disable the OK, Cancel, and MultiThread buttons */
  291.  
  292.           OpenMultiThreadEnableButtons(FALSE, hwnd) ;
  293.  
  294.  
  295.         /* Then multithread the dialogs */
  296.  
  297.           nOpenDialogCount = 2 ;
  298.  
  299.           MultiThreadOpenSave() ;
  300.  
  301.           break ;
  302.  
  303.  
  304.         default:   //end WM_COMMAND case
  305.           break ;
  306.       }
  307.     }
  308.  
  309.     default:
  310.  
  311.       /* If the help button is pressed in the GetOpen/SaveFileName()
  312.          dialogs, it will send a message Registered with RegisterWindowMessage()
  313.          to the parent window.  The message nHelpMessage was registered
  314.          at application startup */
  315.  
  316.       if (msg == nHelpMessage)
  317.         MessageBox(GetForegroundWindow(),
  318.                    TEXT("Hello from the help button"),
  319.                    TEXT("Open Help Button"), MB_OK | MB_APPLMODAL) ;
  320.  
  321.       break ;
  322.  
  323.   }
  324.  
  325.   return FALSE ;
  326. }
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334. /************************************************************************
  335.  
  336.  
  337.   Function: InitOpenStruct(HWND, LPOPENFILENAME)
  338.  
  339.   Purpose:
  340.  
  341.     Initializes the OPENFILENAME structure.  The structure is referenced
  342.     via a pointer passed in as the second parameter so that we can pass
  343.     any of the three OPENFILENAME structures into this function and
  344.     Initialize them.
  345.  
  346.   Returns: Nothing.
  347.  
  348.   Comments:
  349.  
  350.     The szFilterInits and szCustFiltInits arrays are initialized to
  351.     contain some default strings.  Eventually the strings in
  352.     these arrays must be arranged one after the other with a null
  353.     character between them and two null characters at the end:
  354.  
  355.     "Text files\0*.txt\0All files\0*.*\0\0"
  356.  
  357. ************************************************************************/
  358.  
  359.  
  360. void InitOpenStruct(HWND hwnd, LPOPENFILENAME po)
  361. {
  362.    int i = 0 ;
  363.    szFileName[0] = 0 ;
  364.    szFileTitle[0] = 0 ;
  365.  
  366.    dwFlags = OFN_READONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_SHOWHELP  ;
  367.  
  368.    if (bDoOpenDlg)
  369.      lstrcpy(szDlgTitle, TEXT("Open Dialog Title")) ;
  370.    else
  371.      lstrcpy(szDlgTitle, TEXT("Save Dialog Title")) ;
  372.  
  373.    lstrcpy(szDefExt, TEXT("rat")) ;
  374.    lstrcpy(szInitialDir, TEXT("c:\\")) ;
  375.    lstrcpy(szTempName, TEXT("opentemp1")) ;
  376.  
  377.    lstrcpy(&szFilterInits[0][0], TEXT("All Files (*.*)")) ;
  378.    lstrcpy(&szFilterInits[1][0], TEXT("*.*")) ;
  379.    lstrcpy(&szFilterInits[2][0], TEXT("Fat Files (*.fat)")) ;
  380.    lstrcpy(&szFilterInits[3][0], TEXT("*.fat")) ;
  381.    szFilterInits[4][0] = (TCHAR) 0 ;
  382.  
  383.    lstrcpy(&szCustFiltInits[0][0], TEXT("Last Filter Used")) ;
  384.    lstrcpy(&szCustFiltInits[1][0], TEXT("*.lst")) ;
  385.    szCustFiltInits[2][0] = (TCHAR) 0 ;
  386.  
  387.  
  388.    /*
  389.  
  390.       These two functions will create "strings" in the applications
  391.       data area that are in the form
  392.  
  393.       "Filter Description"\0
  394.       "Filter"\0
  395.       "Filter Description"\0
  396.       "Filter"\0
  397.       ..
  398.       ..
  399.       \0\0
  400.  
  401.       The filters must be in this form in order that the common dialogs
  402.       interpret it correctly...
  403.    */
  404.  
  405.    InitFilterString() ;
  406.  
  407.    InitCustFilterString() ;
  408.  
  409.    po->lStructSize          = sizeof(OPENFILENAME) ;
  410.    po->hwndOwner            = hwnd ;
  411.    po->hInstance            = hInst ;
  412.    (LPTSTR) po->lpstrFilter = lpszFilterString ;
  413.    po->lpstrCustomFilter    = lpszCustFilterString ;
  414.    po->nMaxCustFilter       = MAXCUSTFILTER ;
  415.    po->nFilterIndex         = 1L ;
  416.    po->lpstrFile            = szFileName ;
  417.    po->nMaxFile             = FILENAMESIZE ;
  418.    po->lpstrFileTitle       = szFileTitle ;
  419.    po->nMaxFileTitle        = FILETITLESIZE ;
  420.    po->lpstrInitialDir      = szInitialDir ;
  421.    (LPTSTR) po->lpstrTitle  = szDlgTitle ;
  422.    po->Flags                = dwFlags ;
  423.    po->nFileOffset          = 0 ;
  424.    po->nFileExtension       = 0 ;
  425.    (LPTSTR) po->lpstrDefExt = szDefExt;
  426.    po->lCustData            = 0L ;
  427.    po->lpfnHook             = OpenSaveHookProc ;
  428.    (LPTSTR) po->lpTemplateName  = szTempName ;
  429.  
  430.    return ;
  431. }
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439. /************************************************************************
  440.  
  441.  
  442.   Function: FillOpenDlg(HWND, LPOPENFILENAME)
  443.  
  444.   Purpose:
  445.  
  446.     - This function will fill in the edit boxes that correspond to each
  447.       of the fields in the OPENFILENAME structure.  The user can accept
  448.       these values to create the common dialog or edit them.
  449.  
  450.   Returns: Nothing.
  451.  
  452.   Comments:
  453.  
  454.       The contents of the strings "szShortFilter" and "szLongFilter"
  455.       determine how a WORD or a DWORD value is represented in the edit boxes
  456.  
  457. ************************************************************************/
  458.  
  459. void FillOpenDlg(HWND hwnd, LPOPENFILENAME po)
  460. {
  461.    int i = 0 ;
  462.  
  463.    wsprintf(szTemp, szShortFilter, (int) po->lStructSize) ;
  464.    SetDlgItemText(hwnd, ID_STRUCTSIZEO, szTemp) ;
  465.  
  466.    wsprintf(szTemp, szLongFilter, (LONG) po->hwndOwner) ;
  467.    SetDlgItemText(hwnd, ID_HWNDOWNERO, szTemp) ;
  468.  
  469.    wsprintf(szTemp, szLongFilter, (LONG) po->hInstance) ;
  470.    SetDlgItemText(hwnd, ID_HINSTANCEO, szTemp) ;
  471.  
  472.  
  473.    SendDlgItemMessage(hwnd, ID_FILTERO, CB_RESETCONTENT,
  474.                       (WPARAM) 0, (LPARAM) 0) ;
  475.  
  476.    while (szFilterInits[i][0] != (TCHAR) 0)
  477.    {
  478.       SendDlgItemMessage(hwnd, ID_FILTERO, CB_ADDSTRING, (WPARAM) 0,
  479.                         (LPARAM) (LPTSTR) &szFilterInits[i][0]) ;
  480.       i++ ;
  481.    }
  482.  
  483.    SendDlgItemMessage(hwnd, ID_FILTERO, CB_SETCURSEL,
  484.                      (WPARAM) 0, (LPARAM) 0 ) ;
  485.  
  486.  
  487.  
  488.    SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_RESETCONTENT,
  489.                       (WPARAM) 0, (LPARAM) 0) ;
  490.  
  491.    for (i=0; i<2; i++)
  492.      SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_ADDSTRING, (WPARAM) 0,
  493.                         (LPARAM) (LPTSTR) &szCustFiltInits[i][0]) ;
  494.  
  495.    SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_SETCURSEL,
  496.                      (WPARAM) 0, (LPARAM) 0) ;
  497.  
  498.  
  499.    wsprintf(szTemp, szShortFilter, (int) po->nMaxCustFilter) ;
  500.    SetDlgItemText(hwnd, ID_MAXCUSTFILTO, szTemp) ;
  501.  
  502.    wsprintf(szTemp, szShortFilter, (int) po->nFilterIndex) ;
  503.    SetDlgItemText(hwnd, ID_FILTINDEXO, szTemp) ;
  504.  
  505.    SetDlgItemText(hwnd, ID_SZFILEO, po->lpstrFile) ;
  506.  
  507.    wsprintf(szTemp, szShortFilter, (int) po->nMaxFile) ;
  508.    SetDlgItemText(hwnd, ID_MAXSZFILEO, szTemp) ;
  509.  
  510.    SetDlgItemText(hwnd, ID_SZFILETITLEO, po->lpstrFileTitle) ;
  511.  
  512.    wsprintf(szTemp, szShortFilter, (int) po->nMaxFileTitle) ;
  513.    SetDlgItemText(hwnd, ID_MAXSZFILETITLEO, szTemp) ;
  514.  
  515.    SetDlgItemText(hwnd, ID_SZINITDIRO, po->lpstrInitialDir) ;
  516.  
  517.    SetDlgItemText(hwnd, ID_SZTITLEO, po->lpstrTitle) ;
  518.  
  519.    wsprintf(szTemp, szLongFilter, po->Flags) ;
  520.    SetDlgItemText(hwnd, ID_FLAGSO, szTemp) ;
  521.  
  522.    wsprintf(szTemp, szShortFilter, po->nFileOffset) ;
  523.    SetDlgItemText(hwnd, ID_FILEOFFO, szTemp) ;
  524.  
  525.    wsprintf(szTemp, szShortFilter, po->nFileExtension) ;
  526.    SetDlgItemText(hwnd, ID_FILEEXTO, szTemp) ;
  527.  
  528.    SetDlgItemText(hwnd, ID_SZDEFEXTO, po->lpstrDefExt) ;
  529.  
  530.    wsprintf(szTemp, szLongFilter, po->lCustData) ;
  531.    SetDlgItemText(hwnd, ID_CUSTDATAO, szTemp) ;
  532.  
  533.    wsprintf(szTemp, szLongFilter, po->lpfnHook) ;
  534.    SetDlgItemText(hwnd, ID_HOOKO, szTemp) ;
  535.  
  536.    SetDlgItemText(hwnd, ID_TEMPLATEO, po->lpTemplateName) ;
  537.  
  538.    return ;
  539. }
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548. /************************************************************************
  549.  
  550.  
  551.   Function: GetOpenDlg(HWND, LPOPENFILENAME)
  552.  
  553.  
  554.   Purpose:
  555.  
  556.       This function will retrieve the contents of each edit box corresponding
  557.       with each field in the OPENFILENAME structure, and fill in the
  558.       OPENFILENAME structure with these values.
  559.  
  560.   Returns: Nothing.
  561.  
  562.   Comments:
  563.  
  564.     if (uMode == IDM_HEXMODE), then the numbers should be interpreted as
  565.     hexidecimal and the MyAtol() function is called with its "bHex"
  566.     parameter set to true.
  567.  
  568. ************************************************************************/
  569.  
  570. void GetOpenDlg(HWND hwnd, LPOPENFILENAME po)
  571. {
  572.    int i ;
  573.    BOOL b ;
  574.    TCHAR szNum[20] ;
  575.  
  576.    GetDlgItemText(hwnd, ID_STRUCTSIZEO, szNum, 20) ;
  577.    po->lStructSize = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  578.  
  579.    GetDlgItemText(hwnd, ID_HWNDOWNERO, szNum, 20) ;
  580.    po->hwndOwner = (HWND) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  581.  
  582.    GetDlgItemText(hwnd, ID_HINSTANCEO, szNum, 20) ;
  583.    po->hInstance = (HANDLE) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  584.  
  585.  
  586.    /* these are just strings, no conversion necessary */
  587.  
  588.    i = 0 ;
  589.    while (SendDlgItemMessage(hwnd, ID_FILTERO, CB_GETLBTEXT, (WPARAM) i,
  590.                           (LPARAM) (LPTSTR) szFilterInits[i]) != CB_ERR)
  591.    { i++ ; }
  592.  
  593.  
  594.    /* create the filter string */
  595.  
  596.    InitFilterString() ;
  597.  
  598.  
  599.    i = 0 ;
  600.  
  601.    while (SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_GETLBTEXT, (WPARAM) i,
  602.                         (LPARAM) (LPTSTR) szCustFiltInits[i]) != CB_ERR)
  603.    { i++ ; }
  604.  
  605.  
  606.    InitCustFilterString() ;
  607.  
  608.  
  609.    GetDlgItemText(hwnd, ID_MAXCUSTFILTO, szNum, 20) ;
  610.    po->nMaxCustFilter = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  611.  
  612.    GetDlgItemText(hwnd, ID_FILTINDEXO, szNum, 20) ;
  613.    po->nFilterIndex = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  614.  
  615.    GetDlgItemText(hwnd, ID_SZFILEO, po->lpstrFile, MAXBUF) ;
  616.  
  617.    GetDlgItemText(hwnd, ID_MAXSZFILEO, szNum, 20) ;
  618.    po->nMaxFile = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  619.  
  620.    GetDlgItemText(hwnd, ID_SZFILETITLEO, po->lpstrFileTitle, MAXBUF) ;
  621.  
  622.    GetDlgItemText(hwnd, ID_MAXSZFILETITLEO, szNum, MAXBUF) ;
  623.    po->nMaxFileTitle = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  624.  
  625.    GetDlgItemText(hwnd, ID_SZINITDIRO, (LPTSTR) po->lpstrInitialDir, MAXBUF) ;
  626.  
  627.    GetDlgItemText(hwnd, ID_SZTITLEO, (LPTSTR) po->lpstrTitle, MAXBUF) ;
  628.  
  629.    GetDlgItemText(hwnd, ID_FLAGSO, szNum, 20) ;
  630.    po->Flags = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  631.  
  632.    GetDlgItemText(hwnd, ID_FILEOFFO, szNum, 20) ;
  633.    po->nFileOffset = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  634.  
  635.    GetDlgItemText(hwnd, ID_FILEEXTO, szNum, 20) ;
  636.    po->nFileExtension = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  637.  
  638.    GetDlgItemText(hwnd, ID_SZDEFEXTO, (LPTSTR) po->lpstrDefExt, DEFEXTSIZE) ;
  639.  
  640.    GetDlgItemText(hwnd, ID_CUSTDATAO, szNum, 20) ;
  641.    po->lCustData = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  642.  
  643.    GetDlgItemText(hwnd, ID_HOOKO, szNum, 20) ;
  644.    po->lpfnHook = (LPOFNHOOKPROC) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  645.  
  646.    GetDlgItemText(hwnd, ID_TEMPLATEO, (LPTSTR) po->lpTemplateName, TEMPNAMESIZE) ;
  647.  
  648.  
  649.    /*  if we are supposed to use a preloaded resource handle, load it and put it in
  650.        OPENFILENAME.hInstance... */
  651.  
  652.    if (IsDlgButtonChecked(hwnd, ID_USEHINSTO) == 1)
  653.      po->hInstance = GetCorrectResourceHandle() ;
  654.  
  655.    return ;
  656. }
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664. /************************************************************************
  665.  
  666.  
  667.   Function: InitFilterString(void)
  668.  
  669.  
  670.   Purpose:
  671.  
  672.     This function will create a "string" in memory in the form that the
  673.     GetOpenFileName() function will expect for the filters it fills into
  674.     the "List Files of Type" combo box.
  675.  
  676.   Returns: Nothing.
  677.  
  678.   Comments:
  679.  
  680.     The szFilterInits and szCustFiltInits arrays are initialized to
  681.     contain some default strings.  Eventually the strings in
  682.     these arrays must be arranged one after the other with a null
  683.     character between them and two null characters at the end:
  684.  
  685.     "Text files\0*.txt\0All files\0*.*\0\0"
  686.  
  687. ************************************************************************/
  688.  
  689.  
  690. void InitFilterString(void)
  691. {
  692.   int i ;
  693.   int nInc = 0 ;
  694.   LPTSTR lpStr = szFilterString ;
  695.  
  696.  
  697.   /* First, zero out this memory just for the sake of sanity */
  698.  
  699.   for (i=0; i<MAXBUF; i++)
  700.     szFilterString[i] = 0 ;
  701.  
  702.  
  703.   /* Now, for each string in the szFilterInits array, concatenate it to
  704.      the last one right after the last one's null terminator */
  705.  
  706.   i = 0 ;
  707.  
  708.   while (szFilterInits[i][0] != (TCHAR) 0)
  709.   {
  710.     lstrcpy(lpStr, &szFilterInits[i][0]) ;
  711.     nInc+=lstrlen(&szFilterInits[i][0]) + 1 ;   //1 past null term...
  712.     lpStr = &szFilterString[nInc] ;
  713.     i++ ;
  714.   }
  715.  
  716.   szFilterString[nInc] = (TCHAR) 0 ;  //double terminator
  717.  
  718.  
  719.   /* Set the lpszFilterString to point to the memory we just filled in
  720.      with the filters because lpszFilterString is what is in
  721.      OPENFILENAME->lpstrFilter */
  722.  
  723.   lpszFilterString = szFilterString ;
  724.  
  725.   return ;
  726. }
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734.  
  735.  
  736. /************************************************************************
  737.  
  738.  
  739.   Function: InitCustFiltString(void)
  740.  
  741.  
  742.   Purpose:
  743.  
  744.     This function will create a "string" in memory in the form that the
  745.     GetOpenFileName() function will expect for a custom filter.
  746.  
  747.   Returns: Nothing.
  748.  
  749.   Comments:
  750.  
  751.     The szFilterInits and szCustFiltInits arrays are initialized to
  752.     contain some default strings.  Eventually the strings in
  753.     these arrays must be arranged one after the other with a null
  754.     character between them and two null characters at the end:
  755.  
  756.     "Text files\0*.txt\0All files\0*.*\0\0"
  757.  
  758.     This program initializes these strings, but they do not need to be
  759.     initialized.  The GetOpenFileName() functiion will write a filter
  760.     into this memory area if the user types a new filter into the
  761.     "FileName" box and returns by clicking the OK button (indicating that
  762.     a file matching that filter was found).
  763.  
  764. ************************************************************************/
  765.  
  766.  
  767. void InitCustFilterString(void)
  768. {
  769.   int i ;
  770.   LPTSTR lpStr = szCustFilterString ;
  771.   int nInc = 0 ;
  772.  
  773.   for (i=0; i<MAXBUF; i++)
  774.     szCustFilterString[i] = 0 ;
  775.  
  776.   i = 0 ;
  777.  
  778.   for(i=0; i<2; i++)  //only two for the custom filter
  779.   {
  780.     lstrcpy(lpStr, &szCustFiltInits[i][0]) ;
  781.     nInc+=lstrlen(&szCustFiltInits[i][0]) + 1 ;
  782.     lpStr = &szCustFilterString[nInc] ;
  783.   }
  784.  
  785.   szCustFilterString[nInc] = (TCHAR) 0 ;
  786.  
  787.   lpszCustFilterString = szCustFilterString ;
  788.  
  789.   return ;
  790. }
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800. /************************************************************************
  801.  
  802.   Function: InterpretCustomFilterString(void)
  803.  
  804.  
  805.   Purpose:
  806.  
  807.     This function will parse the memory that is being used for the
  808.     custom filter string.  If the user returned TRUE after entering
  809.     their own filter, the new filter will be here and so we need to
  810.     add it to our custom filter init array...
  811.  
  812.   Returns: Nothing.
  813.  
  814.   Comments:
  815.  
  816. ************************************************************************/
  817.  
  818. void InterpretCustomFilterString(void)
  819. {
  820.   LPTSTR pNext ;
  821.  
  822.   int nCount = lstrlen(ofn.lpstrCustomFilter) ;
  823.  
  824.   pNext = ofn.lpstrCustomFilter + nCount + 1 ;  //one past the NULL
  825.  
  826.  
  827.   /* add it to the filter inits array */
  828.  
  829.   lstrcpy(&szCustFiltInits[0][0], ofn.lpstrCustomFilter) ;
  830.   lstrcpy(&szCustFiltInits[1][0], pNext) ;
  831.  
  832. }
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842. /************************************************************************
  843.  
  844.   Function: GetCorrectResourceHandle(void)
  845.  
  846.   Purpose:
  847.  
  848.     This function will use FindResource() to find the correct custom
  849.     template resource, use LoadResource() to get a handle to it.
  850.  
  851.   Returns: A handle to a custom template resource.
  852.  
  853.   Comments:
  854.  
  855.     The names for the custom template for GetOpenFileName() are
  856.  
  857.       "opentemp1" -- normal
  858.       "opentemp2" -- contains a multi-select list box for the file names
  859.  
  860.     If the user has marked the "Preloaded Template" box and specified
  861.     OFN_ENABLETEMPLATEHANDLE in the "Flags" edit box, this handle
  862.     will be used to create the GetOpenFileName() dialog box.
  863.  
  864. ************************************************************************/
  865.  
  866.  
  867. HANDLE GetCorrectResourceHandle(void)
  868. {
  869.   if (ofn.Flags & OFN_ALLOWMULTISELECT)
  870.   {
  871.      hRes = FindResource(hInst, TEXT("opentemp2"), RT_DIALOG) ;
  872.      hDialog = LoadResource(hInst, hRes) ;
  873.   }
  874.  
  875.   else
  876.   {
  877.      hRes = FindResource(hInst, TEXT("opentemp1"), RT_DIALOG) ;
  878.      hDialog = LoadResource(hInst, hRes) ;
  879.   }
  880.  
  881.   return hDialog ;
  882. }
  883.  
  884.  
  885.  
  886.  
  887.  
  888.  
  889.  
  890. /************************************************************************
  891.  
  892.   Function: OpenSaveHookProc(HWND, UINT, UINT, LONG) ;
  893.  
  894.   Purpose:
  895.  
  896.     This function is the hook function for the GetOpenFileName() function.
  897.     If GetOpenFileName() is called with the OFN_ENABLEHOOK flag, this
  898.     function will be called before the normal GetOpenFileName() dialog
  899.     function is called.
  900.  
  901.   Returns: FALSE to pass the message on to the normal GetOpenFileName()
  902.            logic, TRUE to discard the message.
  903.  
  904.   Comments:
  905.  
  906.     To enable this function in this program, enter the value for
  907.     OFN_ENABLEHOOK in the "Flags" edit box.
  908.  
  909. ************************************************************************/
  910.  
  911.  
  912. UINT APIENTRY OpenSaveHookProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  913. {
  914.   LPOPENFILENAME pOfn ;
  915.   TCHAR szMsg[50] ;
  916.  
  917.   switch(msg)
  918.   {
  919.     case WM_INITDIALOG:
  920.  
  921.       pOfn = (LPOPENFILENAME) lParam ;
  922.  
  923.  
  924.       /* During initialization, if there is a hook proc, the getopen()
  925.          code will send pointer to the OPENFILENAME strucure in the
  926.          lParam.  To demonstrate this, pop up a message box if this
  927.          structure has a non zero value in the lCustData structure member */
  928.  
  929.  
  930.       if (pOfn->lCustData != 0L)
  931.       {
  932.         wsprintf(szMsg, TEXT("OPENFILENAME->lCustData is: %ld"), pOfn->lCustData) ;
  933.  
  934.         MessageBox(hwnd, szMsg, TEXT("lCustData Sent!"), MB_OK) ;
  935.       }
  936.  
  937.       SetWindowText(hwnd, TEXT("Open Hook Proc Dialog")) ;
  938.  
  939.       break ;
  940.  
  941.  
  942.     /* use the WM_CTLCOLOR* messages to change the color of the Open
  943.        dialog */
  944.  
  945.     case WM_CTLCOLORDLG:
  946.  
  947.         if (!hBrushDlg)
  948.             hBrushDlg = GetStockObject(LTGRAY_BRUSH) ;
  949.  
  950.         return (UINT) hBrushDlg ;
  951.  
  952.         break ;
  953.  
  954.  
  955.     case WM_CTLCOLORBTN:
  956.  
  957.         SetBkMode((HDC) wParam, TRANSPARENT) ;   //sets background color
  958.                                                  //for push and check box
  959.                                                  //buttons...
  960.  
  961.         if (!hBrushButton)
  962.             hBrushButton = GetStockObject(LTGRAY_BRUSH) ;
  963.  
  964.         return (UINT) hBrushButton ;
  965.  
  966.         break ;
  967.  
  968.  
  969.     case WM_CTLCOLORSTATIC:
  970.  
  971.         SetTextColor((HDC) wParam, RGB(0x00, 0xff, 0x00)) ;  //green
  972.         SetBkMode((HDC) wParam, TRANSPARENT) ;               //transparent text
  973.  
  974.         if (!hBrushDlg)
  975.             hBrushDlg = GetStockObject(LTGRAY_BRUSH) ;
  976.  
  977.         return (UINT) hBrushDlg ;
  978.  
  979.         break ;
  980.  
  981.  
  982.     case WM_COMMAND:
  983.         switch (LOWORD(wParam))
  984.         {
  985.           case chx1:
  986.             MessageBox(hwnd, TEXT("Read-Only button clicked..."),
  987.                        TEXT("Open"), MB_OK | MB_APPLMODAL) ;
  988.             break ;
  989.  
  990.           case ID_FILEPREVIEW:
  991.             MessageBox(hwnd, TEXT("File Preview Button Clicked"),
  992.                        TEXT("Open"), MB_OK | MB_APPLMODAL) ;
  993.             break ;
  994.  
  995.           default: break ;
  996.         }
  997.         break ;
  998.  
  999.     default:
  1000.  
  1001.       if (msg == nOpenShareVMsg)
  1002.       {
  1003.         MessageBox(hwnd, TEXT("The SHAREVSTRING message is here!"),
  1004.                          TEXT("Open"),
  1005.                          MB_ICONEXCLAMATION | MB_OK | MB_APPLMODAL) ;
  1006.  
  1007.         return OFN_SHAREWARN ;
  1008.       }
  1009.       break ;
  1010.   }
  1011.  
  1012.   return FALSE ;   //send msg to the common dialog code
  1013. }
  1014.  
  1015.  
  1016.  
  1017.  
  1018.  
  1019.  
  1020.  
  1021.  
  1022.  
  1023. /************************************************************************
  1024.  
  1025.   Function: MultiThreadOpenSave(void)
  1026.  
  1027.   Purpose:
  1028.  
  1029.     This function will start two threads and then return.  The two
  1030.     threads will create GetOpenFileName() dialogs, and the user
  1031.     can interact with two Open dialogs at once.
  1032.  
  1033.   Returns: Nothing.
  1034.  
  1035.   Comments:
  1036.  
  1037.     This will create two Open dialogs, but they will be created in the
  1038.     same location on the screen.  The only way to change that would be
  1039.     to call the function with a hookproc and move one of the windows.
  1040.  
  1041.     But that would mean that if the user did not enter OFN_ENABLEHOOK
  1042.     in the "Flags" edit box, we would be no better off than before.  So,
  1043.     in order to see both dialogs, you just have to move the top one out
  1044.     of the way a little.
  1045.  
  1046.     Multithreading note:
  1047.  
  1048.     This function will return before the common dialog functions return.
  1049.     Therefore, do not pass any parameters to this function that will be
  1050.     referenced by the common dialogs because as soon as this function
  1051.     ends those parameters will be gone.
  1052.  
  1053. ************************************************************************/
  1054.  
  1055. void MultiThreadOpenSave(void)
  1056. {
  1057.  
  1058.   if (!(hOpenSaveThread1 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
  1059.                                         (LPTHREAD_START_ROUTINE) OpenSaveThread1Proc,
  1060.                                         &dwThreadParm1, CREATE_SUSPENDED, &dwThreadID1)))
  1061.  
  1062.   {
  1063.     MessageBox(GetForegroundWindow(), TEXT("Cannot create thread 1"), NULL, MB_OK | MB_ICONEXCLAMATION) ;
  1064.     OpenMultiThreadEnableButtons(TRUE, hwndMainDialog) ;
  1065.     nOpenDialogCount = 0 ;
  1066.     return ;
  1067.   }
  1068.  
  1069.  
  1070.  
  1071.   if (!(hOpenSaveThread2 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
  1072.                                         (LPTHREAD_START_ROUTINE) OpenSaveThread2Proc,
  1073.                                         &dwThreadParm2, CREATE_SUSPENDED, &dwThreadID2)))
  1074.   {
  1075.     MessageBox(GetForegroundWindow(), TEXT("Cannot create thread 2"), NULL, MB_OK | MB_ICONEXCLAMATION) ;
  1076.     OpenMultiThreadEnableButtons(TRUE, hwndMainDialog) ;
  1077.     nOpenDialogCount = 0 ;
  1078.     return ;
  1079.   }
  1080.  
  1081.  
  1082.   ResumeThread(hOpenSaveThread1) ;
  1083.   ResumeThread(hOpenSaveThread2) ;
  1084.  
  1085. }
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093. /************************************************************************
  1094.  
  1095.   Function: OpenSaveThreadProc1(LPDWORD)
  1096.  
  1097.   Purpose:
  1098.  
  1099.     This is the address where the first thread starts executing.
  1100.  
  1101.   Returns: Any DWORD value.
  1102.  
  1103.   Comments:
  1104.  
  1105. ************************************************************************/
  1106.  
  1107.  
  1108. DWORD OpenSaveThread1Proc(LPDWORD pDw)
  1109. {
  1110.  
  1111.   /* Get the user's input */
  1112.  
  1113.   GetOpenDlg(hwndMainDialog, &ofnThread1) ;
  1114.  
  1115.  
  1116.   /* Do the dialog */
  1117.  
  1118.   DoOpenSaveStuff(&ofnThread1) ;
  1119.  
  1120.  
  1121.   /* send a message to the parent telling it to decrement the dialog count.
  1122.      When the dialog count reaches zero, all the buttons are enabled again. */
  1123.  
  1124.   SendMessage(hwndMainDialog, UMSG_DECREMENTDLGCOUNT, 0, 0L) ;
  1125.  
  1126.   return 0L ;
  1127. }
  1128.  
  1129.  
  1130.  
  1131.  
  1132.  
  1133.  
  1134.  
  1135. /************************************************************************
  1136.  
  1137.   Function: OpenSaveThreadProc2(LPDWORD)
  1138.  
  1139.   Purpose:
  1140.  
  1141.     This is the address where the second thread starts executing.
  1142.  
  1143.   Returns: Any DWORD value.
  1144.  
  1145.   Comments:
  1146.  
  1147. ************************************************************************/
  1148.  
  1149. DWORD OpenSaveThread2Proc(LPDWORD pDw)
  1150. {
  1151.   GetOpenDlg(hwndMainDialog, &ofnThread2) ;
  1152.  
  1153.   DoOpenSaveStuff(&ofnThread2) ;
  1154.  
  1155.   SendMessage(hwndMainDialog, UMSG_DECREMENTDLGCOUNT, 0, 0L) ;
  1156.  
  1157.   return 0L ;
  1158. }
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166. /************************************************************************
  1167.  
  1168.   Function: DoOpenSaveStuff(LPOPENFILENAME)
  1169.  
  1170.   Purpose:
  1171.  
  1172.     This is the function that actually calls GetOpenFileName() or
  1173.     GetSaveFileName().  It receives a pointer to the structure to
  1174.     use as its only parameter.
  1175.  
  1176.   Returns: Nothing.
  1177.  
  1178.   Comments:
  1179.  
  1180. ************************************************************************/
  1181.  
  1182. void DoOpenSaveStuff(LPOPENFILENAME po)
  1183. {
  1184.   BOOL bRet = TRUE ;
  1185.  
  1186.  
  1187.   /* If bOpenDlg is TRUE, do GetOpenFileName(), else do GetSave().
  1188.      If the "NULL Structure" button is checked, send in a NULL pointer
  1189.      to the function */
  1190.  
  1191.   if (bDoOpenDlg)
  1192.   {
  1193.     if (IsDlgButtonChecked(hwndMainDialog, ID_NULLSTRUCTO) == 1)
  1194.       bRet = GetOpenFileName((LPOPENFILENAME) NULL) ;
  1195.     else
  1196.       bRet = GetOpenFileName(po) ;
  1197.   }
  1198.  
  1199.   else
  1200.   {
  1201.     if (IsDlgButtonChecked(hwndMainDialog, ID_NULLSTRUCTO))
  1202.       bRet = GetSaveFileName((LPOPENFILENAME) NULL) ;
  1203.     else
  1204.       bRet = GetSaveFileName(po) ;
  1205.   }
  1206.  
  1207.  
  1208.   /* Record the results */
  1209.  
  1210.   wsprintf(szTemp, szLongFilter, CommDlgExtendedError()) ;
  1211.   SetDlgItemText(hwndMainDialog, ID_ERRORO, szTemp) ;
  1212.  
  1213.   wsprintf(szTemp, szShortFilter, (int) bRet) ;
  1214.   SetDlgItemText(hwndMainDialog, ID_RETURNO, szTemp) ;
  1215.  
  1216.   InterpretCustomFilterString() ;
  1217.  
  1218.   FillOpenDlg(hwndMainDialog, po) ;
  1219.  
  1220.   if (hDialog)
  1221.   {
  1222.     FreeResource(hDialog) ;    //free ofn.hInstance
  1223.     hDialog = (HANDLE) 0 ;
  1224.     hRes = (HANDLE) 0 ;
  1225.   }
  1226. }
  1227.  
  1228.  
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234. /************************************************************************
  1235.  
  1236.   Function: OpenMultiThreadEnableButtons(BOOL, HWND)
  1237.  
  1238.   Purpose:
  1239.  
  1240.     Enable or disable the buttons that might affect the state of the
  1241.     OPENFILENAME structures.  This is necessary because during a
  1242.     multithreading session, these buttons may be accessible even though
  1243.     there are Open dialogs still working and we don't want to change
  1244.     the OPENFILENAME structure out from under them.
  1245.  
  1246.  
  1247.   Returns: Nothing.
  1248.  
  1249.   Comments:
  1250.  
  1251. ************************************************************************/
  1252.  
  1253. void OpenMultiThreadEnableButtons(BOOL bEnable, HWND hwnd)
  1254. {
  1255.   EnableWindow(GetDlgItem(hwnd, IDOK), bEnable) ;
  1256.   EnableWindow(GetDlgItem(hwnd, IDCANCEL), bEnable) ;
  1257.   EnableWindow(GetDlgItem(hwnd, ID_RESETOPEN), bEnable) ;
  1258.   EnableWindow(GetDlgItem(hwnd, ID_MULTIOPEN), bEnable) ;
  1259. }
  1260.