OPEN.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:33k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /************************************************************************
  2.   File: open.c
  3.   Purpose:
  4.     This file contains the routines to control the CDTEST.EXE "Open" dialog
  5.     box.  The "Open" dialog box allows the user to enter values into an
  6.     OPENFILENAME structure and then create GetOpenFileName() dialog boxes
  7.     on the fly.
  8.   Functions:
  9.     DoOpenDialog()                   -- starts off the main dialog for "open"
  10.     OpenFunc()                       -- Callback function for main dialog
  11.     InitOpenStruct()                 -- Fills initial OPENFILENAME structure.
  12.     FillOpenDlg()                    -- Fills the dialog with the values from
  13.                                         the OPENFILENAME structure.
  14.     GetOpenDlg()                     -- Retrieves the users entries from the
  15.                                         main dialog and puts them in the
  16.                                         OPENFILENAME structure.
  17.     InitFilterString()               -- Creates filter string
  18.     InitCustFiltString()             -- Creates custom filter string
  19.     InterpretCustomFilterString()    -- Parses custom filter string returned
  20.                                         from GetOpenFileName()
  21.     GetCorrectResourceHandle()       -- Loads custom templates from file
  22.                                         as resource handles
  23.     OpenSaveHookProc()               -- The hook function that will be
  24.                                         called if GetOpen/Save is called
  25.                                         with the OFN_ENABLEHOOK flag set.
  26.     MultiThreadOpenSave()            -- Creates two Open/Save dialogs that
  27.                                         the user can simultaneously access
  28.     OpenSaveThread1Proc()            -- The starting address of thread 1
  29.     OpenSaveThread2Proc()            -- The starting address of thread 2
  30.     DoOpenSaveStuff()                -- Does the actuall calling of
  31.                                         GetOpen/SaveFileName()
  32.     OpenMultiThreadEnableButtons()   -- Enables and disables buttons in
  33.                                         main dialog.  Needed when multi-
  34.                                         threading.
  35. ************************************************************************/
  36. #include <windows.h>
  37. #include <commdlg.h>
  38. #include <stdlib.h>
  39. #include <winnls.h>
  40. #include "cdtest.h"
  41. #include "open.h"
  42. #include "save.h"
  43. #include "dlgs.h"     //include file that contains all #defines for the
  44.                       //commdlg dialog templates.
  45. /* All functions defined in this file + 1 external function
  46.    and one external variable */
  47. extern UINT uMode ;                               //see cdtest.c
  48. extern LONG MyAtol(LPTSTR, BOOL, LPBOOL) ;
  49. void InterpretCustomFilterString(void) ;
  50. HANDLE GetCorrectResourceHandle(void) ;
  51. void DoOpenSaveStuff(LPOPENFILENAME) ;
  52. UINT APIENTRY OpenSaveHookProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam) ;
  53. DWORD OpenSaveThread1Proc(LPDWORD) ;
  54. DWORD OpenSaveThread2Proc(LPDWORD) ;
  55. void MultiThreadOpenSave(void) ;
  56. void OpenMultiThreadEnableButtons(BOOL, HWND) ;
  57. /* All global variables defined in this file */
  58. HWND hwndMainDialog ;   //global handle for open dialog.
  59. HANDLE hRes ;           //handles to the resource and dialog for
  60. HANDLE hDialog ;        //ofn_enabletemplatehandle
  61. HBRUSH hBrushDlg ;
  62. HBRUSH hBrushEdit ;     //brush handles for new colors done with hook proc
  63. HBRUSH hBrushButton ;
  64. HANDLE hOpenSaveThread1, hOpenSaveThread2 ;   //variables for the
  65. DWORD dwThreadID1, dwThreadID2 ;              //multithreading part
  66. DWORD dwThreadParm1, dwThreadParm2 ;
  67. OPENFILENAME ofnThread1, ofnThread2 ;
  68. int nOpenDialogCount ;
  69. /************************************************************************
  70.   Function: DoOpenDialog(HWND)
  71.   Purpose: To create the GetOpenFileName() and GetSaveFileName()
  72.            creation dialog.
  73.   Returns: Nothing.
  74.   Comments:
  75.     GetOpenFileName() and GetSaveFileName() are similiar enough so that
  76.     the same dialog can be used to edit their creation structure elements,
  77.     so a global variable "bDoOpenDlg" keeps track of which one to create
  78.     when the user clicks the OK or Multithread buttons...
  79. ************************************************************************/
  80. void DoOpenDialog(HWND hwnd)
  81. {
  82.   bDoOpenDlg = TRUE ;
  83.   DialogBox(hInst, MAKEINTRESOURCE(ID_OPENDIALOG), hwnd, OpenFunc) ;
  84. }
  85. /************************************************************************
  86.   Function: OpenFunc(HWND, UINT, UINT, LONG)
  87.   Purpose:
  88.     This is the callback function for the dialog box containing the
  89.     GetOpenFileName() and the GetSaveFileName() creation options.
  90.     This function will handle the messages for this dialog and create
  91.     either a GetOpenFileName() dialog or a GetSaveFileName() dialog
  92.     depending on the state of the bDoOpenDlg variable.
  93.   Returns: TRUE or FALSE depending on the situation.
  94.   Comments:
  95. ************************************************************************/
  96. BOOL APIENTRY OpenFunc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  97. {
  98.   switch (msg)
  99.   {
  100.     case WM_INITDIALOG:
  101.       if (bDoOpenDlg)
  102.         SetWindowText(hwnd, TEXT("GetOpenFileName()")) ;
  103.       else
  104.         SetWindowText(hwnd, TEXT("GetSaveFileName()")) ;
  105.       /* initialize the OPENFILENAME structure members */
  106.       InitOpenStruct(hwnd, &ofn) ;
  107.       /* Fill these values into the creation dialog */
  108.       FillOpenDlg(hwnd, &ofn) ;
  109.       /* There are three separate OPENFILENAME structures.  One for
  110.          the main Open/Save dialog and one for each multithreaded dialog.
  111.          Set them equal to begin with */
  112.       *(&ofnThread1) = *(&ofnThread2) = *(&ofn) ;
  113.       hwndMainDialog = hwnd ;
  114.       SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEO)) ;
  115.       break ;
  116.     case UMSG_DECREMENTDLGCOUNT:  //user defined message indicating
  117.                                   //the closure of a multithreaded dialog
  118.       /* When we are multithreading, there is nothing to prevent the
  119.          user from interacting with the creation dialog once the first
  120.          GetOpen(Save) file name dialog has returned.  So, in order
  121.          to prevent the Multithread" button from being pressed again
  122.          before the previous two multithreaded dialogs have been canceled,
  123.          disable the controls until we get a message from each thread
  124.          that the dialog has ended */
  125.       nOpenDialogCount-- ;
  126.       if (nOpenDialogCount == 0)
  127.         OpenMultiThreadEnableButtons(TRUE, hwnd) ;
  128.       break ;
  129.     case WM_COMMAND:
  130.     {
  131.       switch (LOWORD(wParam))
  132.       {
  133.         case IDOK:
  134.           GetOpenDlg(hwnd, &ofn) ;          //get the user's input
  135.           DoOpenSaveStuff(&ofn) ;           //do the dialog
  136.           break ;
  137.         case IDCANCEL:
  138.           EndDialog(hwnd, FALSE) ;
  139.           break ;
  140.         case ID_RESETOPEN:
  141.           SendDlgItemMessage(hwnd, ID_FILTERO, CB_RESETCONTENT,
  142.             (WPARAM) 0, (LPARAM) 0) ;
  143.           InitOpenStruct(hwnd, &ofn) ;
  144.           FillOpenDlg(hwnd, &ofn) ;
  145.           SendDlgItemMessage(hwnd, ID_NULLSTRUCTO, BM_SETCHECK, (WPARAM)0, (LPARAM)0) ;
  146.           SendDlgItemMessage(hwnd, ID_USEHINSTO, BM_SETCHECK, (WPARAM)0, (LPARAM)0) ;
  147.           *(&ofnThread1) = *(&ofnThread2) = *(&ofn) ;
  148.           SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEO)) ;
  149.           break ;
  150.         case ID_ADD1O:
  151.           GetDlgItemText(hwnd, ID_FILTERO, szTemp, 100) ;
  152.           if (*szTemp)
  153.           {
  154.             SendDlgItemMessage(hwnd, ID_FILTERO, CB_ADDSTRING, (WPARAM) 0,
  155.                               (LPARAM) (LPTSTR) szTemp) ;
  156.             SetWindowText(GetDlgItem(hwnd, ID_FILTERO), TEXT("")) ;
  157.           }
  158.           break ;
  159.         case ID_ADD2O:
  160.           GetDlgItemText(hwnd, ID_CUSTFILTO, szTemp, 100) ;
  161.           if (*szTemp)
  162.           {
  163.             SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_ADDSTRING, (WPARAM) 0,
  164.                               (LPARAM) (LPTSTR) szTemp) ;
  165.             SetWindowText(GetDlgItem(hwnd, ID_CUSTFILTO), TEXT("")) ;
  166.           }
  167.           break ;
  168.         case ID_CLEAR1O:
  169.           SendDlgItemMessage(hwnd, ID_FILTERO, CB_RESETCONTENT,
  170.                              (WPARAM) 0, (LPARAM) 0) ;
  171.           break ;
  172.         case ID_CLEAR2O:
  173.           SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_RESETCONTENT,
  174.                              (WPARAM) 0, (LPARAM) 0) ;
  175.           break ;
  176.         case ID_MULTIOPEN:
  177.         /* First, disable the OK, Cancel, and MultiThread buttons */
  178.           OpenMultiThreadEnableButtons(FALSE, hwnd) ;
  179.         /* Then multithread the dialogs */
  180.           nOpenDialogCount = 2 ;
  181.           MultiThreadOpenSave() ;
  182.           break ;
  183.         default:   //end WM_COMMAND case
  184.           break ;
  185.       }
  186.     }
  187.     default:
  188.       /* If the help button is pressed in the GetOpen/SaveFileName()
  189.          dialogs, it will send a message Registered with RegisterWindowMessage()
  190.          to the parent window.  The message nHelpMessage was registered
  191.          at application startup */
  192.       if (msg == nHelpMessage)
  193.         MessageBox(GetForegroundWindow(),
  194.                    TEXT("Hello from the help button"),
  195.                    TEXT("Open Help Button"), MB_OK | MB_APPLMODAL) ;
  196.       break ;
  197.   }
  198.   return FALSE ;
  199. }
  200. /************************************************************************
  201.   Function: InitOpenStruct(HWND, LPOPENFILENAME)
  202.   Purpose:
  203.     Initializes the OPENFILENAME structure.  The structure is referenced
  204.     via a pointer passed in as the second parameter so that we can pass
  205.     any of the three OPENFILENAME structures into this function and
  206.     Initialize them.
  207.   Returns: Nothing.
  208.   Comments:
  209.     The szFilterInits and szCustFiltInits arrays are initialized to
  210.     contain some default strings.  Eventually the strings in
  211.     these arrays must be arranged one after the other with a null
  212.     character between them and two null characters at the end:
  213.     "Text files*.txtAll files*.*"
  214. ************************************************************************/
  215. void InitOpenStruct(HWND hwnd, LPOPENFILENAME po)
  216. {
  217.    int i = 0 ;
  218.    szFileName[0] = 0 ;
  219.    szFileTitle[0] = 0 ;
  220.    dwFlags = OFN_READONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_SHOWHELP  ;
  221.    if (bDoOpenDlg)
  222.      lstrcpy(szDlgTitle, TEXT("Open Dialog Title")) ;
  223.    else
  224.      lstrcpy(szDlgTitle, TEXT("Save Dialog Title")) ;
  225.    lstrcpy(szDefExt, TEXT("rat")) ;
  226.    lstrcpy(szInitialDir, TEXT("c:\")) ;
  227.    lstrcpy(szTempName, TEXT("opentemp1")) ;
  228.    lstrcpy(&szFilterInits[0][0], TEXT("All Files (*.*)")) ;
  229.    lstrcpy(&szFilterInits[1][0], TEXT("*.*")) ;
  230.    lstrcpy(&szFilterInits[2][0], TEXT("Fat Files (*.fat)")) ;
  231.    lstrcpy(&szFilterInits[3][0], TEXT("*.fat")) ;
  232.    szFilterInits[4][0] = (TCHAR) 0 ;
  233.    lstrcpy(&szCustFiltInits[0][0], TEXT("Last Filter Used")) ;
  234.    lstrcpy(&szCustFiltInits[1][0], TEXT("*.lst")) ;
  235.    szCustFiltInits[2][0] = (TCHAR) 0 ;
  236.    /*
  237.       These two functions will create "strings" in the applications
  238.       data area that are in the form
  239.       "Filter Description"
  240.       "Filter"
  241.       "Filter Description"
  242.       "Filter"
  243.       ..
  244.       ..
  245.       
  246.       The filters must be in this form in order that the common dialogs
  247.       interpret it correctly...
  248.    */
  249.    InitFilterString() ;
  250.    InitCustFilterString() ;
  251.    po->lStructSize          = sizeof(OPENFILENAME) ;
  252.    po->hwndOwner            = hwnd ;
  253.    po->hInstance            = hInst ;
  254.    (LPTSTR) po->lpstrFilter = lpszFilterString ;
  255.    po->lpstrCustomFilter    = lpszCustFilterString ;
  256.    po->nMaxCustFilter       = MAXCUSTFILTER ;
  257.    po->nFilterIndex         = 1L ;
  258.    po->lpstrFile            = szFileName ;
  259.    po->nMaxFile             = FILENAMESIZE ;
  260.    po->lpstrFileTitle       = szFileTitle ;
  261.    po->nMaxFileTitle        = FILETITLESIZE ;
  262.    po->lpstrInitialDir      = szInitialDir ;
  263.    (LPTSTR) po->lpstrTitle  = szDlgTitle ;
  264.    po->Flags                = dwFlags ;
  265.    po->nFileOffset          = 0 ;
  266.    po->nFileExtension       = 0 ;
  267.    (LPTSTR) po->lpstrDefExt = szDefExt;
  268.    po->lCustData            = 0L ;
  269.    po->lpfnHook             = OpenSaveHookProc ;
  270.    (LPTSTR) po->lpTemplateName  = szTempName ;
  271.    return ;
  272. }
  273. /************************************************************************
  274.   Function: FillOpenDlg(HWND, LPOPENFILENAME)
  275.   Purpose:
  276.     - This function will fill in the edit boxes that correspond to each
  277.       of the fields in the OPENFILENAME structure.  The user can accept
  278.       these values to create the common dialog or edit them.
  279.   Returns: Nothing.
  280.   Comments:
  281.       The contents of the strings "szShortFilter" and "szLongFilter"
  282.       determine how a WORD or a DWORD value is represented in the edit boxes
  283. ************************************************************************/
  284. void FillOpenDlg(HWND hwnd, LPOPENFILENAME po)
  285. {
  286.    int i = 0 ;
  287.    wsprintf(szTemp, szShortFilter, (int) po->lStructSize) ;
  288.    SetDlgItemText(hwnd, ID_STRUCTSIZEO, szTemp) ;
  289.    wsprintf(szTemp, szLongFilter, (LONG) po->hwndOwner) ;
  290.    SetDlgItemText(hwnd, ID_HWNDOWNERO, szTemp) ;
  291.    wsprintf(szTemp, szLongFilter, (LONG) po->hInstance) ;
  292.    SetDlgItemText(hwnd, ID_HINSTANCEO, szTemp) ;
  293.    SendDlgItemMessage(hwnd, ID_FILTERO, CB_RESETCONTENT,
  294.                       (WPARAM) 0, (LPARAM) 0) ;
  295.    while (szFilterInits[i][0] != (TCHAR) 0)
  296.    {
  297.       SendDlgItemMessage(hwnd, ID_FILTERO, CB_ADDSTRING, (WPARAM) 0,
  298.                         (LPARAM) (LPTSTR) &szFilterInits[i][0]) ;
  299.       i++ ;
  300.    }
  301.    SendDlgItemMessage(hwnd, ID_FILTERO, CB_SETCURSEL,
  302.                      (WPARAM) 0, (LPARAM) 0 ) ;
  303.    SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_RESETCONTENT,
  304.                       (WPARAM) 0, (LPARAM) 0) ;
  305.    for (i=0; i<2; i++)
  306.      SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_ADDSTRING, (WPARAM) 0,
  307.                         (LPARAM) (LPTSTR) &szCustFiltInits[i][0]) ;
  308.    SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_SETCURSEL,
  309.                      (WPARAM) 0, (LPARAM) 0) ;
  310.    wsprintf(szTemp, szShortFilter, (int) po->nMaxCustFilter) ;
  311.    SetDlgItemText(hwnd, ID_MAXCUSTFILTO, szTemp) ;
  312.    wsprintf(szTemp, szShortFilter, (int) po->nFilterIndex) ;
  313.    SetDlgItemText(hwnd, ID_FILTINDEXO, szTemp) ;
  314.    SetDlgItemText(hwnd, ID_SZFILEO, po->lpstrFile) ;
  315.    wsprintf(szTemp, szShortFilter, (int) po->nMaxFile) ;
  316.    SetDlgItemText(hwnd, ID_MAXSZFILEO, szTemp) ;
  317.    SetDlgItemText(hwnd, ID_SZFILETITLEO, po->lpstrFileTitle) ;
  318.    wsprintf(szTemp, szShortFilter, (int) po->nMaxFileTitle) ;
  319.    SetDlgItemText(hwnd, ID_MAXSZFILETITLEO, szTemp) ;
  320.    SetDlgItemText(hwnd, ID_SZINITDIRO, po->lpstrInitialDir) ;
  321.    SetDlgItemText(hwnd, ID_SZTITLEO, po->lpstrTitle) ;
  322.    wsprintf(szTemp, szLongFilter, po->Flags) ;
  323.    SetDlgItemText(hwnd, ID_FLAGSO, szTemp) ;
  324.    wsprintf(szTemp, szShortFilter, po->nFileOffset) ;
  325.    SetDlgItemText(hwnd, ID_FILEOFFO, szTemp) ;
  326.    wsprintf(szTemp, szShortFilter, po->nFileExtension) ;
  327.    SetDlgItemText(hwnd, ID_FILEEXTO, szTemp) ;
  328.    SetDlgItemText(hwnd, ID_SZDEFEXTO, po->lpstrDefExt) ;
  329.    wsprintf(szTemp, szLongFilter, po->lCustData) ;
  330.    SetDlgItemText(hwnd, ID_CUSTDATAO, szTemp) ;
  331.    wsprintf(szTemp, szLongFilter, po->lpfnHook) ;
  332.    SetDlgItemText(hwnd, ID_HOOKO, szTemp) ;
  333.    SetDlgItemText(hwnd, ID_TEMPLATEO, po->lpTemplateName) ;
  334.    return ;
  335. }
  336. /************************************************************************
  337.   Function: GetOpenDlg(HWND, LPOPENFILENAME)
  338.   Purpose:
  339.       This function will retrieve the contents of each edit box corresponding
  340.       with each field in the OPENFILENAME structure, and fill in the
  341.       OPENFILENAME structure with these values.
  342.   Returns: Nothing.
  343.   Comments:
  344.     if (uMode == IDM_HEXMODE), then the numbers should be interpreted as
  345.     hexidecimal and the MyAtol() function is called with its "bHex"
  346.     parameter set to true.
  347. ************************************************************************/
  348. void GetOpenDlg(HWND hwnd, LPOPENFILENAME po)
  349. {
  350.    int i ;
  351.    BOOL b ;
  352.    TCHAR szNum[20] ;
  353.    GetDlgItemText(hwnd, ID_STRUCTSIZEO, szNum, 20) ;
  354.    po->lStructSize = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  355.    GetDlgItemText(hwnd, ID_HWNDOWNERO, szNum, 20) ;
  356.    po->hwndOwner = (HWND) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  357.    GetDlgItemText(hwnd, ID_HINSTANCEO, szNum, 20) ;
  358.    po->hInstance = (HANDLE) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  359.    /* these are just strings, no conversion necessary */
  360.    i = 0 ;
  361.    while (SendDlgItemMessage(hwnd, ID_FILTERO, CB_GETLBTEXT, (WPARAM) i,
  362.                           (LPARAM) (LPTSTR) szFilterInits[i]) != CB_ERR)
  363.    { i++ ; }
  364.    /* create the filter string */
  365.    InitFilterString() ;
  366.    i = 0 ;
  367.    while (SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_GETLBTEXT, (WPARAM) i,
  368.                         (LPARAM) (LPTSTR) szCustFiltInits[i]) != CB_ERR)
  369.    { i++ ; }
  370.    InitCustFilterString() ;
  371.    GetDlgItemText(hwnd, ID_MAXCUSTFILTO, szNum, 20) ;
  372.    po->nMaxCustFilter = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  373.    GetDlgItemText(hwnd, ID_FILTINDEXO, szNum, 20) ;
  374.    po->nFilterIndex = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  375.    GetDlgItemText(hwnd, ID_SZFILEO, po->lpstrFile, MAXBUF) ;
  376.    GetDlgItemText(hwnd, ID_MAXSZFILEO, szNum, 20) ;
  377.    po->nMaxFile = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  378.    GetDlgItemText(hwnd, ID_SZFILETITLEO, po->lpstrFileTitle, MAXBUF) ;
  379.    GetDlgItemText(hwnd, ID_MAXSZFILETITLEO, szNum, MAXBUF) ;
  380.    po->nMaxFileTitle = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  381.    GetDlgItemText(hwnd, ID_SZINITDIRO, (LPTSTR) po->lpstrInitialDir, MAXBUF) ;
  382.    GetDlgItemText(hwnd, ID_SZTITLEO, (LPTSTR) po->lpstrTitle, MAXBUF) ;
  383.    GetDlgItemText(hwnd, ID_FLAGSO, szNum, 20) ;
  384.    po->Flags = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  385.    GetDlgItemText(hwnd, ID_FILEOFFO, szNum, 20) ;
  386.    po->nFileOffset = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  387.    GetDlgItemText(hwnd, ID_FILEEXTO, szNum, 20) ;
  388.    po->nFileExtension = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  389.    GetDlgItemText(hwnd, ID_SZDEFEXTO, (LPTSTR) po->lpstrDefExt, DEFEXTSIZE) ;
  390.    GetDlgItemText(hwnd, ID_CUSTDATAO, szNum, 20) ;
  391.    po->lCustData = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  392.    GetDlgItemText(hwnd, ID_HOOKO, szNum, 20) ;
  393.    po->lpfnHook = (LPOFNHOOKPROC) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
  394.    GetDlgItemText(hwnd, ID_TEMPLATEO, (LPTSTR) po->lpTemplateName, TEMPNAMESIZE) ;
  395.    /*  if we are supposed to use a preloaded resource handle, load it and put it in
  396.        OPENFILENAME.hInstance... */
  397.    if (IsDlgButtonChecked(hwnd, ID_USEHINSTO) == 1)
  398.      po->hInstance = GetCorrectResourceHandle() ;
  399.    return ;
  400. }
  401. /************************************************************************
  402.   Function: InitFilterString(void)
  403.   Purpose:
  404.     This function will create a "string" in memory in the form that the
  405.     GetOpenFileName() function will expect for the filters it fills into
  406.     the "List Files of Type" combo box.
  407.   Returns: Nothing.
  408.   Comments:
  409.     The szFilterInits and szCustFiltInits arrays are initialized to
  410.     contain some default strings.  Eventually the strings in
  411.     these arrays must be arranged one after the other with a null
  412.     character between them and two null characters at the end:
  413.     "Text files*.txtAll files*.*"
  414. ************************************************************************/
  415. void InitFilterString(void)
  416. {
  417.   int i ;
  418.   int nInc = 0 ;
  419.   LPTSTR lpStr = szFilterString ;
  420.   /* First, zero out this memory just for the sake of sanity */
  421.   for (i=0; i<MAXBUF; i++)
  422.     szFilterString[i] = 0 ;
  423.   /* Now, for each string in the szFilterInits array, concatenate it to
  424.      the last one right after the last one's null terminator */
  425.   i = 0 ;
  426.   while (szFilterInits[i][0] != (TCHAR) 0)
  427.   {
  428.     lstrcpy(lpStr, &szFilterInits[i][0]) ;
  429.     nInc+=lstrlen(&szFilterInits[i][0]) + 1 ;   //1 past null term...
  430.     lpStr = &szFilterString[nInc] ;
  431.     i++ ;
  432.   }
  433.   szFilterString[nInc] = (TCHAR) 0 ;  //double terminator
  434.   /* Set the lpszFilterString to point to the memory we just filled in
  435.      with the filters because lpszFilterString is what is in
  436.      OPENFILENAME->lpstrFilter */
  437.   lpszFilterString = szFilterString ;
  438.   return ;
  439. }
  440. /************************************************************************
  441.   Function: InitCustFiltString(void)
  442.   Purpose:
  443.     This function will create a "string" in memory in the form that the
  444.     GetOpenFileName() function will expect for a custom filter.
  445.   Returns: Nothing.
  446.   Comments:
  447.     The szFilterInits and szCustFiltInits arrays are initialized to
  448.     contain some default strings.  Eventually the strings in
  449.     these arrays must be arranged one after the other with a null
  450.     character between them and two null characters at the end:
  451.     "Text files*.txtAll files*.*"
  452.     This program initializes these strings, but they do not need to be
  453.     initialized.  The GetOpenFileName() functiion will write a filter
  454.     into this memory area if the user types a new filter into the
  455.     "FileName" box and returns by clicking the OK button (indicating that
  456.     a file matching that filter was found).
  457. ************************************************************************/
  458. void InitCustFilterString(void)
  459. {
  460.   int i ;
  461.   LPTSTR lpStr = szCustFilterString ;
  462.   int nInc = 0 ;
  463.   for (i=0; i<MAXBUF; i++)
  464.     szCustFilterString[i] = 0 ;
  465.   i = 0 ;
  466.   for(i=0; i<2; i++)  //only two for the custom filter
  467.   {
  468.     lstrcpy(lpStr, &szCustFiltInits[i][0]) ;
  469.     nInc+=lstrlen(&szCustFiltInits[i][0]) + 1 ;
  470.     lpStr = &szCustFilterString[nInc] ;
  471.   }
  472.   szCustFilterString[nInc] = (TCHAR) 0 ;
  473.   lpszCustFilterString = szCustFilterString ;
  474.   return ;
  475. }
  476. /************************************************************************
  477.   Function: InterpretCustomFilterString(void)
  478.   Purpose:
  479.     This function will parse the memory that is being used for the
  480.     custom filter string.  If the user returned TRUE after entering
  481.     their own filter, the new filter will be here and so we need to
  482.     add it to our custom filter init array...
  483.   Returns: Nothing.
  484.   Comments:
  485. ************************************************************************/
  486. void InterpretCustomFilterString(void)
  487. {
  488.   LPTSTR pNext ;
  489.   int nCount = lstrlen(ofn.lpstrCustomFilter) ;
  490.   pNext = ofn.lpstrCustomFilter + nCount + 1 ;  //one past the NULL
  491.   /* add it to the filter inits array */
  492.   lstrcpy(&szCustFiltInits[0][0], ofn.lpstrCustomFilter) ;
  493.   lstrcpy(&szCustFiltInits[1][0], pNext) ;
  494. }
  495. /************************************************************************
  496.   Function: GetCorrectResourceHandle(void)
  497.   Purpose:
  498.     This function will use FindResource() to find the correct custom
  499.     template resource, use LoadResource() to get a handle to it.
  500.   Returns: A handle to a custom template resource.
  501.   Comments:
  502.     The names for the custom template for GetOpenFileName() are
  503.       "opentemp1" -- normal
  504.       "opentemp2" -- contains a multi-select list box for the file names
  505.     If the user has marked the "Preloaded Template" box and specified
  506.     OFN_ENABLETEMPLATEHANDLE in the "Flags" edit box, this handle
  507.     will be used to create the GetOpenFileName() dialog box.
  508. ************************************************************************/
  509. HANDLE GetCorrectResourceHandle(void)
  510. {
  511.   if (ofn.Flags & OFN_ALLOWMULTISELECT)
  512.   {
  513.      hRes = FindResource(hInst, TEXT("opentemp2"), RT_DIALOG) ;
  514.      hDialog = LoadResource(hInst, hRes) ;
  515.   }
  516.   else
  517.   {
  518.      hRes = FindResource(hInst, TEXT("opentemp1"), RT_DIALOG) ;
  519.      hDialog = LoadResource(hInst, hRes) ;
  520.   }
  521.   return hDialog ;
  522. }
  523. /************************************************************************
  524.   Function: OpenSaveHookProc(HWND, UINT, UINT, LONG) ;
  525.   Purpose:
  526.     This function is the hook function for the GetOpenFileName() function.
  527.     If GetOpenFileName() is called with the OFN_ENABLEHOOK flag, this
  528.     function will be called before the normal GetOpenFileName() dialog
  529.     function is called.
  530.   Returns: FALSE to pass the message on to the normal GetOpenFileName()
  531.            logic, TRUE to discard the message.
  532.   Comments:
  533.     To enable this function in this program, enter the value for
  534.     OFN_ENABLEHOOK in the "Flags" edit box.
  535. ************************************************************************/
  536. UINT APIENTRY OpenSaveHookProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  537. {
  538.   LPOPENFILENAME pOfn ;
  539.   TCHAR szMsg[50] ;
  540.   switch(msg)
  541.   {
  542.     case WM_INITDIALOG:
  543.       pOfn = (LPOPENFILENAME) lParam ;
  544.       /* During initialization, if there is a hook proc, the getopen()
  545.          code will send pointer to the OPENFILENAME strucure in the
  546.          lParam.  To demonstrate this, pop up a message box if this
  547.          structure has a non zero value in the lCustData structure member */
  548.       if (pOfn->lCustData != 0L)
  549.       {
  550.         wsprintf(szMsg, TEXT("OPENFILENAME->lCustData is: %ld"), pOfn->lCustData) ;
  551.         MessageBox(hwnd, szMsg, TEXT("lCustData Sent!"), MB_OK) ;
  552.       }
  553.       SetWindowText(hwnd, TEXT("Open Hook Proc Dialog")) ;
  554.       break ;
  555.     /* use the WM_CTLCOLOR* messages to change the color of the Open
  556.        dialog */
  557.     case WM_CTLCOLORDLG:
  558.         if (!hBrushDlg)
  559.             hBrushDlg = GetStockObject(LTGRAY_BRUSH) ;
  560.         return (UINT) hBrushDlg ;
  561.         break ;
  562.     case WM_CTLCOLORBTN:
  563.         SetBkMode((HDC) wParam, TRANSPARENT) ;   //sets background color
  564.                                                  //for push and check box
  565.                                                  //buttons...
  566.         if (!hBrushButton)
  567.             hBrushButton = GetStockObject(LTGRAY_BRUSH) ;
  568.         return (UINT) hBrushButton ;
  569.         break ;
  570.     case WM_CTLCOLORSTATIC:
  571.         SetTextColor((HDC) wParam, RGB(0x00, 0xff, 0x00)) ;  //green
  572.         SetBkMode((HDC) wParam, TRANSPARENT) ;               //transparent text
  573.         if (!hBrushDlg)
  574.             hBrushDlg = GetStockObject(LTGRAY_BRUSH) ;
  575.         return (UINT) hBrushDlg ;
  576.         break ;
  577.     case WM_COMMAND:
  578.         switch (LOWORD(wParam))
  579.         {
  580.           case chx1:
  581.             MessageBox(hwnd, TEXT("Read-Only button clicked..."),
  582.                        TEXT("Open"), MB_OK | MB_APPLMODAL) ;
  583.             break ;
  584.           case ID_FILEPREVIEW:
  585.             MessageBox(hwnd, TEXT("File Preview Button Clicked"),
  586.                        TEXT("Open"), MB_OK | MB_APPLMODAL) ;
  587.             break ;
  588.           default: break ;
  589.         }
  590.         break ;
  591.     default:
  592.       if (msg == nOpenShareVMsg)
  593.       {
  594.         MessageBox(hwnd, TEXT("The SHAREVSTRING message is here!"),
  595.                          TEXT("Open"),
  596.                          MB_ICONEXCLAMATION | MB_OK | MB_APPLMODAL) ;
  597.         return OFN_SHAREWARN ;
  598.       }
  599.       break ;
  600.   }
  601.   return FALSE ;   //send msg to the common dialog code
  602. }
  603. /************************************************************************
  604.   Function: MultiThreadOpenSave(void)
  605.   Purpose:
  606.     This function will start two threads and then return.  The two
  607.     threads will create GetOpenFileName() dialogs, and the user
  608.     can interact with two Open dialogs at once.
  609.   Returns: Nothing.
  610.   Comments:
  611.     This will create two Open dialogs, but they will be created in the
  612.     same location on the screen.  The only way to change that would be
  613.     to call the function with a hookproc and move one of the windows.
  614.     But that would mean that if the user did not enter OFN_ENABLEHOOK
  615.     in the "Flags" edit box, we would be no better off than before.  So,
  616.     in order to see both dialogs, you just have to move the top one out
  617.     of the way a little.
  618.     Multithreading note:
  619.     This function will return before the common dialog functions return.
  620.     Therefore, do not pass any parameters to this function that will be
  621.     referenced by the common dialogs because as soon as this function
  622.     ends those parameters will be gone.
  623. ************************************************************************/
  624. void MultiThreadOpenSave(void)
  625. {
  626.   if (!(hOpenSaveThread1 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
  627.                                         (LPTHREAD_START_ROUTINE) OpenSaveThread1Proc,
  628.                                         &dwThreadParm1, CREATE_SUSPENDED, &dwThreadID1)))
  629.   {
  630.     MessageBox(GetForegroundWindow(), TEXT("Cannot create thread 1"), NULL, MB_OK | MB_ICONEXCLAMATION) ;
  631.     OpenMultiThreadEnableButtons(TRUE, hwndMainDialog) ;
  632.     nOpenDialogCount = 0 ;
  633.     return ;
  634.   }
  635.   if (!(hOpenSaveThread2 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
  636.                                         (LPTHREAD_START_ROUTINE) OpenSaveThread2Proc,
  637.                                         &dwThreadParm2, CREATE_SUSPENDED, &dwThreadID2)))
  638.   {
  639.     MessageBox(GetForegroundWindow(), TEXT("Cannot create thread 2"), NULL, MB_OK | MB_ICONEXCLAMATION) ;
  640.     OpenMultiThreadEnableButtons(TRUE, hwndMainDialog) ;
  641.     nOpenDialogCount = 0 ;
  642.     return ;
  643.   }
  644.   ResumeThread(hOpenSaveThread1) ;
  645.   ResumeThread(hOpenSaveThread2) ;
  646. }
  647. /************************************************************************
  648.   Function: OpenSaveThreadProc1(LPDWORD)
  649.   Purpose:
  650.     This is the address where the first thread starts executing.
  651.   Returns: Any DWORD value.
  652.   Comments:
  653. ************************************************************************/
  654. DWORD OpenSaveThread1Proc(LPDWORD pDw)
  655. {
  656.   /* Get the user's input */
  657.   GetOpenDlg(hwndMainDialog, &ofnThread1) ;
  658.   /* Do the dialog */
  659.   DoOpenSaveStuff(&ofnThread1) ;
  660.   /* send a message to the parent telling it to decrement the dialog count.
  661.      When the dialog count reaches zero, all the buttons are enabled again. */
  662.   SendMessage(hwndMainDialog, UMSG_DECREMENTDLGCOUNT, 0, 0L) ;
  663.   return 0L ;
  664. }
  665. /************************************************************************
  666.   Function: OpenSaveThreadProc2(LPDWORD)
  667.   Purpose:
  668.     This is the address where the second thread starts executing.
  669.   Returns: Any DWORD value.
  670.   Comments:
  671. ************************************************************************/
  672. DWORD OpenSaveThread2Proc(LPDWORD pDw)
  673. {
  674.   GetOpenDlg(hwndMainDialog, &ofnThread2) ;
  675.   DoOpenSaveStuff(&ofnThread2) ;
  676.   SendMessage(hwndMainDialog, UMSG_DECREMENTDLGCOUNT, 0, 0L) ;
  677.   return 0L ;
  678. }
  679. /************************************************************************
  680.   Function: DoOpenSaveStuff(LPOPENFILENAME)
  681.   Purpose:
  682.     This is the function that actually calls GetOpenFileName() or
  683.     GetSaveFileName().  It receives a pointer to the structure to
  684.     use as its only parameter.
  685.   Returns: Nothing.
  686.   Comments:
  687. ************************************************************************/
  688. void DoOpenSaveStuff(LPOPENFILENAME po)
  689. {
  690.   BOOL bRet = TRUE ;
  691.   /* If bOpenDlg is TRUE, do GetOpenFileName(), else do GetSave().
  692.      If the "NULL Structure" button is checked, send in a NULL pointer
  693.      to the function */
  694.   if (bDoOpenDlg)
  695.   {
  696.     if (IsDlgButtonChecked(hwndMainDialog, ID_NULLSTRUCTO) == 1)
  697.       bRet = GetOpenFileName((LPOPENFILENAME) NULL) ;
  698.     else
  699.       bRet = GetOpenFileName(po) ;
  700.   }
  701.   else
  702.   {
  703.     if (IsDlgButtonChecked(hwndMainDialog, ID_NULLSTRUCTO))
  704.       bRet = GetSaveFileName((LPOPENFILENAME) NULL) ;
  705.     else
  706.       bRet = GetSaveFileName(po) ;
  707.   }
  708.   /* Record the results */
  709.   wsprintf(szTemp, szLongFilter, CommDlgExtendedError()) ;
  710.   SetDlgItemText(hwndMainDialog, ID_ERRORO, szTemp) ;
  711.   wsprintf(szTemp, szShortFilter, (int) bRet) ;
  712.   SetDlgItemText(hwndMainDialog, ID_RETURNO, szTemp) ;
  713.   InterpretCustomFilterString() ;
  714.   FillOpenDlg(hwndMainDialog, po) ;
  715.   if (hDialog)
  716.   {
  717.     FreeResource(hDialog) ;    //free ofn.hInstance
  718.     hDialog = (HANDLE) 0 ;
  719.     hRes = (HANDLE) 0 ;
  720.   }
  721. }
  722. /************************************************************************
  723.   Function: OpenMultiThreadEnableButtons(BOOL, HWND)
  724.   Purpose:
  725.     Enable or disable the buttons that might affect the state of the
  726.     OPENFILENAME structures.  This is necessary because during a
  727.     multithreading session, these buttons may be accessible even though
  728.     there are Open dialogs still working and we don't want to change
  729.     the OPENFILENAME structure out from under them.
  730.   Returns: Nothing.
  731.   Comments:
  732. ************************************************************************/
  733. void OpenMultiThreadEnableButtons(BOOL bEnable, HWND hwnd)
  734. {
  735.   EnableWindow(GetDlgItem(hwnd, IDOK), bEnable) ;
  736.   EnableWindow(GetDlgItem(hwnd, IDCANCEL), bEnable) ;
  737.   EnableWindow(GetDlgItem(hwnd, ID_RESETOPEN), bEnable) ;
  738.   EnableWindow(GetDlgItem(hwnd, ID_MULTIOPEN), bEnable) ;
  739. }