home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / MCITEST / MCITEST.C_ / MCITEST.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  24.6 KB  |  828 lines

  1. /* mcitest.c - WinMain(), main dialog box and support code for MCITest.
  2.  *
  3.  * MCITest is a Windows with Multimedia sample application illustrating
  4.  * the use of the Media Control Interface (MCI). MCITest puts up a dialog
  5.  * box allowing you to enter and execute MCI string commands.
  6.  *
  7.  *    (C) Copyright Microsoft Corp. 1991.  All rights reserved.
  8.  *
  9.  *    You have a royalty-free right to use, modify, reproduce and 
  10.  *    distribute the Sample Files (and/or any modified version) in 
  11.  *    any way you find useful, provided that you agree that 
  12.  *    Microsoft has no warranty obligations or liability for any 
  13.  *    Sample Application Files which are modified. 
  14.  */
  15.  
  16. #include <windows.h>
  17. #include <mmsystem.h>
  18. #include "mcitest.h"
  19. #include "edit.h"
  20. #include "dlgopen.h"
  21.  
  22.  
  23. #define BUFFER_LENGTH 128
  24. #define SLASH(c)      ((c) == '/' || (c) == '\\')
  25.  
  26.  
  27. /* Global variables.
  28.  */
  29. static  int         nLastNumberOfDevices;
  30. static  HANDLE      hAccTable;
  31. static  HANDLE      hInstApp;
  32. static  HWND        hwndMainDlg;
  33. static  HWND        hwndEdit;
  34. static  HWND        hwndDevices;
  35. static  FARPROC     lpfnDevices;
  36. static  FARPROC     lpfnTester;
  37. static  char        aszMciFile[BUFFER_LENGTH];
  38. static  char        aszBuffer[BUFFER_LENGTH];
  39. static  char        aszExt[] = "*.mcs";
  40. static  char        aszAppName[] = "MCI Test";         
  41. static  char        aszMainTextFormat[] = "%ls - %ls";
  42. static  char        aszDeviceTextFormat[] = "Open MCI Devices(count=%d)";
  43. static  char        aszNULL[] = "";
  44. static  char        aszTRUE[] = "TRUE";
  45. static  char        aszFALSE[] = "FALSE";
  46. static  char        aszEOL[] = "\r\n";
  47. static  char        aszOpenFileTitle[] = "Open MCITest File";
  48. static  char        aszSaveFileTitle[] = "Save MCITest File";
  49. static  char        aszSaveFileControl[] = "Save File &Name";
  50. static  char        aszProfileSection[] = "extensions";
  51. static  char        aszProfileKey[] = "mcs";
  52. static  char        aszProfileSetting[] = "mcitest.exe ^.mcs";
  53.  
  54. /* AboutDlgProc - Dialog procedure function for ABOUTBOX.
  55.  *
  56.  * Params:  Standard window procedure parameters.
  57.  */
  58. BOOL FAR PASCAL __export AboutDlgProc(
  59.     HWND    hwndDlg,
  60.     unsigned    wMsg,
  61.     WORD    wParam,
  62.     LONG    lParam)
  63. {
  64.     switch (wMsg) {
  65.         case WM_COMMAND:
  66.             if (wParam == IDOK)
  67.                 EndDialog(hwndDlg, TRUE);
  68.             break;
  69.         case WM_INITDIALOG:
  70.             return TRUE;
  71.     }
  72.     return FALSE;
  73. }
  74.  
  75.  
  76. /* FileName - Takes the full pathname string and returns a pointer to 
  77.  *   the first character of the filename in the same string.
  78.  *
  79.  * Params:  szPath -  pointer to the full path\filename string
  80.  *
  81.  * Returns: a pointer to the first character of the filename in the string
  82.  */
  83. PSTR    PASCAL NEAR FileName(
  84.     PSTR    szPath)
  85. {
  86.     PSTR   szCurrent;
  87.  
  88.     /* Scan to the end of the string */
  89.  
  90.     for (szCurrent = szPath; *szCurrent; szCurrent++)
  91.         ;
  92.  
  93.     /*
  94.      * Now start scanning back towards the beginning of the string until
  95.      * a slash (\) character, colon, or start of the string is encountered.
  96.      */
  97.     for (; szCurrent >= szPath && !SLASH(*szCurrent) && *szCurrent != ':'; szCurrent--)
  98.         ;
  99.  
  100.     /* Now pointing to the char before the first char in the filename.
  101.      */
  102.     return ++szCurrent;
  103. }
  104.  
  105.  
  106. /* OpenMciFile - Opens the specified MCI file and updates the main window 
  107.  *   caption to display this file name along with the app name.
  108.  *
  109.  * Params:  hWndDlg - window handle of the main dialog window
  110.  *          lszFile - pointer to the string containing the filename of
  111.  *            file to be opened
  112.  *
  113.  * Returns: void
  114.  */
  115. void    PASCAL NEAR OpenMciFile(
  116.     HWND    hwndDlg,
  117.     LPSTR   lszFile)
  118. {
  119.     if (EditOpenFile(hwndEdit, lszFile)) {
  120.  
  121.         lstrcpy(aszMciFile, lszFile);
  122.         wsprintf(aszBuffer, aszMainTextFormat, (LPSTR)aszAppName,
  123.             (LPSTR)FileName(aszMciFile));
  124.         SetWindowText(hwndDlg, aszBuffer);
  125.     }
  126. }
  127.  
  128.  
  129. /* get_number_of_devices - Sends a command to MCI querying it as to how 
  130.  *   many devices are currently open in the system. It returns the value 
  131.  *   provided by MCI.
  132.  *
  133.  * Params:  void
  134.  *
  135.  * Returns: The number of MCI devices currently open.
  136.  *
  137.  */
  138. int PASCAL NEAR get_number_of_devices(
  139.     void)
  140.  
  141. {
  142.     MCI_SYSINFO_PARMS sysinfo;
  143.     DWORD dwDevices;
  144.  
  145.     /* Set things up so that MCI puts the number of open devices directly
  146.      * into <nDevices>.
  147.      */
  148.     sysinfo.lpstrReturn = (LPSTR)(LPDWORD)&dwDevices;
  149.     sysinfo.dwRetSize = sizeof(DWORD);
  150.  
  151.     /* Send MCI a command querying all devices in the system to see if they
  152.      * are open. If the command was successful, return the number provided by
  153.      * MCI. Otherwise, return 0.
  154.      */
  155.     if (mciSendCommand(MCI_ALL_DEVICE_ID, MCI_SYSINFO,
  156.                         MCI_SYSINFO_OPEN | MCI_SYSINFO_QUANTITY,
  157.                         (DWORD)(LPMCI_SYSINFO_PARMS)&sysinfo) != 0)
  158.         return 0;
  159.     else
  160.         return (int)dwDevices;
  161. }
  162.  
  163.  
  164. /* update_device_list - Updates the list of devices displayed in the 
  165.  *   Devices dialog.
  166.  *
  167.  * Params:  void
  168.  *
  169.  * Return:  void
  170.  */
  171. void    PASCAL NEAR update_device_list(
  172.     void)
  173.  
  174. {
  175.     MCI_SYSINFO_PARMS sysinfo;
  176.     HWND              hwndList;
  177.     char              aszBuf[256];
  178.     int               nDevices;
  179.     int               nCurrentDevice;
  180.  
  181.     /* If the Devices dialog is not present, then return.
  182.      */
  183.     if (hwndDevices == NULL)
  184.         return;
  185.  
  186.     /* Find out how many devices are currently open in the system.
  187.      */
  188.     nDevices = get_number_of_devices();
  189.  
  190.     /* Update the dialog caption appropriately.
  191.      */
  192.     wsprintf(aszBuf, aszDeviceTextFormat, nDevices);
  193.     SetWindowText(hwndDevices, aszBuf);
  194.  
  195.     /* Get a handle to the dialog's listbox, and prepare it for updating.
  196.      */
  197.     hwndList = GetDlgItem(hwndDevices, ID_DEVICE_LIST);
  198.     SendMessage(hwndList, LB_RESETCONTENT, 0, 0L);
  199.     SendMessage(hwndList, WM_SETREDRAW, FALSE, 0L);
  200.  
  201.     /* Get the name of each open device in the system, one device at a time.
  202.      * Add each device's name to the listbox.
  203.      */
  204.     for (nCurrentDevice = 1; nCurrentDevice <= nDevices; ++nCurrentDevice) {
  205.  
  206.         sysinfo.dwNumber = nCurrentDevice;
  207.         sysinfo.lpstrReturn = (LPSTR)&aszBuf;
  208.     sysinfo.dwRetSize = sizeof(aszBuf);
  209.  
  210.         /* If an error is encountered, skip to the next device.
  211.          */
  212.         if (mciSendCommand(MCI_ALL_DEVICE_ID, MCI_SYSINFO,
  213.                             MCI_SYSINFO_OPEN | MCI_SYSINFO_NAME,
  214.                             (DWORD)(LPMCI_SYSINFO_PARMS)&sysinfo) != 0)
  215.             continue;
  216.  
  217.         /* Redraw the list when all device names have been added.
  218.          */
  219.         if (nCurrentDevice == nDevices)
  220.             SendMessage(hwndList, WM_SETREDRAW, TRUE, 0L);
  221.  
  222.         /* Add the device name to the listbox.
  223.          */
  224.         SendMessage(hwndList, LB_ADDSTRING, 0, (LONG)(LPSTR)aszBuf);
  225.     }
  226.  
  227.     /* Remember the number of open devices found this time.
  228.      */
  229.     nLastNumberOfDevices = nDevices;
  230. }
  231.  
  232.  
  233. /* sendstring - Sends the specified string command to MCI via the MCI 
  234.  *   string interface. Any message returned by MCI is displayed
  235.  *   in the 'MCI output' box. Any error which may have occurred is 
  236.  *   displayed in the 'Error' box'.
  237.  *
  238.  * Params:  hwndDlg - window handle of the main dialog window
  239.  *          szBuffer - pointer to the string containing the string 
  240.  *             command to be executed
  241.  *
  242.  * Returns: MCI error number.
  243.  */
  244. DWORD   PASCAL NEAR sendstring(
  245.     HWND    hwndDlg,
  246.     PSTR    strBuffer)
  247. {
  248.     char    aszReturn[BUFFER_LENGTH];
  249.     DWORD   dwErr;
  250.  
  251.     /* Uncheck the notification buttons.
  252.      */
  253.     CheckDlgButton(hwndDlg, ID_NOT_SUCCESS, FALSE);
  254.     CheckDlgButton(hwndDlg, ID_NOT_SUPER, FALSE);
  255.     CheckDlgButton(hwndDlg, ID_NOT_ABORT, FALSE);
  256.     CheckDlgButton(hwndDlg, ID_NOT_FAIL, FALSE);
  257.  
  258.         /* Send the string command to MCI.
  259.          */
  260.         dwErr = mciSendString(strBuffer, aszReturn, sizeof(aszReturn), hwndDlg);
  261.  
  262.         /* Put the text message returned by MCI into the 'MCI Output' box.
  263.          */
  264.         SetDlgItemText(hwndDlg, ID_OUTPUT, aszReturn);
  265.  
  266.         /* Decode the error # returned by MCI, and display the string in the
  267.          * 'Error' box.
  268.          */
  269.         mciGetErrorString(dwErr, strBuffer, BUFFER_LENGTH);
  270.         SetDlgItemText(hwndDlg, ID_ERRORCODE, strBuffer);
  271.  
  272.     /* Update the internal list of currently open devices.
  273.      */
  274.     update_device_list();
  275.     return dwErr;
  276. }
  277.  
  278.  
  279. /* NDialog - Displays a dialog box and returns the exit code.
  280.  *   The function passed will have a proc instance made for it.
  281.  *
  282.  * Params:  id - resource ID of the dialog to be displayed
  283.  *          hwnd - parent window of the dialog
  284.  *          fpfn - dialog's message function
  285.  *
  286.  * Returns: exit code of the dialog (what was passed to EndDialog)
  287.  */
  288. int PASCAL NEAR NDialog(
  289.     int     id,
  290.     HWND    hwnd,
  291.     FARPROC lpfnDialog)
  292. {
  293.     int         nDialogReturn;
  294.     HANDLE      hInst;
  295.  
  296.     /* Get a handle to the window's instance, and use this to make a proc
  297.      * instance.
  298.      */
  299.     hInst = (HANDLE)GetWindowWord(hwnd, GWW_HINSTANCE);
  300.     lpfnDialog = MakeProcInstance(lpfnDialog, hInst);
  301.  
  302.     /* Create the dialog box and remember the return code when it exits.
  303.      */
  304.     nDialogReturn = DialogBox(hInst, MAKEINTRESOURCE(id), hwnd, (DLGPROC)lpfnDialog);
  305.  
  306.     /* Free up resources used by the dialog, and return the return code.
  307.      */
  308.     FreeProcInstance(lpfnDialog);
  309.     return nDialogReturn;
  310. }
  311.  
  312.  
  313. /* ErrDlgFunc - Callback function for the dialog box which occurs during 
  314.  *  the execution of an error in a loop of MCITEST commands. It displays 
  315.  *  Abort, Continue and Ignore buttons.
  316.  *
  317.  * Params:  standard window procedure parameters.
  318.  */
  319. BOOL FAR PASCAL __export ErrDlgFunc(
  320.     HWND    hwndDlg,
  321.     WORD    wMsg,
  322.     WORD    wParam,
  323.     LONG    lParam) 
  324. {
  325.     switch(wMsg) {
  326.  
  327.     case WM_INITDIALOG:
  328.         return TRUE;
  329.  
  330.     case WM_COMMAND:
  331.         switch(wParam) {            // button pushed
  332.         case IDABORT:
  333.         case IDOK:                      
  334.         case IDIGNORE:
  335.             EndDialog(hwndDlg, wParam); // just return button ID
  336.             break;
  337.         }
  338.         break;
  339.     }
  340.     return FALSE;
  341. }
  342.  
  343.  
  344. /* execute - Executes the MCI command which is currently selected in
  345.  *       the edit box. If <fStep> is true, then only this one line will be
  346.  *       executed. Otherwise, every line from the currently selected line to
  347.  *       the last line in the edit box will be executed sequentially.
  348.  *
  349.  * Params:  hwndDlg - window handle of the main dialog window
  350.  *          fSingleStep - flag indicating whether or not to work in 
  351.  *            'single step' mode
  352.  *
  353.  * Returns: void
  354.  */
  355. void    PASCAL NEAR execute(
  356.     HWND    hwndDlg,
  357.     BOOL    fSingleStep)
  358. {
  359.     int  iLine;                                
  360.     int  n = 0;
  361.     int  runcount;
  362.     int  count;
  363.     int  iLineStart;
  364.     BOOL fIgnoreErrors = FALSE;
  365.  
  366.     runcount = GetDlgItemInt(hwndDlg, ID_RUNCOUNT, NULL, TRUE);
  367.  
  368.     /* Go through this loop for every line in the edit box from the currently
  369.      * selected line to the last line, or a single line if in single step mode
  370.      */
  371.     iLineStart = EditGetCurLine(hwndEdit);
  372.     for (count = runcount; count--;) {
  373.         for (iLine = iLineStart;
  374.             EditGetLine(hwndEdit, iLine, aszBuffer, sizeof(aszBuffer));
  375.             iLine++) {
  376.  
  377.             /* If a comment line or a blank line, skip to the next line.
  378.              */
  379.             if (*aszBuffer == ';' || *aszBuffer == 0)
  380.                 continue;
  381.  
  382.             /* Select the line that is about to be processed.
  383.              */
  384.             EditSelectLine(hwndEdit, iLine);
  385.  
  386.             /* If in 'single step' mode and one line has already been 
  387.              * proccessed, then break out of the loop (and exit the routine).
  388.              */
  389.             if (fSingleStep && (++n == 2))
  390.                 break;
  391.  
  392.             /* Send the command on the current line to MCI via the string
  393.              * interface.
  394.              */
  395.             if (sendstring(hwndDlg, aszBuffer) && !fIgnoreErrors &&
  396.                 runcount > 1 && !fSingleStep) {
  397.                 int nRet;
  398.  
  399.                 nRet = NDialog(IDD_ERRORDLG, hwndDlg, (FARPROC)ErrDlgFunc);
  400.                 if (nRet == IDABORT)
  401.                     goto exit_fn;
  402.                 if (nRet == IDIGNORE)
  403.                     fIgnoreErrors = TRUE;
  404.             }
  405.         }
  406.         SetDlgItemInt(hwndDlg, ID_RUNCOUNT, count, TRUE);
  407.         if (fSingleStep)
  408.             break;
  409.     }
  410. exit_fn:
  411.     SetDlgItemInt(hwndDlg, ID_RUNCOUNT, runcount, TRUE);
  412. }
  413.  
  414.  
  415. /* devices - This function handles messages belonging to the 
  416.  *   "List of open devices" dialog box. The only message that it looks for 
  417.  *    is WM_COMMAND, indicating the user has pressed the "OK" button.  
  418.  *    When this happens, it takes down the dialog box.
  419.  *
  420.  * Params:  standard window procedure parameters
  421.  *
  422.  * Return:  TRUE if the message has been processed, else FALSE.
  423.  */
  424. BOOL FAR PASCAL __export devices(
  425.     HWND    hwndDlg,
  426.     WORD    wMsg,
  427.     WORD    wParam,
  428.     LONG    lParam)
  429. {
  430.     switch (wMsg) {
  431.  
  432.         case WM_COMMAND:
  433.  
  434.             switch (wParam) {
  435.  
  436.                 case ID_END_DEVICE_LIST:
  437.  
  438.                     hwndDevices = NULL;
  439.                     EndDialog(hwndDlg, TRUE);
  440.  
  441.                 break;
  442.             }
  443.  
  444.         break;
  445.     }
  446.  
  447.     return FALSE;
  448. }
  449.  
  450.  
  451. /* create_device_list - Creates the Devices dialog box and updates 
  452.  *   the list of open devices displayed in it.
  453.  *
  454.  * Params:  void
  455.  *
  456.  * Returns: void
  457.  */
  458. void    PASCAL NEAR create_device_list(
  459.     void)
  460.  
  461. {
  462.     /* Create the Devices dialog box.
  463.      */
  464.     if (lpfnDevices == NULL)
  465.         lpfnDevices = MakeProcInstance((FARPROC)devices, hInstApp);
  466.     hwndDevices = CreateDialog(hInstApp, MAKEINTRESOURCE(IDD_DEVICES),
  467.         hwndMainDlg, (DLGPROC)lpfnDevices);
  468.     if (hwndDevices == NULL)
  469.         return;
  470.  
  471.     /* Update the information displayed in the listbox.
  472.      */
  473.     update_device_list();
  474. }
  475.  
  476.  
  477. /* mcitester - This function is the main message handler for MCI test.
  478.  *  It handles messages from the pushbuttons, radio buttons, edit controls, 
  479.  *  menu system, etc. When it receives a WM_EXIT message, this routine tears
  480.  *  everything down and exits.
  481.  *
  482.  * Params:  standard window procedure paramters
  483.  *
  484.  * Returns: TRUE if the message has been processed, else FALSE
  485.  */
  486. BOOL FAR PASCAL __export mcitester(
  487.     HWND    hwndDlg,
  488.     WORD    wMsg,
  489.     WORD    wParam,
  490.     LONG    lParam)
  491. {
  492.     DWORD dw;
  493.     WORD  f;
  494.     BOOL  fSel;
  495.     WORD  wID;
  496.  
  497.     switch (wMsg) {
  498.  
  499.         case WM_COMMAND:
  500.  
  501.             switch (wParam) {
  502.  
  503.                 case IDOK:
  504.  
  505.                     /* When the OK button gets pressed, insert a CR LF into
  506.                      * the edit control. and execute the current line.
  507.                      */
  508.                     SetFocus(hwndEdit);
  509.                     f = EditGetCurLine(hwndEdit);
  510.                     execute(hwndDlg, TRUE);
  511.  
  512.                     EditSetCurLine(hwndEdit, f);
  513.  
  514.                     SendMessage(hwndEdit, WM_KEYDOWN, VK_END, 0L);
  515.                     SendMessage(hwndEdit, WM_KEYUP, VK_END, 0L);
  516.                     SendMessage(hwndEdit, EM_REPLACESEL, 0, (LONG)(LPSTR)aszEOL);
  517.  
  518.                 break;
  519.  
  520.                 case ID_GO:
  521.  
  522.                     /* When the GO! button gets pressed, execute every line
  523.                      * in the edit box starting with the first one.
  524.                      */
  525.                     EditSetCurLine(hwndEdit, 0);
  526.                     execute(hwndDlg, FALSE);
  527.                     
  528.                 break;
  529.  
  530.                 case ID_STEP:
  531.  
  532.                     /* When the STEP button gets pressed, execute the 
  533.                      * currently selected line in the edit box.
  534.                      */
  535.                     execute(hwndDlg, TRUE);
  536.                     
  537.                 break;
  538.  
  539.                 case MENU_EXIT:
  540.                 case ID_EXIT:
  541.                 case IDCANCEL:
  542.  
  543.                     /* If the user indicates that he/she wishes to exit the
  544.                      * application, then end the main dialog and post a
  545.                      * WM_QUIT message.
  546.                      */
  547.                     EndDialog(hwndDlg, TRUE);
  548.                     PostQuitMessage(0);
  549.                     hwndMainDlg = 0;
  550.                     
  551.                 break;
  552.  
  553.                 case MENU_ABOUT:
  554.  
  555.                     /* Show the 'About...' box.
  556.                      */
  557.                     NDialog(IDD_ABOUTBOX, hwndDlg, (FARPROC)AboutDlgProc);
  558.  
  559.                 break;
  560.  
  561.                 case WM_CLEAR:
  562.                 case WM_CUT:
  563.                 case WM_COPY:
  564.                 case WM_PASTE:
  565.                 case WM_UNDO:
  566.  
  567.                     /* Pass whatever edit message received to the edit box.
  568.                      */
  569.                     SendMessage(hwndEdit, wParam, 0, 0L);
  570.                     
  571.                 break;
  572.  
  573.                 case MENU_OPEN:
  574.  
  575.                     f = OpenFileDialog(hwndDlg, aszOpenFileTitle, aszExt,
  576.                         DLGOPEN_MUSTEXIST | OF_EXIST | OF_READ, NULL,
  577.                         aszBuffer, sizeof(aszBuffer));
  578.  
  579.                     /* If the user selected a valid file, then open it */
  580.  
  581.                     if ((int)f >= 0)
  582.                         OpenMciFile(hwndDlg, aszBuffer);
  583.  
  584.                 break;
  585.  
  586.                 case MENU_SAVE:
  587.  
  588.                     /* If a filename exists, then save the contents of the
  589.                      * edit box under that filename.
  590.                      */
  591.                     if (*aszMciFile) {
  592.  
  593.                         EditSaveFile(hwndEdit, aszMciFile);
  594.                         break;
  595.                     }
  596.  
  597.                 break;
  598.  
  599.                 case MENU_SAVEAS:
  600.  
  601.                     /* Open a 'File Open' dialog to allow the
  602.                      * user to spacify a filename to save under.
  603.                      */
  604.  
  605.                     *aszBuffer = (char)0;
  606.                     f = OpenFileDialog(hwndDlg, aszSaveFileTitle, aszExt,
  607.                         DLGOPEN_SAVE | OF_EXIST, aszSaveFileControl, aszBuffer,
  608.                         sizeof(aszBuffer));
  609.  
  610.                     /* If the user didn't hit Cancel, then he must have set a
  611.                      * filename, so save the contents of the edit box under
  612.                      * that filename.
  613.                      */
  614.                     if (f != DLGOPEN_CANCEL) {
  615.  
  616.                         EditSaveFile(hwndEdit, aszBuffer);
  617.                     }
  618.  
  619.                 break;
  620.  
  621.                 case MENU_DEVICES:
  622.  
  623.                     /* If the Devices dialog box doesn't already exist, then
  624.                      * create and display it.
  625.                      */
  626.                     if (hwndDevices == NULL)
  627.                         create_device_list();
  628.  
  629.                 break;
  630.             }
  631.         break;
  632.  
  633.         case WM_INITDIALOG:
  634.  
  635.             /* Do general initialization stuff.
  636.              */
  637.             hwndEdit = GetDlgItem(hwndDlg, ID_INPUT);
  638.  
  639.             SetMenu(hwndDlg, LoadMenu(hInstApp, MAKEINTRESOURCE(IDM_MCITEST)));
  640.  
  641.             CheckDlgButton(hwndDlg, ID_NOT_SUCCESS, FALSE);
  642.             CheckDlgButton(hwndDlg, ID_NOT_SUPER, FALSE);
  643.             CheckDlgButton(hwndDlg, ID_NOT_ABORT, FALSE);
  644.             CheckDlgButton(hwndDlg, ID_NOT_FAIL, FALSE);
  645.             SetDlgItemInt(hwndDlg, ID_RUNCOUNT, 1, TRUE);
  646.  
  647.             hAccTable = LoadAccelerators(hInstApp,
  648.                 MAKEINTRESOURCE(IDA_MCITEST));
  649.  
  650.         return TRUE;
  651.  
  652.         case WM_DESTROY:
  653.  
  654.             /* End the dialog and send a WM_QUIT message.
  655.              */
  656.             EndDialog(hwndDlg, TRUE);
  657.             PostQuitMessage(0);
  658.             hwndMainDlg = 0;
  659.             
  660.         break;
  661.  
  662.         case MM_MCINOTIFY:
  663.  
  664.             /* Check the radio button corresponding to the notification
  665.              * received.
  666.              */
  667.             wID = NULL;
  668.             switch (wParam) {
  669.  
  670.                 case MCI_NOTIFY_SUCCESSFUL:
  671.  
  672.                     wID = ID_NOT_SUCCESS;
  673.                 
  674.                 break;
  675.  
  676.                 case MCI_NOTIFY_SUPERSEDED:
  677.  
  678.                     wID = ID_NOT_SUPER;
  679.                 
  680.                 break;
  681.  
  682.                 case MCI_NOTIFY_ABORTED:
  683.  
  684.                     wID = ID_NOT_ABORT;
  685.                 
  686.                 break;
  687.  
  688.                 case MCI_NOTIFY_FAILURE:
  689.  
  690.                     wID = ID_NOT_FAIL;
  691.                 
  692.                 break;
  693.  
  694.                 default:
  695.                 break;
  696.             }
  697.  
  698.             if (wID) {
  699.  
  700.                 CheckDlgButton(hwndDlg, wID, TRUE);
  701.                 SetFocus(GetDlgItem(hwndDlg, ID_INPUT));
  702.             }
  703.  
  704.         break;
  705.  
  706.         case WM_INITMENUPOPUP:
  707.  
  708.             /* Enable the 'Save' option if a valid filename exists.
  709.              */
  710.             EnableMenuItem((HMENU)wParam, MENU_SAVE,
  711.                 *aszMciFile ? MF_ENABLED : MF_GRAYED);
  712.  
  713.             /* Find out if something is currently selected in the edit box.
  714.              */
  715.             dw = SendMessage(hwndEdit, EM_GETSEL, 0, 0L);
  716.             fSel = HIWORD(dw) != LOWORD(dw);
  717.  
  718.             /* Enable / disable the Edit menu options appropriately.
  719.              */
  720.             EnableMenuItem((HMENU)wParam, WM_UNDO,
  721.                 SendMessage(hwndEdit,EM_CANUNDO,0,0L) ? MF_ENABLED : MF_GRAYED);
  722.             EnableMenuItem((HMENU)wParam, WM_CUT, fSel ? MF_ENABLED : MF_GRAYED);
  723.             EnableMenuItem((HMENU)wParam, WM_COPY, fSel ? MF_ENABLED : MF_GRAYED);
  724.             EnableMenuItem((HMENU)wParam, WM_PASTE,
  725.                 IsClipboardFormatAvailable(CF_TEXT) ? MF_ENABLED : MF_GRAYED);
  726.             EnableMenuItem((HMENU)wParam, WM_CLEAR, fSel ? MF_ENABLED : MF_GRAYED);
  727.  
  728.         return 0L;
  729.     }
  730.  
  731.     return FALSE;
  732. }
  733.  
  734.  
  735. /* AppInit - This is called when the application is first loaded into memory.
  736.  *   It performs all initialization that doesn't need to be done once per
  737.  *   instance.
  738.  *
  739.  * Params:  hInstance - instance handle of current instance
  740.  *          hPrev - instance handle of previous instance
  741.  *          szCmdLine - string containing the command line arguments
  742.  *          nCmdShow - not really used at all
  743.  *
  744.  * Returns: TRUE if successful, FALSE if not
  745.  *
  746.  */
  747. BOOL    PASCAL NEAR AppInit(
  748.     HANDLE  hInst,
  749.     HANDLE  hPrev,
  750.     LPSTR   lszCmdLine,
  751.     WORD    nCmdShow)
  752.  
  753. {
  754.     /* Save the app's instance handle for use by the dialog boxes.
  755.      */
  756.     hInstApp = hInst;
  757.  
  758.     /* Put up the main dialog box.
  759.      */
  760.     lpfnTester = MakeProcInstance((FARPROC)mcitester, hInst);
  761.     hwndMainDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_MCITEST), NULL,
  762.         (DLGPROC)lpfnTester);
  763.  
  764.     /* Fix up WIN.INI if this is the first time run... 
  765.      */
  766.     if (!GetProfileString(aszProfileSection, aszProfileKey, aszNULL, aszBuffer, sizeof(aszBuffer)))
  767.         WriteProfileString(aszProfileSection, aszProfileKey, aszProfileSetting);
  768.  
  769.     /* If a command line argument was specified, assume it to be a filename
  770.      * and open that file.
  771.      */
  772.     if (lszCmdLine && *lszCmdLine)
  773.         OpenMciFile(hwndMainDlg, lszCmdLine);
  774.  
  775.     return TRUE;
  776. }
  777.  
  778.  
  779. /* WinMain - Entry point from Windows
  780.  *
  781.  * Params:  hInstance - instance handle of current instance
  782.  *          hPrev - instance handle of previous instance
  783.  *          szCmdLine - string containing the command line arguments
  784.  *          nCmdShow - not really used at all
  785.  *
  786.  * Returns: The exit code as specified in the WM_QUIT message.
  787.  */
  788. int PASCAL WinMain(
  789.     HINSTANCE  hInst,
  790.     HINSTANCE  hPrev,
  791.     LPSTR   lszCmdLine,
  792.     int     nCmdShow)
  793. {
  794.     MSG     msg;
  795.  
  796.     /* Call the initialization procedure.
  797.      */
  798.     if (!AppInit(hInst, hPrev, lszCmdLine, nCmdShow))
  799.         return FALSE;
  800.  
  801.  
  802.     /* Poll the event queue for messages.
  803.      */
  804.     while (GetMessage(&msg, NULL, 0, 0))  {
  805.  
  806.         /* If the Devices dialog is showing and the number of open devices has
  807.          * changed since last checked, then update the list of open devices.
  808.          */
  809.  
  810.         if (hwndDevices != 0 && get_number_of_devices() != nLastNumberOfDevices)
  811.             update_device_list();
  812.  
  813.         /* Main message processing.
  814.          */
  815.         if (hwndMainDlg &&
  816.             (TranslateAccelerator(hwndMainDlg, hAccTable, &msg) ||
  817.             IsDialogMessage(hwndMainDlg, &msg)))
  818.             continue;
  819.         TranslateMessage(&msg);
  820.         DispatchMessage(&msg);
  821.     }
  822.  
  823.     if (lpfnDevices != NULL)
  824.         FreeProcInstance(lpfnDevices);
  825.     FreeProcInstance(lpfnTester);
  826.     return msg.wParam;
  827. }
  828.