home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / video / langplay / langplay.c next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  24.4 KB  |  589 lines

  1. /*--------------------------------------------------------------------
  2. |
  3. | LangPlay.c - Sample Win app to play AVI movies using MCIWnd. Handles
  4. |       multiple language track movies and lets the
  5. |       user select the track to listen to at playback.
  6. |
  7. |
  8. +--------------------------------------------------------------------*/
  9. /**************************************************************************
  10.  *
  11.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  12.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  13.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  14.  *  PURPOSE.
  15.  *  Copyright (C) 1992 - 1997 Microsoft Corporation.  All Rights Reserved.
  16.  *
  17.  **************************************************************************/
  18. #define INC_OLE2
  19. #include <windows.h>
  20. #include <windowsx.h>
  21. #include <mmsystem.h>
  22. #include <commdlg.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <direct.h>
  26. #include <digitalv.h>
  27. #include <vfw.h>
  28. #include "langplay.h"
  29.  
  30.  
  31. /**************************************************************
  32. ************************ GLOBALS ******************************
  33. **************************************************************/
  34. /* AVI stuff to keep around */
  35. HWND hwndMovie;                 /* window handle of the movie */
  36. BOOL fMovieOpen = FALSE;        /* Open flag: TRUE == movie open, FALSE = none */
  37. HMENU hMenuBar = NULL;          /* menu bar handle */
  38. char szAppName [] = "LangPlay";
  39.  
  40. // struct for handling multi-language support
  41. typedef struct langs_tag {
  42.         WORD            wLangTag;       // language type tag
  43.         char            achName[64];    // stream name  (limited to 64 chars by AVIStreamInfo)
  44. } LANGS, FAR *LPLANGS;
  45.  
  46. #define         NOAUDIO         0       // no audio stream
  47. int             iCurLang;               // current language selected (0 == NONE)
  48.  
  49.  
  50. /* function declarations */
  51. long FAR PASCAL WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  52. void fileOpenMovie(HWND hWnd);
  53. void menubarUpdate(HWND hWnd);
  54. void titlebarUpdate(HWND hWnd, LPSTR lpstrMovie);
  55. BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  56.  
  57. /* language specific functions */
  58. BOOL enumLangs(HWND hwnd, LPSTR lpstrMovie);
  59. void buildLangMenu(HWND hwnd, LPLANGS lpLangs, DWORD dwLangs);
  60. void switchLang(HWND hWnd, int iLangStream);
  61.  
  62.  
  63. /********************************************************************
  64. ************************** FUNCTIONS ********************************
  65. ********************************************************************/
  66.  
  67.  
  68. /*--------------------------------------------------------------+
  69. | initApp - initialize the app overall.                         |
  70. |                                                               |
  71. | Returns the Window handle for the app on success, NULL if     |
  72. | there is a failure.                                           |
  73. |                                                               |
  74. +--------------------------------------------------------------*/
  75. HWND initApp(HINSTANCE hInstance, HINSTANCE hPrevInstance, int nCmdShow)
  76. {
  77.         HWND            hWnd;   /* window handle to return */
  78.         int             iWinHeight;
  79.         WORD    wVer;
  80.  
  81.         /* first let's make sure we are running on 1.1 */
  82.         wVer = HIWORD(VideoForWindowsVersion());
  83.         if (wVer < 0x010a){
  84.                 /* oops, we are too old, blow out of here */
  85.                 MessageBeep(MB_ICONHAND);
  86.                 MessageBox(NULL, "Video for Windows version is too old",
  87.                           "LangPlay Error", MB_OK|MB_ICONSTOP);
  88.                 return FALSE;
  89.         }
  90.  
  91.         if (!hPrevInstance){
  92.                 WNDCLASS    wndclass;
  93.  
  94.                 wndclass.style         = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  95.                 wndclass.lpfnWndProc   = WndProc;
  96.                 wndclass.cbClsExtra    = 0;
  97.                 wndclass.cbWndExtra    = 0;
  98.                 wndclass.hInstance     = hInstance;
  99.                 wndclass.hIcon         = LoadIcon (hInstance, "AppIcon");
  100.                 wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
  101.                 wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  102.                 wndclass.lpszMenuName  = szAppName;
  103.                 wndclass.lpszClassName = szAppName;
  104.  
  105.                 if (!RegisterClass(&wndclass)){
  106.                         MessageBox(NULL, "RegisterClass failure", szAppName, MB_OK);
  107.                         return NULL;
  108.                 }
  109.         }
  110.  
  111.         iWinHeight = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYMENU) +
  112.                         (GetSystemMetrics(SM_CYFRAME) * 2);
  113.  
  114.         /* create the main window for the app */
  115.         hWnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW |
  116.                 WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, 180, iWinHeight,
  117.                 NULL, NULL, hInstance, NULL);
  118.  
  119.         if (hWnd == NULL){
  120.                 MessageBox(NULL, "CreateWindow failure", szAppName, MB_OK);
  121.                 return NULL;
  122.         }
  123.  
  124.         hMenuBar = GetMenu(hWnd);       /* get the menu bar handle */
  125.         menubarUpdate(hWnd);            /* update menu bar to disable Movie menu */
  126.  
  127.         /* Show the main window */
  128.         ShowWindow(hWnd, nCmdShow);
  129.         UpdateWindow(hWnd);
  130.  
  131.         /* create the movie window using MCIWnd that has no file open initially */
  132.         hwndMovie = MCIWndCreate(hWnd, hInstance, WS_CHILD |WS_VISIBLE | MCIWNDF_NOOPEN |
  133.                                 MCIWNDF_NOERRORDLG | MCIWNDF_NOTIFYSIZE, NULL);
  134.  
  135.         if (!hwndMovie){
  136.                 /* we didn't get the movie window, destroy the app's window and bail out */
  137.                 DestroyWindow(hWnd);
  138.                 return NULL;
  139.         }
  140.         return hWnd;
  141. }
  142.  
  143.  
  144.  
  145.  
  146. /*--------------------------------------------------------------+
  147. | WinMain - main routine.                                       |
  148. |                                                               |
  149. +--------------------------------------------------------------*/
  150. int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  151.                                 LPSTR lpszCmdParam, int nCmdShow)
  152. {
  153.         HWND        hWnd;
  154.         MSG         msg;
  155.  
  156.         if ((hWnd = initApp(hInstance, hPrevInstance,nCmdShow)) == NULL)
  157.                 return 0;       /* died initializing, bail out */
  158.  
  159.         while (GetMessage(&msg, NULL, 0, 0)){
  160.                 TranslateMessage(&msg);
  161.                 DispatchMessage(&msg);
  162.         }
  163.         return msg.wParam;
  164. }
  165.  
  166.  
  167. /*--------------------------------------------------------------+
  168. | WndProc - window proc for the app                             |
  169. |                                                               |
  170. +--------------------------------------------------------------*/
  171. long FAR PASCAL WndProc (HWND hWnd, UINT message, WPARAM wParam,
  172.                                                 LPARAM lParam)
  173. {
  174.         PAINTSTRUCT ps;
  175.         WORD w;
  176.         WORD    wMenu;
  177.         RECT    rc;
  178.  
  179.         switch (message){
  180.                 case WM_CREATE:
  181.                         return 0;
  182.  
  183.                 case WM_INITMENUPOPUP:
  184.                         /* be sure this isn't the system menu */
  185.                         if (HIWORD(lParam))
  186.                                 return DefWindowProc(hWnd, WM_INITMENUPOPUP,
  187.                                                 wParam, lParam);
  188.  
  189.                         wMenu = LOWORD(lParam);
  190.                         switch (wMenu){
  191.                                 case 0:   /* file menu */
  192.                                         /* turn on/off CLOSE & PLAY */
  193.                                         if (fMovieOpen) w = MF_ENABLED|MF_BYCOMMAND;
  194.                                         else            w = MF_GRAYED|MF_BYCOMMAND;
  195.                                         EnableMenuItem((HMENU)wParam, IDM_CLOSE, w);
  196.                                         break;
  197.                         } /* switch */
  198.                         break;
  199.  
  200.                 case WM_COMMAND:
  201.                         if (wParam >= IDM_STREAM){
  202.                                 // the command is to switch the audio stream
  203.                                 switchLang(hWnd, wParam - IDM_STREAM + 1);
  204.                                 return 0;
  205.                         }
  206.                         /* handle the menu commands */
  207.                         switch (wParam) {
  208.                                 /* File Menu */
  209.                                 case IDM_OPEN:
  210.                                         fileOpenMovie(hWnd);
  211.                                         break;
  212.                                 case IDM_CLOSE:
  213.                                         fMovieOpen = FALSE;
  214.                                         MCIWndClose(hwndMovie);         // close the movie
  215.                                         ShowWindow(hwndMovie, SW_HIDE); //hide the window
  216.                                         menubarUpdate(hWnd);
  217.                                         titlebarUpdate(hWnd, NULL);     // title bar back to plain
  218.                                         break;
  219.                                 case IDM_EXIT:
  220.                                         PostMessage(hWnd, WM_CLOSE, 0, 0L);
  221.                                         break;
  222.  
  223.                                 /* audio menu */
  224.                                 case IDM_NONE:
  225.                                         switchLang(hWnd, NOAUDIO);
  226.                                         break;
  227.  
  228.                                 case IDM_ABOUT:
  229.                                         DialogBox((HANDLE)GetWindowInstance(hWnd),
  230.                                                   MAKEINTRESOURCE(IDD_ABOUT),
  231.                                                   hWnd,
  232.                                                   AboutDlgProc);
  233.                                         break;
  234.  
  235.                         }
  236.                         return 0;
  237.  
  238.                 case WM_PAINT:
  239.                         BeginPaint(hWnd, &ps);
  240.                         EndPaint(hWnd, &ps);
  241.                         return 0;
  242.  
  243.                 case WM_SIZE:
  244.                         if (!IsIconic(hWnd) && hwndMovie && fMovieOpen)
  245.                                 MoveWindow(hwndMovie,0,0,LOWORD(lParam),HIWORD(lParam),TRUE);
  246.                         break;
  247.  
  248.                 case WM_DESTROY:
  249.                         if (fMovieOpen)
  250.                                 MCIWndClose(hwndMovie);  // close an open movie
  251.                         MCIWndDestroy(hwndMovie);    // now destroy the MCIWnd window
  252.                         PostQuitMessage(0);
  253.                         return 0;
  254.  
  255.                 case MCIWNDM_NOTIFYSIZE:
  256.             if (!IsIconic(hWnd)) {
  257.                             if (fMovieOpen){
  258.                                 /* adjust to size of the movie window */
  259.                                 GetWindowRect(hwndMovie, &rc);
  260.                                 AdjustWindowRect(&rc, GetWindowLong(hWnd, GWL_STYLE), TRUE);
  261.                                 SetWindowPos(hWnd, NULL, 0, 0, rc.right - rc.left,
  262.                                         rc.bottom - rc.top,
  263.                                         SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
  264.                             } else {
  265.                                 /* movie closed, adjust to the default size */
  266.                                 int iWinHeight;
  267.  
  268.                                 iWinHeight = GetSystemMetrics(SM_CYCAPTION) +
  269.                                                 GetSystemMetrics(SM_CYMENU) +
  270.                                                 (GetSystemMetrics(SM_CYFRAME) * 2);
  271.                                 SetWindowPos(hWnd, NULL, 0, 0, 180, iWinHeight,
  272.                                         SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
  273.                 }
  274.                         }
  275.                         break;
  276.  
  277.                 case WM_ACTIVATE:
  278.                 case WM_QUERYNEWPALETTE:
  279.                 case WM_PALETTECHANGED:
  280.                         //
  281.                         // Forward palette-related messages through to the MCIWnd,
  282.                         // so it can do the right thing.
  283.                         //
  284.                         if (hwndMovie)
  285.                                 return SendMessage(hwndMovie, message, wParam, lParam);
  286.                         break;
  287.         } /* switch */
  288.         return DefWindowProc(hWnd, message, wParam, lParam);
  289. }
  290.  
  291. /*--------------------------------------------------------------+
  292. | menubarUpdate - update the menu bar based on the <fMovieOpen> |
  293. |                 flag value.  This will turn on/off the        |
  294. |                 Movie menu.                                   |
  295. |                                                               |
  296. +--------------------------------------------------------------*/
  297. void menubarUpdate(HWND hWnd)
  298. {
  299.         WORD w;
  300.  
  301.         if (fMovieOpen){
  302.                 w = MF_ENABLED|MF_BYPOSITION;
  303.         } else {
  304.                 w = MF_GRAYED|MF_BYPOSITION;
  305.         }
  306.         EnableMenuItem(hMenuBar, 1, w); /* change the Movie menu (#1) */
  307.         DrawMenuBar(hWnd);      /* re-draw the menu bar */
  308. }
  309.  
  310. /*--------------------------------------------------------------+
  311. | titlebarUpdate - update the title bar to include the name     |
  312. |                  of the movie playing.                        |
  313. |                                                               |
  314. +--------------------------------------------------------------*/
  315. void titlebarUpdate(HWND hWnd, LPSTR lpstrMovie)
  316. {
  317.         char achNewTitle[BUFFER_LENGTH];        // space for the title
  318.  
  319.         if (lpstrMovie != NULL)
  320.                 wsprintf((LPSTR)achNewTitle,"%s - %s", (LPSTR)szAppName,lpstrMovie);
  321.         else
  322.                 lstrcpy((LPSTR)achNewTitle, (LPSTR)szAppName);
  323.         SetWindowText(hWnd, (LPSTR)achNewTitle);
  324. }
  325.  
  326. /*--------------------------------------------------------------+
  327. | fileOpenMovie - open an AVI movie. Use CommDlg open box to    |
  328. |               open and then handle the initialization to      |
  329. |               show the movie and position it properly.  Keep  |
  330. |               the movie paused when opened.                   |
  331. |                                                               |
  332. |               Sets <fMovieOpened> on success.                 |
  333. +--------------------------------------------------------------*/
  334. void fileOpenMovie(HWND hWnd)
  335. {
  336.         OPENFILENAME ofn;
  337.  
  338.         static char szFile [BUFFER_LENGTH];
  339.         static char szFileTitle [BUFFER_LENGTH];
  340.  
  341.         /* use the OpenFile dialog to get the filename */
  342.         memset(&ofn, 0, sizeof(ofn));
  343.         ofn.lStructSize = sizeof(ofn);
  344.         ofn.hwndOwner = hWnd;
  345.         ofn.lpstrFilter = "Video for Windows\0*.avi\0\0";
  346.         ofn.lpstrFile = szFile;
  347.         ofn.nMaxFile = sizeof(szFile);
  348.         ofn.lpstrFileTitle = szFileTitle;
  349.         ofn.nMaxFileTitle = sizeof(szFileTitle);
  350.         ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  351.  
  352.         /* use CommDlg to get our filename */
  353.         if (GetOpenFileName(&ofn)){
  354.  
  355.                 /* we got a filename, now close any old movie and open */
  356.                 /* the new one.                                 */
  357.                 if (fMovieOpen)
  358.                         MCIWndClose(hwndMovie);
  359.  
  360.                 enumLangs(hWnd, ofn.lpstrFile); // find out the languages used in the file.
  361.  
  362.                 /* try to open the file */
  363.                 fMovieOpen = TRUE;              // assume the best
  364.                 if (MCIWndOpen(hwndMovie, ofn.lpstrFile, 0) == 0){
  365.                         /* we opened the file o.k., now set up to */
  366.                         /* play it.                                */
  367.                         ShowWindow(hwndMovie, SW_SHOW);
  368.                 } else {
  369.                         /* generic error for open */
  370.                         MessageBox(hWnd, "Unable to open Movie", NULL,
  371.                               MB_ICONEXCLAMATION|MB_OK);
  372.                         fMovieOpen = FALSE;
  373.                 }
  374.         }
  375.         /* update menu bar */
  376.         menubarUpdate(hWnd);
  377.         if (fMovieOpen)
  378.                 titlebarUpdate(hWnd, (LPSTR)ofn.lpstrFileTitle);
  379.         else
  380.                 titlebarUpdate(hWnd, NULL);
  381.  
  382.         /* cause an update to occur */
  383.         InvalidateRect(hWnd, NULL, FALSE);
  384.         UpdateWindow(hWnd);
  385. }
  386.  
  387.  
  388.  
  389. /*--------------------------------------------------------------+
  390. | enumLangs - enumerate the audio streams in a file and set up  |
  391. |             the global ghLangs as a handle to the array of    |
  392. |             language streams.                                 |                                                               |
  393. |                                                               |
  394. | To do this:                                                   |
  395. |       1. Open the file using AVIFileOpen().                   |
  396. |       2. Open all Audio Streams, getting the pavi for it      |
  397. |       3. Get the stream info on all audio streams to get names|
  398. |       4. If names don't exist use "Audio Strean n"            |
  399. |       5. Close the file                                       |
  400. |       6. Build the audio stream menu                          |
  401. |                                                               |
  402. | Return TRUE if successfully set up menu, FALSE on any error   |
  403. |                                                               |
  404. +--------------------------------------------------------------*/
  405. BOOL enumLangs(HWND hWnd, LPSTR lpstrMovie)
  406. {
  407.         PAVIFILE        pFile;
  408.         PAVISTREAM      pStream;
  409.         AVIFILEINFO aviInfo;
  410.         AVISTREAMINFO aviStream;
  411.         DWORD           dwNumStreams;
  412.         DWORD           dwNumAudioStreams = 0L;
  413.         LPLANGS         lpLangs;
  414.         LPLANGS         lpLang;
  415.         HANDLE          hLangs;
  416.  
  417.         DWORD           dw;
  418.  
  419.  
  420.         AVIFileInit();
  421.  
  422.         // go open the file
  423.         if (AVIFileOpen((PAVIFILE far *)&pFile, lpstrMovie, OF_READ, NULL) != 0)
  424.                 return FALSE;
  425.  
  426.         // get the file information
  427.         AVIFileInfo(pFile, (LPAVIFILEINFO)&aviInfo, sizeof(aviInfo));
  428.         dwNumStreams = aviInfo.dwStreams;               // grab the number of streams
  429.  
  430.         // loop through the streams and find the # of audio streams
  431.         for (dw = 0L; dw < dwNumStreams; dw++){
  432.                 AVIFileGetStream(pFile, (PAVISTREAM far *)&pStream, 0, dw);
  433.                 AVIStreamInfo(pStream, (LPAVISTREAMINFO)&aviStream, sizeof(aviStream));
  434.                 if (aviStream.fccType == streamtypeAUDIO)
  435.                         dwNumAudioStreams++;
  436.                 AVIStreamClose(pStream);
  437.  
  438.         }
  439.  
  440.         // we now know how many audio streams we are dealing with, we need to allocate
  441.         // enough memory for the Langs array and then get all the audio stream information
  442.         // again.
  443.         hLangs = GlobalAlloc(GHND, (sizeof(LANGS) *  dwNumAudioStreams));
  444.         if (hLangs == NULL)
  445.                 return FALSE;
  446.  
  447.         lpLangs = (LPLANGS)GlobalLock(hLangs);  // get the memory
  448.  
  449.         // loop through the audio streams and fill out the array
  450.         for (dw = 0L, lpLang = lpLangs; dw < dwNumAudioStreams; dw++, lpLang++) {
  451.                 AVIFileGetStream(pFile, (PAVISTREAM far *)&pStream, streamtypeAUDIO, dw);
  452.                 AVIStreamInfo(pStream, (LPAVISTREAMINFO)&aviStream, sizeof(aviStream));
  453.                 if (aviStream.szName && *aviStream.szName != '\0')
  454.                         lstrcpy((LPSTR)lpLang->achName, (LPSTR)aviStream.szName);
  455.                 else
  456.                         wsprintf((LPSTR)lpLang->achName, "Audio Stream %lu",dw);
  457.                 AVIStreamClose(pStream);
  458.  
  459.         }
  460.  
  461.         // now build the menu for this
  462.         buildLangMenu(hWnd, lpLangs, dwNumAudioStreams);
  463.  
  464.         // close up and deallocate resources
  465.         AVIFileClose(pFile);
  466.         AVIFileExit();
  467.  
  468.         GlobalUnlock(hLangs);
  469.         GlobalFree(hLangs);
  470.  
  471.         return TRUE;
  472. }
  473.  
  474.  
  475. /*--------------------------------------------------------------+
  476. | buildLangMenu - build up the language menu for the audio      |
  477. |                                 streams available.            |
  478. |                                                               |
  479. | hwnd is the main application window handle                    |
  480. | lang points to an array of LANGSTRUCT entries already filled  |
  481. |      in by the caller.                                        |
  482. +--------------------------------------------------------------*/
  483. void buildLangMenu(HWND hwnd, LPLANGS lpLangs, DWORD dwLangs)
  484. {
  485.         UINT    i;
  486.         HMENU   hMenu;
  487.         LPLANGS lplang;
  488.         UINT    uNumMenus;
  489.  
  490.         // go through menu chain and get the Audio Stream pop-up menu
  491.         hMenu = GetMenu(hwnd);                  // get the menu bar
  492.         hMenu = GetSubMenu(hMenu, 1);   // get the Audio Stream menu
  493.  
  494.         uNumMenus = GetMenuItemCount(hMenu);    // how many items are on this menu?
  495.         if (uNumMenus > 1){
  496.                 // we've got a menu with items already, time to delete all of them
  497.                 // except for the first one (NONE).  NOTE: Item 0 == first item
  498.                 // be sure to delete in reverse order so you get them all.
  499.                 for ( --uNumMenus; uNumMenus; uNumMenus--) {
  500.                         DeleteMenu(hMenu, uNumMenus, MF_BYPOSITION);
  501.                 }
  502.         }
  503.  
  504.         // loop through the languages and add menus to the existing menu
  505.         for (i=0, lplang = lpLangs; i<dwLangs; i++, lplang++){
  506.                 AppendMenu(hMenu, MF_ENABLED | MF_STRING, IDM_STREAM+i, lplang->achName);
  507.         }
  508.  
  509.         // get default set up
  510.         if (dwLangs)
  511.                 iCurLang = 1;           // use first audio stream
  512.         else
  513.                 iCurLang = NOAUDIO;     // else none
  514.  
  515.         /* set up the checkmark initially */
  516.         CheckMenuItem(hMenu, (iCurLang), MF_BYPOSITION | MF_CHECKED);
  517. }
  518.  
  519.  
  520. /*------------------------------------------------------------------+
  521. | switchLang - switch audio stream playback                                                     |
  522. |                                                                                                                                       |
  523. | iLangStream == the audio stream to switch to (-1 == NONE)                     |
  524. | Be sure to update iCurrLang global to be the current audio stream     |
  525. | selected.                                                                                                                     |
  526. |                                                                                                                                       |
  527. +------------------------------------------------------------------*/
  528. void switchLang(HWND hWnd, int iLangStream)
  529. {
  530.         HMENU                                   hMenu;
  531.         char                                    achStrBuff[256];
  532.  
  533.  
  534.         // if user just picked the same stream then just get out of here
  535.         if (iCurLang == iLangStream)
  536.                 return;
  537.  
  538.         // go through menu chain and get the Audio Stream pop-up menu
  539.         hMenu = GetMenu(hWnd);          // get the menu bar
  540.         hMenu = GetSubMenu(hMenu, 1);   // get the Audio Stream menu
  541.  
  542.         // turn off the checkmark from the old item
  543.         CheckMenuItem(hMenu, (iCurLang), MF_BYPOSITION | MF_UNCHECKED);
  544.  
  545.         // turn on the checkmark on the new item
  546.         CheckMenuItem(hMenu, (iLangStream), MF_BYPOSITION | MF_CHECKED);
  547.  
  548.         if (iLangStream == NOAUDIO){
  549.                 // turn off all audio
  550.                 MCIWndSendString(hwndMovie, "setaudio off");
  551.         } else {
  552.                 // turn on audio & the specific stream
  553.                 wsprintf(achStrBuff, "setaudio stream to %d", iLangStream);
  554.  
  555.                 // send the command
  556.                 MCIWndSendString(hwndMovie, achStrBuff);
  557.  
  558.  
  559.                 if (iCurLang == NOAUDIO){
  560.                         // audio was off, turn it on
  561.                         MCIWndSendString(hwndMovie, "setaudio on");
  562.                 }
  563.         }
  564.  
  565.         iCurLang = iLangStream;         // set the current stream
  566. }
  567.  
  568. /* AboutDlgProc()
  569.  *
  570.  * Dialog Procedure for the "about" dialog box.
  571.  *
  572.  */
  573.  
  574. BOOL CALLBACK AboutDlgProc(
  575.         HWND    hwnd,
  576.         UINT    msg,
  577.         WPARAM  wParam,
  578.         LPARAM  lParam)
  579. {
  580.         switch (msg) {
  581.         case WM_COMMAND:
  582.                 EndDialog(hwnd, TRUE);
  583.                 return TRUE;
  584.         case WM_INITDIALOG:
  585.                 return TRUE;
  586.         }
  587.         return FALSE;
  588. }
  589.