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

  1. /**************************************************************************
  2.  *
  3.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6.  *  PURPOSE.
  7.  *
  8.  *  Copyright (C) 1992 - 1997 Microsoft Corporation.  All Rights Reserved.
  9.  *
  10.  **************************************************************************/
  11. /*----------------------------------------------------------------------------*\
  12.  *
  13.  *  MCIPUZZLE:
  14.  *
  15.  *    Sample app showing the use of MCIWnd, installable draw procedure
  16.  *
  17.  *    MCIPUZZLE is an application that demonstrates the following:
  18.  *
  19.  *      - Using the MCIWnd window class to play MCI files.
  20.  *
  21.  *      - Using an installable draw procedure with MCIAVI
  22.  *
  23.  *      - Implementing a version of the classic "15" puzzle
  24.  *
  25.  *----------------------------------------------------------------------------*/
  26.  
  27. #define  STRICT
  28. #define INC_OLE2
  29. #include <windows.h>
  30. #include <windowsx.h>
  31. #include <commdlg.h>
  32. #include <mmsystem.h>
  33. #include <digitalv.h>
  34. #include <mciavi.h>
  35. #include <vfw.h>
  36.  
  37. #include "mcipuzzl.h"
  38. #include "puzzle.h"
  39. #include "puzzproc.h"
  40.  
  41. //---------------------------------------------------------------------------
  42.  
  43. #define BUFSIZE 260
  44. #define MCIPLAY_APP_CLASS "MCIPuzzle_App"
  45. #define MCIPLAY_DOC_CLASS MCIWND_WINDOW_CLASS
  46. typedef MCI_DGV_SETVIDEO_PARMS * LP_MCI_DGV;
  47.  
  48. /*-------------------------------------------------------------------------*\
  49. |                                                                          |
  50. |   g l o b a l   v a r i a b l e s                                        |
  51. |                                                                          |
  52. \*------------------------------------------------------------------------*/
  53.  
  54. static  HINSTANCE ghInstApp;            /* Instance handle */
  55. static  HACCEL    ghAccelApp;
  56. static  HWND      ghwndApp;             /* Handle to parent window */
  57. static  HWND      ghwndMCI;             /* Handle to MCI client window */
  58. static  char      gszBuffer[BUFSIZE];
  59. static  DWORD     gdwHook = 0L;
  60.  
  61. PUZZLE            gPuzzle;
  62.  
  63. //---------------------------------------------------------------------------
  64.  
  65. LRESULT CALLBACK AppWndProc(HWND, UINT, WPARAM, LPARAM);
  66. BOOL    CALLBACK AppAbout(HWND, UINT, WPARAM, LPARAM);
  67.  
  68. static BOOL AppInit(HINSTANCE, HINSTANCE, LPSTR, int);
  69. static BOOL FormatFilterString(UINT, LPSTR);
  70. static void MCI_OnCommand(HWND, int, HWND, UINT);
  71. static void MCI_OnInitMenuPopup(HWND, HMENU, int, BOOL);
  72. static void MCI_OnSize(HWND, UINT, int, int);
  73. static void MCI_OnParentNotify(HWND, UINT, HWND, int);
  74. static void Handle_NotifyMedia(HWND,WPARAM);
  75. static void Handle_NotifySize(HWND,WPARAM);
  76.  
  77. /*----------------------------------------------------------------------------*\
  78. |   AppAbout( hDlg, msg, wParam, lParam )                                      |
  79. |                                                                              |
  80. |   Description:                                                               |
  81. |       This function handles messages belonging to the "About" dialog box.    |
  82. |       The only message that it looks for is WM_COMMAND, indicating the user  |
  83. |       has pressed the "OK" button.  When this happens, it takes down         |
  84. |       the dialog box.                                                        |
  85. |                                                                              |
  86. |   Arguments:                                                                 |
  87. |       hDlg            window handle of about dialog window                   |
  88. |       msg             message number                                         |
  89. |       wParam          message-dependent                                      |
  90. |       lParam          message-dependent                                      |
  91. |                                                                              |
  92. |   Returns:                                                                   |
  93. |       TRUE if message has been processed, else FALSE                         |
  94. |                                                                              |
  95. \*----------------------------------------------------------------------------*/
  96. BOOL CALLBACK AppAbout(
  97. HWND hwnd,
  98. UINT msg,
  99. WPARAM wParam,
  100. LPARAM lParam)
  101. {
  102.         switch (msg) {
  103.                 case WM_COMMAND:
  104.                 EndDialog(hwnd,TRUE);
  105.                 return TRUE;
  106.         }
  107.         return FALSE;
  108. }
  109.  
  110. /*----------------------------------------------------------------------------*\
  111. |   AppInit ( hInstance, hPrevInstance )                                       |
  112. |                                                                              |
  113. |   Description:                                                               |
  114. |       This is called when the application is first loaded into               |
  115. |       memory.  It performs all initialization that doesn't need to be done   |
  116. |       once per instance.                                                     |
  117. |                                                                              |
  118. |   Arguments:                                                                 |
  119. |       hPrevInstance   instance handle of previous instance                   |
  120. |       hInstance       instance handle of current instance                    |
  121. |                                                                              |
  122. |   Returns:                                                                   |
  123. |       TRUE if successful, FALSE if not                                       |
  124. |                                                                              |
  125. \*----------------------------------------------------------------------------*/
  126. static BOOL AppInit(
  127. HINSTANCE hInst,
  128. HINSTANCE hPrev,
  129. LPSTR szCmd,
  130. int sw)
  131. {
  132.         WNDCLASS cls;
  133.         WORD wVer;
  134.         char szAppName[BUFSIZE];
  135.  
  136.         /* Save instance handle for DialogBox */
  137.         ghInstApp = hInst;
  138.  
  139.         LoadString( ghInstApp, IDS_APPNAME, szAppName, BUFSIZE );
  140.  
  141.         /* first let's make sure we are running on 1.1 */
  142.         wVer = HIWORD(VideoForWindowsVersion());
  143.         if (wVer < 0x010a){
  144.                 char szTitle[BUFSIZE];
  145.                 /* oops, we are too old, blow out of here */
  146.                 LoadString( ghInstApp, IDS_APPERR, szTitle, BUFSIZE );
  147.                 LoadString( ghInstApp, IDS_VFWTOOOLD, gszBuffer, BUFSIZE );
  148.                 MessageBeep(MB_ICONHAND);
  149.                 MessageBox(NULL, gszBuffer, szTitle, MB_OK|MB_ICONSTOP);
  150.                 return FALSE;
  151.         }
  152.  
  153.         ghAccelApp = LoadAccelerators(ghInstApp, "AppAccel");
  154.  
  155.         if (!hPrev) {
  156.                 cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
  157.                 cls.hIcon          = LoadIcon(hInst,"AppIcon");
  158.                 cls.lpszMenuName   = "AppMenu";
  159.                 cls.lpszClassName  = MCIPLAY_APP_CLASS;
  160.                 cls.hbrBackground  = (HBRUSH)COLOR_APPWORKSPACE+1;
  161.                 cls.hInstance      = hInst;
  162.                 cls.style          = 0;
  163.                 cls.lpfnWndProc    = (WNDPROC)AppWndProc;
  164.                 cls.cbClsExtra     = 0;
  165.                 cls.cbWndExtra     = 0;
  166.  
  167.                 if (!RegisterClass(&cls))
  168.                         return FALSE;
  169.         }
  170.  
  171.         ghwndApp = CreateWindow(
  172.                 MCIPLAY_APP_CLASS,
  173.                 szAppName,
  174.                 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  175.                 CW_USEDEFAULT,
  176.                 0,
  177.                 160,
  178.                 120,
  179.                 (HWND)NULL,       /* no parent */
  180.                 (HMENU)NULL,      /* use class menu */
  181.                 (HANDLE)hInst,     /* handle to window instance */
  182.                 (LPSTR)NULL);     /* no params to pass on */
  183.  
  184.         InitPuzzle(&gPuzzle, TRUE /* FALSE to not scramble */);
  185.  
  186.         /* Make window visible according to the way the app is activated */
  187.         ShowWindow(ghwndApp,sw);
  188.  
  189.         return TRUE;
  190. }
  191.  
  192. /*----------------------------------------------------------------------------*\
  193. |   WinMain( hInstance, hPrevInstance, lpszCmdLine, cmdShow )                  |
  194. |                                                                              |
  195. |   Description:                                                               |
  196. |       The main procedure for the App.  After initializing, it just goes      |
  197. |       into a message-processing loop until it gets a WM_QUIT message         |
  198. |       (meaning the app was closed).                                          |
  199. |                                                                              |
  200. |   Arguments:                                                                 |
  201. |       hInstance       instance handle of this instance of the app            |
  202. |       hPrevInstance   instance handle of previous instance, NULL if first    |
  203. |       lpszCmdLine     ->null-terminated command line                         |
  204. |       cmdShow         specifies how the window is initially displayed        |
  205. |                                                                              |
  206. |   Returns:                                                                   |
  207. |       The exit code as specified in the WM_QUIT message.                     |
  208. |                                                                              |
  209. \*----------------------------------------------------------------------------*/
  210. int PASCAL WinMain(
  211. HINSTANCE hInstance,
  212. HINSTANCE hPrevInstance,
  213. LPSTR szCmdLine,
  214. int sw)
  215. {
  216.         MSG msg;
  217.  
  218.         if (!AppInit(hInstance,hPrevInstance,szCmdLine,sw))
  219.                 return FALSE;
  220.  
  221.         //Polling messages from event queue
  222.         for (;;) {
  223.                 if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE)) {
  224.                         if (msg.message == WM_QUIT)
  225.                                 break;
  226.  
  227.                         if (ghAccelApp && ghwndApp && TranslateAccelerator(ghwndApp, ghAccelApp, &msg))
  228.                                 continue;
  229.  
  230.                         TranslateMessage(&msg);
  231.                         DispatchMessage(&msg);
  232.                         } else {
  233.                         // idle time here, DONT BE A PIG!
  234.                         WaitMessage();
  235.                 }
  236.         }
  237.         return msg.wParam;
  238. }
  239.  
  240.  
  241. //----------------------------------------------------------------------------
  242. // MCI_OnCommand - Handles WM_COMMAND
  243. //----------------------------------------------------------------------------
  244. static void MCI_OnCommand(
  245. HWND hwnd,
  246. int id,
  247. HWND hwndCtl,
  248. UINT codeNotify)
  249. {
  250.         switch(id) {
  251.                 case MENU_ABOUT:
  252.                 DialogBox(ghInstApp,MAKEINTRESOURCE(ABOUTBOX),hwnd,AppAbout);
  253.                 break;
  254.  
  255.                 case MENU_EXIT:
  256.                 PostMessage(hwnd,WM_CLOSE,0,0L);
  257.                 break;
  258.  
  259.                 case MENU_CLOSE:
  260.                 PostMessage(ghwndMCI, WM_CLOSE, 0, 0L);
  261.                 break;
  262.  
  263.                 case MENU_OPEN:
  264.                 {
  265.                         OPENFILENAME ofn;
  266.                         char szFileName[BUFSIZE];
  267.                         char szFilter[BUFSIZE];
  268.  
  269.                         FormatFilterString( IDS_FILTERSTRING, szFilter );
  270.  
  271.                         /* prompt user for file to open */
  272.                         ofn.lStructSize = sizeof(OPENFILENAME);
  273.                         ofn.hwndOwner = hwnd;
  274.                         ofn.hInstance = NULL;
  275.                         ofn.lpstrFilter = szFilter;
  276.                         ofn.lpstrCustomFilter = NULL;
  277.                         ofn.nMaxCustFilter = 0;
  278.                         ofn.nFilterIndex = 0;
  279.                         *szFileName = '\0';
  280.                         ofn.lpstrFile = szFileName;
  281.                         ofn.nMaxFile = BUFSIZE;
  282.                         ofn.lpstrFileTitle = NULL;
  283.                         ofn.nMaxFileTitle = 0;
  284.                         ofn.lpstrInitialDir = NULL;
  285.                         ofn.lpstrTitle = "Open";
  286.                         ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  287.                         ofn.nFileOffset = 0;
  288.                         ofn.nFileExtension = 0;
  289.                         ofn.lpstrDefExt = NULL;
  290.                         ofn.lCustData = 0;
  291.                         ofn.lpfnHook = NULL;
  292.                         ofn.lpTemplateName = NULL;
  293.  
  294.                         if (GetOpenFileName(&ofn)) {
  295.                                 MCIWndOpen(ghwndMCI, (LPARAM)(LPSTR)szFileName, 0);
  296.                                 InitPuzzle(&gPuzzle, TRUE /* FALSE to not scramble */);
  297.                         }
  298.                 }
  299.                 break;
  300.  
  301.  
  302.                 /* Movie Menu (for use by accelerators) */
  303.                 case IDM_PLAY:
  304.                         MCIWndPlay(ghwndMCI);
  305.                         break;
  306.  
  307.                 case IDM_RPLAY:
  308.                         MCIWndPlayReverse(ghwndMCI);
  309.                         break;
  310.  
  311.       // Solve or scramble the puzzle, as appropriate
  312.                 case IDM_SOLVE:
  313.                 case IDM_SCRAMBLE:
  314.                     InitPuzzle(&gPuzzle, id == IDM_SCRAMBLE);
  315.                     InvalidateRect(ghwndMCI, NULL, FALSE);
  316.                     break;
  317.         }
  318.         return;
  319. }
  320.  
  321. //----------------------------------------------------------------------------
  322. // MCI_OnSize - Handles WM_SIZE
  323. //----------------------------------------------------------------------------
  324. static void MCI_OnSize(
  325. HWND hwnd,
  326. UINT state,
  327. int cx,
  328. int cy)
  329. {
  330.     if (!IsIconic(hwnd)) {
  331.             MoveWindow(ghwndMCI,0,0,cx,cy,TRUE);
  332.         }
  333. }
  334. //----------------------------------------------------------------------------
  335. // MCI_OnParentNotify - Handles WM_PARENTNOTIFY
  336. //----------------------------------------------------------------------------
  337. static void MCI_OnParentNotify(
  338. HWND hwnd,
  339. UINT msg,
  340. HWND hwndChild,
  341. int idChild)
  342. {
  343.     if (msg == WM_LBUTTONDOWN && ghwndMCI) {
  344.         RECT    rc;
  345.         POINT   pt;
  346.  
  347.         pt.x = (int)LOWORD((DWORD)hwndChild);
  348.         pt.y = (int)HIWORD((DWORD)hwndChild);
  349.  
  350.         ClientToScreen(hwnd, &pt);
  351.  
  352.         MCIWndGetDest(ghwndMCI, &rc);
  353.  
  354.         if (rc.bottom != rc.top && rc.right != rc.left) {
  355.             ScreenToClient(ghwndMCI, &pt);
  356.  
  357.             ClickPuzzle(&gPuzzle,
  358.                     (pt.x - rc.left) * PSIZE / (rc.right - rc.left),
  359.                     (pt.y - rc.top) * PSIZE / (rc.bottom - rc.top));
  360.  
  361.             InvalidateRect(ghwndMCI, &rc, FALSE);
  362.         }
  363.     }
  364.     return;
  365. }
  366. /*----------------------------------------------------------------------------*\
  367. |   AppWndProc( hwnd, msg, wParam, lParam )                                    |
  368. |                                                                              |
  369. |   Description:                                                               |
  370. |       The window proc for the app's main (tiled) window.  This processes all |
  371. |       of the parent window's messages.                                       |
  372. |                                                                              |
  373. |   Arguments:                                                                 |
  374. |       hwnd            window handle for the parent window                    |
  375. |       msg             message number                                         |
  376. |       wParam          message-dependent                                      |
  377. |       lParam          message-dependent                                      |
  378. |                                                                              |
  379. |   Returns:                                                                   |
  380. |       0 if processed, nonzero if ignored                                     |
  381. |                                                                              |
  382. \*----------------------------------------------------------------------------*/
  383. LRESULT CALLBACK AppWndProc(
  384. HWND hwnd,
  385. UINT msg,
  386. WPARAM wParam,
  387. LPARAM lParam)
  388. {
  389.  
  390.     switch (msg) {
  391.        case WM_CREATE:
  392.                 ghwndMCI = MCIWndCreate(hwnd, ghInstApp, WS_CHILD | WS_VISIBLE |
  393.                         MCIWNDF_NOTIFYMEDIA | MCIWNDF_NOTIFYSIZE | MCIWNDF_NOMENU, 0);
  394.                 break;
  395.  
  396.         case WM_COMMAND:
  397.                 HANDLE_WM_COMMAND(hwnd, wParam, lParam, MCI_OnCommand);
  398.                 break;
  399.  
  400.         case WM_PALETTECHANGED:
  401.         case WM_QUERYNEWPALETTE:
  402.         case WM_ACTIVATE:
  403.                 // Forward palette-related messages through to the MCIWnd,
  404.                 // so it can do the right thing.
  405.                 if (ghwndMCI)
  406.                         return SendMessage(ghwndMCI, msg, wParam, lParam);
  407.                 break;
  408.  
  409.         case WM_SIZE:
  410.                 HANDLE_WM_SIZE(hwnd, wParam, lParam, MCI_OnSize);
  411.                 break;
  412.  
  413.         case WM_DESTROY:
  414.                 PostQuitMessage(0);
  415.                 return (0);
  416.                 break;
  417.  
  418.        case WM_PARENTNOTIFY:
  419.                 HANDLE_WM_PARENTNOTIFY(hwnd, wParam, lParam, MCI_OnParentNotify);
  420.                 break;
  421.  
  422.        case MCIWNDM_NOTIFYMEDIA:
  423.                 Handle_NotifyMedia(hwnd, wParam);
  424.                 break;
  425.  
  426.        case MCIWNDM_NOTIFYSIZE:
  427.                 Handle_NotifySize(hwnd, wParam);
  428.                 break;
  429.         }
  430.  
  431.         return DefWindowProc(hwnd,msg,wParam,lParam);
  432. }
  433.  
  434. /*--------------------------------------------------------------+
  435. | Handle_NotifyMedia                                            |
  436. |                                                               |
  437. +--------------------------------------------------------------*/
  438. static void Handle_NotifyMedia(
  439. HWND hwnd,
  440. WPARAM wParam)
  441. {
  442.         MCI_DGV_SETVIDEO_PARMS dgv;
  443.         DWORD dw;
  444.         UINT uDevice;
  445.  
  446.         if (ghwndMCI == 0)
  447.                 ghwndMCI = (HWND) wParam;
  448.  
  449.         if (!gdwHook)
  450.                 gdwHook = (DWORD)ICAVIDrawProc;
  451.  
  452.         dgv.dwValue = gdwHook;
  453.  
  454.         dgv.dwItem = MCI_AVI_SETVIDEO_DRAW_PROCEDURE;
  455.  
  456.         uDevice = MCIWndGetDeviceID(ghwndMCI);
  457.         if (uDevice) {
  458.                 dw = mciSendCommand(uDevice, MCI_SETVIDEO,
  459.                                MCI_DGV_SETVIDEO_ITEM | MCI_DGV_SETVIDEO_VALUE,
  460.                                (DWORD)(LP_MCI_DGV)&dgv);
  461.  
  462.                 if (dw != 0) {
  463.                         char szTitle[BUFSIZE];
  464.  
  465.                         LoadString( ghInstApp, IDS_APPERR, szTitle, BUFSIZE );
  466.                         LoadString( ghInstApp, IDS_MCIERROR, gszBuffer, BUFSIZE );
  467.  
  468.                         MessageBox(hwnd, gszBuffer, szTitle, MB_OK | MB_ICONHAND);
  469.                 }
  470.         }
  471.         return;
  472. }
  473.  
  474.  
  475. /*--------------------------------------------------------------+
  476. | Handle_NotifySize                                             |
  477. |                                                               |
  478. +--------------------------------------------------------------*/
  479. static void Handle_NotifySize(
  480. HWND hwnd,
  481. WPARAM wParam)
  482. {
  483.     RECT rc;
  484.  
  485.     if (!IsIconic(hwnd)) {
  486.             if (ghwndMCI == 0)
  487.                     ghwndMCI = (HWND) wParam;
  488.  
  489.             GetWindowRect(ghwndMCI, &rc);
  490.             AdjustWindowRect(&rc, GetWindowLong(hwnd, GWL_STYLE), TRUE);
  491.             SetWindowPos(hwnd, NULL, 0, 0, rc.right - rc.left,
  492.             rc.bottom - rc.top,
  493.                     SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
  494.     }
  495. }
  496. /*--------------------------------------------------------------+
  497. | FormatFilterString                                            |
  498. |                                                               |
  499. +--------------------------------------------------------------*/
  500. static BOOL FormatFilterString(
  501. UINT uID,
  502. LPSTR lpszString )
  503. {
  504.         int nLength, nCtr = 0;
  505.         char chWildCard;
  506.  
  507.         *lpszString = 0;
  508.  
  509.         nLength = LoadString( ghInstApp, uID, lpszString, BUFSIZE );
  510.  
  511.         chWildCard = lpszString[nLength-1];
  512.  
  513.         while( lpszString[nCtr] ) {
  514.                 if( lpszString[nCtr] == chWildCard )
  515.                         lpszString[nCtr] = 0;
  516.                 nCtr++;
  517.         }
  518.  
  519.         return TRUE;
  520. }
  521.