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 / captest / captest.c next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  30.4 KB  |  847 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.  *   captest.c: Source Code for the CapTest Sample Program
  14.  *
  15.  *   Microsoft Video for Windows Capture Class Sample Program
  16.  *
  17.  ***************************************************************************/
  18.  
  19.  
  20. #define ENABLE_ERROR_CALLBACK           1
  21. #define ENABLE_STATUS_CALLBACK          1
  22. #define ENABLE_VIDEOFRAME_CALLBACKS     0
  23.  
  24. #define INC_OLE2
  25. #include <windows.h>
  26. #include <windowsx.h>
  27. #include <commdlg.h>
  28. #include <vfw.h>
  29. #include <mmreg.h>
  30. #include <io.h>
  31. #include <fcntl.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <memory.h>
  35. #include <dos.h>
  36.  
  37. #include "captest.h"
  38.  
  39. //
  40. // Global Variables
  41. //
  42. TCHAR           gachAppName[]  = TEXT("CapTestApp") ;
  43. TCHAR           gachIconName[] = TEXT("CapTestIcon") ;
  44. TCHAR           gachMenuName[] = TEXT("CapTestMenu") ;
  45. TCHAR           gachMCIDeviceName[21] = TEXT("VideoDisc") ;  // default MCI device
  46. TCHAR           gachString[128] ;
  47. TCHAR           gachBuffer[200] ;
  48.  
  49. HINSTANCE      ghInstApp ;
  50. HWND           ghWndMain ;
  51. HWND           ghWndCap ;
  52. HANDLE         ghAccel ;
  53. WORD           gwDeviceIndex ;
  54. WORD           gwPalFrames = DEF_PALNUMFRAMES ;
  55. WORD           gwPalColors = DEF_PALNUMCOLORS ;
  56. WORD           gwCapFileSize ;
  57. DWORD          gdwFrameNum ;
  58. DWORD          gdwVideoNum ;
  59.  
  60. CAPSTATUS      gCapStatus ;
  61. CAPDRIVERCAPS  gCapDriverCaps ;
  62. CAPTUREPARMS   gCapParms ;
  63.  
  64. LPWAVEFORMATEX glpwfex ;
  65.  
  66. // MakeProcInstance is only required for 16-bit apps
  67. #ifndef WIN32
  68.  FARPROC        fpErrorCallback;
  69.  FARPROC        fpStatusCallback;
  70.  FARPROC        fpFrameCallback;
  71.  FARPROC        fpVideoCallback;
  72. #endif
  73.  
  74. // Function prototypes
  75. //
  76. LONG FAR PASCAL MainWndProc(HWND, UINT, UINT, LONG) ;
  77. LRESULT FNWCALLBACK ErrorCallbackProc(HWND, int, LPTSTR) ;
  78. LRESULT FNWCALLBACK StatusCallbackProc(HWND, int, LPTSTR) ;
  79. LRESULT FNWCALLBACK FrameCallbackProc(HWND, LPVIDEOHDR) ;
  80. LRESULT FNWCALLBACK VideoCallbackProc(HWND, LPVIDEOHDR) ;
  81.  
  82. //
  83. // WinMain: Application Entry Point Function
  84. //
  85. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  86. {
  87. ///////////////////////////////////////////////////////////////////////
  88. //  hInstance:      handle for this instance
  89. //  hPrevInstance:  handle for possible previous instances
  90. //  lpszCmdLine:    long pointer to exec command line
  91. //  nCmdShow:       Show code for main window display
  92. ///////////////////////////////////////////////////////////////////////
  93.  
  94.     MSG          msg ;
  95.     WNDCLASS     wc ;
  96.  
  97.     ghInstApp = hInstance ;
  98.     if (! hPrevInstance) {
  99.         // If it's the first instance, register the window class
  100.         wc.lpszClassName = gachAppName ;
  101.         wc.hInstance     = hInstance ;
  102.         wc.lpfnWndProc   = MainWndProc ;
  103.         wc.hCursor       = LoadCursor(NULL, IDC_ARROW) ;
  104.         wc.hIcon         = LoadIcon(hInstance, gachIconName) ;
  105.         wc.lpszMenuName  = gachMenuName ;
  106.         wc.hbrBackground = GetStockObject(WHITE_BRUSH) ;
  107.         wc.style         = CS_HREDRAW | CS_VREDRAW ;
  108.         wc.cbClsExtra    = 0 ;
  109.         wc.cbWndExtra    = 0 ;
  110.  
  111.         if (! RegisterClass(&wc)) {
  112.             LoadString(ghInstApp, IDS_ERR_REGISTER_CLASS, gachString, sizeof(gachString)/sizeof(TCHAR)) ;
  113.             MessageBox(NULL, gachString, NULL,
  114. #ifdef BIDI
  115.                 MB_RTL_READING |
  116. #endif
  117.  
  118.             MB_ICONEXCLAMATION) ;
  119.             return 0 ;
  120.         }
  121.     }
  122.  
  123.     // Create Application's Main window
  124.     ghWndMain =
  125. #ifdef BIDI
  126.  
  127. //
  128. // unfortunately you can't just #ifdef the CreateWindow line and leave
  129. // the parameters common: on Win32, CreateWindow is a macro and does not
  130. // expand correctly if you ifdef only the 'CreateWindow(' line.
  131. //
  132.         CreateWindowEx(WS_EX_BIDI_SCROLL |  WS_EX_BIDI_MENU |WS_EX_BIDI_NOICON,
  133.                              gachAppName,
  134.                              TEXT("Capture Test App"),
  135.                              WS_CAPTION      |
  136.                              WS_SYSMENU      |
  137.                              WS_MINIMIZEBOX  |
  138.                              WS_MAXIMIZEBOX  |
  139.                              WS_THICKFRAME   |
  140.                              WS_CLIPCHILDREN |
  141.                              WS_OVERLAPPED,
  142.                              CW_USEDEFAULT, 0,
  143.                              320, 240,
  144.                              NULL,
  145.                              NULL,
  146.                              ghInstApp,
  147.                              NULL) ;
  148. #else
  149.         CreateWindow (
  150.                              gachAppName,
  151.                              TEXT("Capture Test App"),
  152.                              WS_CAPTION      |
  153.                              WS_SYSMENU      |
  154.                              WS_MINIMIZEBOX  |
  155.                              WS_MAXIMIZEBOX  |
  156.                              WS_THICKFRAME   |
  157.                              WS_CLIPCHILDREN |
  158.                              WS_OVERLAPPED,
  159.                              CW_USEDEFAULT, 0,
  160.                              320, 240,
  161.                              NULL,
  162.                              NULL,
  163.                              ghInstApp,
  164.                              NULL) ;
  165. #endif
  166.  
  167.     if (ghWndMain == NULL) {
  168.         LoadString(ghInstApp, IDS_ERR_CREATE_WINDOW, gachString, sizeof(gachString)/sizeof(TCHAR)) ;
  169.         MessageBox(NULL, gachString, NULL,
  170. #ifdef BIDI
  171.                 MB_RTL_READING |
  172. #endif
  173.  
  174.         MB_ICONEXCLAMATION | MB_OK) ;
  175.         return IDS_ERR_CREATE_WINDOW ;
  176.     }
  177.  
  178.     ShowWindow(ghWndMain, nCmdShow) ;
  179.     UpdateWindow(ghWndMain) ;
  180.     ghAccel = LoadAccelerators(ghInstApp, gachAppName) ;
  181.  
  182.     // All set; get and process messages
  183.     while (GetMessage(&msg, NULL, 0, 0)) {
  184.         if (! TranslateAccelerator(ghWndMain, ghAccel, &msg)) {
  185.             TranslateMessage(&msg) ;
  186.             DispatchMessage(&msg) ;
  187.         }
  188.     }
  189.  
  190.     return msg.wParam ;
  191. }  // End of WinMain
  192.  
  193.  
  194. //
  195. // ErrorCallbackProc: Error Callback Function
  196. //
  197. LRESULT FNWCALLBACK ErrorCallbackProc(HWND hWnd, int nErrID, LPTSTR lpErrorText)
  198. {
  199. ////////////////////////////////////////////////////////////////////////
  200. //  hWnd:          Application main window handle
  201. //  nErrID:        Error code for the encountered error
  202. //  lpErrorText:   Error text string for the encountered error
  203. ////////////////////////////////////////////////////////////////////////
  204.  
  205.     if (!ghWndMain)
  206.         return FALSE;
  207.  
  208.     if (nErrID == 0)            // Starting a new major function
  209.         return TRUE;            // Clear out old errors...
  210.  
  211.     // Show the error ID and text
  212.     wsprintf(gachBuffer, TEXT("Error# %d"), nErrID) ;
  213.  
  214.     MessageBox(hWnd, lpErrorText, gachBuffer,
  215. #ifdef BIDI
  216.                 MB_RTL_READING |
  217. #endif
  218.                 MB_OK | MB_ICONEXCLAMATION) ;
  219.  
  220.     return (LRESULT) TRUE ;
  221. }
  222.  
  223.  
  224. //
  225. // StatusCallbackProc: Status Callback Function
  226. //
  227. LRESULT FNWCALLBACK StatusCallbackProc(HWND hWnd, int nID, LPTSTR lpStatusText)
  228. {
  229. ////////////////////////////////////////////////////////////////////////
  230. //  hWnd:           Application main window handle
  231. //  nID:            Status code for the current status
  232. //  lpStatusText:   Status text string for the current status
  233. ////////////////////////////////////////////////////////////////////////
  234.  
  235.     if (!ghWndMain)
  236.         return FALSE;
  237.  
  238.     if (nID == 0) {              // Zero means clear old status messages
  239.         SetWindowText(ghWndMain, (LPTSTR) gachAppName) ;
  240.         return (LRESULT) TRUE ;
  241.     }
  242.  
  243.     // Show the status ID and status text...
  244.     wsprintf(gachBuffer, TEXT("Status# %d: %s"), nID, lpStatusText) ;
  245.  
  246.         SetWindowText(ghWndMain, (LPTSTR)gachBuffer) ;
  247.  
  248.     return (LRESULT) TRUE ;
  249. }
  250.  
  251.  
  252. //
  253. // FrameCallbackProc: Frame Callback Function
  254. // Called whenever a new frame is captured but not streaming
  255. //
  256. LRESULT FNWCALLBACK FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
  257. {
  258. ////////////////////////////////////////////////////////////////////////
  259. //  hWnd:       Application main window handle
  260. //  lpVHdr:     long pointer to VideoHdr struct containing captured
  261. //              frame information
  262. ////////////////////////////////////////////////////////////////////////
  263.  
  264.     if (!ghWndMain)
  265.         return FALSE;
  266.  
  267.     wsprintf(gachBuffer, TEXT("Preview frame# %ld "), gdwFrameNum++) ;
  268.  
  269.     SetWindowText(ghWndMain, (LPTSTR)gachBuffer) ;
  270.     return (LRESULT) TRUE ;
  271. }
  272.  
  273.  
  274. //
  275. // VideoCallbackProc: Video Stream Callback Function
  276. // Called whenever a new frame is captured while streaming
  277. //
  278. LRESULT FNWCALLBACK VideoCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
  279. {
  280. ////////////////////////////////////////////////////////////////////////
  281. //  hWnd:       Application main window handle
  282. //  lpVHdr:     long pointer to VideoHdr struct containing captured
  283. //              frame information
  284. ////////////////////////////////////////////////////////////////////////
  285.  
  286.     gdwVideoNum++;      // Testing:  just count the callbacks
  287.  
  288.     return (LRESULT) TRUE ;
  289. }
  290.  
  291.  
  292. //
  293. // CenterCaptureWindow: Placess Capture Window at the Center of Main Window
  294. //
  295. static void CenterCaptureWindow(HWND hWndM, HWND hWndC)
  296. {
  297. ////////////////////////////////////////////////////////////////////////
  298. //  hWndM:      Application main window handle
  299. //  hWndC:      Capture window handle
  300. ////////////////////////////////////////////////////////////////////////
  301.  
  302.     RECT       MainRect ;
  303.     RECT       CapRect ;
  304.     WORD       wCapXPos ;
  305.     WORD       wCapYPos ;
  306.  
  307.     // Get the sizes of main and capture windows and
  308.     // calculate the location for centering
  309.     GetClientRect(hWndM, &MainRect) ;
  310.     GetClientRect(hWndC, &CapRect) ;
  311.     wCapXPos = max(0, (Width(MainRect) - Width(CapRect)) / 2) ;
  312.     wCapYPos = max(0, (Height(MainRect) - Height(CapRect)) / 2) ;
  313.  
  314.     // Position the capture window at the required location
  315.     MoveWindow(hWndC, wCapXPos, wCapYPos, Width(CapRect),
  316.                Height(CapRect), TRUE) ;
  317. }
  318.  
  319.  
  320. //
  321. // StartNewVideoChannel: Gets Selected Driver's Caps -- Updates menu,
  322. //                       Checks Image Size -- Resizes display window,
  323. //                       Enables Preview (at 15 FPS rate)
  324. //
  325. static void StartNewVideoChannel(HWND hWndM, HWND hWndC, WORD wIndex)
  326. {
  327. ////////////////////////////////////////////////////////////////////////
  328. //  hWndM:      Application main window handle
  329. //  hWndC:      Capture window handle
  330. //  wIndex:     Selected capture driver index
  331. ////////////////////////////////////////////////////////////////////////
  332.  
  333.     HMENU       hMenu = GetMenu(hWndM) ;
  334.  
  335.     // Get capture driver settings and update menu
  336.     capDriverGetCaps(hWndC, &gCapDriverCaps, sizeof(CAPDRIVERCAPS)) ;
  337.     EnableMenuItem(hMenu, IDM_O_OVERLAY, MF_BYCOMMAND |
  338.                 gCapDriverCaps.fHasOverlay ? MF_ENABLED : MF_GRAYED) ;
  339.     EnableMenuItem(hMenu, IDM_O_VIDEOFORMAT, MF_BYCOMMAND |
  340.                 gCapDriverCaps.fHasDlgVideoFormat ? MF_ENABLED : MF_GRAYED) ;
  341.     EnableMenuItem(hMenu, IDM_O_VIDEOSOURCE, MF_BYCOMMAND |
  342.                 gCapDriverCaps.fHasDlgVideoSource ? MF_ENABLED : MF_GRAYED) ;
  343.     EnableMenuItem(hMenu, IDM_O_VIDEODISPLAY, MF_BYCOMMAND |
  344.                 gCapDriverCaps.fHasDlgVideoDisplay ? MF_ENABLED : MF_GRAYED) ;
  345.  
  346.     // Get video format and adjust capture window
  347.     capGetStatus(hWndC, &gCapStatus, sizeof(CAPSTATUS)) ;
  348.     SetWindowPos(hWndC, NULL, 0, 0, gCapStatus.uiImageWidth,
  349.                  gCapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE) ;
  350.  
  351.     // Start preview by default
  352.     capPreviewRate(hWndC, MS_FOR_15FPS) ;
  353.     capPreview(hWndC, TRUE) ;
  354.  
  355.     // Put check mark beside appropriate menu options
  356.     CheckMenuItem(hMenu, wIndex + IDM_O_DRIVERS, MF_BYCOMMAND | MF_CHECKED) ;
  357. }
  358.  
  359.  
  360. //
  361. // MenuProc: Processes All Menu-based Operations
  362. //
  363. long FAR PASCAL MenuProc(HWND hWnd, UINT wParam, LONG lParam)
  364. {
  365. ////////////////////////////////////////////////////////////////////////
  366. //  hWnd:      Application main window handle
  367. //  hMenu:     Application menu handle
  368. //  wParam:    Menu option
  369. //  lParam:    Additional info for any menu option
  370. ////////////////////////////////////////////////////////////////////////
  371.  
  372.     OPENFILENAME ofn ;
  373.     DWORD        dwError ;
  374.     WORD         wIndex ;
  375.     BOOL         fResult ;
  376.     DWORD        dwSize ;
  377.     TCHAR        achBuffer[_MAX_PATH] ;
  378.     TCHAR        achFileName[_MAX_PATH] ;
  379.     TCHAR        *szFileFilter = TEXT("Microsoft AVI\0")
  380.                                  TEXT("*.avi\0")
  381.                                  TEXT("All Files\0")
  382.                                  TEXT("*.*\0") ;
  383.  
  384.     HMENU hMenu = GetMenu(hWnd) ;
  385.  
  386.     switch (wParam) {
  387.         case IDM_F_SETCAPTUREFILE:
  388.         {
  389.             LPTSTR p;
  390.  
  391.             // Get current capture file name and
  392.             // then try to get the new capture file name
  393.             dwError = capFileGetCaptureFile(ghWndCap, achFileName,
  394.                                         sizeof(achFileName)/sizeof(TCHAR));
  395.             if (dwError) {
  396.  
  397.                 // Get just the path info
  398.                 // Terminate the full path at the last backslash
  399.                 lstrcpy (achBuffer, achFileName);
  400.                 for (p = achBuffer + lstrlen(achBuffer); p > achBuffer; p--) {
  401.                     if (*p == '\\') {
  402.                         *(p+1) = '\0';
  403.                         break;
  404.                     }
  405.                 }
  406.  
  407.                 _fmemset(&ofn, 0, sizeof(OPENFILENAME)) ;
  408.                 ofn.lStructSize = sizeof(OPENFILENAME) ;
  409.                 ofn.hwndOwner = hWnd ;
  410.                 ofn.lpstrFilter = szFileFilter ;
  411.                 ofn.nFilterIndex = 0 ;
  412.                 ofn.lpstrFile = achFileName ;
  413.                 ofn.nMaxFile = sizeof(achFileName)/sizeof(TCHAR) ;
  414.                 ofn.lpstrFileTitle = NULL;
  415.                 ofn.lpstrTitle = TEXT("Set Capture File") ;
  416.                 ofn.nMaxFileTitle = 0 ;
  417.                 ofn.lpstrInitialDir = achBuffer;
  418.                 ofn.Flags =
  419. #ifdef BIDI
  420.                 OFN_BIDIDIALOG |
  421. #endif
  422.                 OFN_HIDEREADONLY |
  423.                 OFN_NOREADONLYRETURN |
  424.                 OFN_PATHMUSTEXIST ;
  425.  
  426.                 if (GetOpenFileName(&ofn))
  427.                     // If the user has hit OK then set capture file name
  428.                     capFileSetCaptureFile(ghWndCap, achFileName) ;
  429.             }
  430.         }
  431.         break;
  432.  
  433.         case IDM_F_SAVEVIDEOAS:
  434.             // Get the current capture file name and
  435.             // then get the substitute file name to save video in
  436.             dwError = capFileGetCaptureFile(ghWndCap, achFileName, sizeof(achFileName)/sizeof(TCHAR));
  437.             if (dwError) {
  438.  
  439.                 _fmemset(&ofn, 0, sizeof(OPENFILENAME)) ;
  440.                 ofn.lStructSize = sizeof(OPENFILENAME) ;
  441.                 ofn.hwndOwner = hWnd ;
  442.                 ofn.lpstrFilter = szFileFilter ;
  443.                 ofn.nFilterIndex = 0 ;
  444.                 ofn.lpstrFile = achFileName ;
  445.                 ofn.nMaxFile = sizeof(achFileName)/sizeof(TCHAR) ;
  446.                 ofn.lpstrFileTitle = NULL ;
  447.                 ofn.lpstrTitle = TEXT("Save Video As...") ;
  448.                 ofn.nMaxFileTitle = 0 ;
  449.                 ofn.lpstrInitialDir = NULL ;
  450.                 ofn.Flags =
  451. #ifdef BIDI
  452.                 OFN_BIDIDIALOG |
  453. #endif
  454.                 OFN_PATHMUSTEXIST ;
  455.  
  456.                 if (GetSaveFileName(&ofn))
  457.                     // If the user has hit OK then set save file name
  458.                     capFileSaveAs(ghWndCap, achFileName) ;
  459.             }
  460.             break;
  461.  
  462.         case IDM_F_ALLOCATESPACE:
  463.             if (DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_AllocCapFileSpace),
  464.                           hWnd, AllocCapFileProc))
  465.                 // If user has hit OK then alloc requested capture file space
  466.                 if (! capFileAlloc(ghWndCap, (long) gwCapFileSize * ONEMEG))
  467.                     MessageBox(NULL, TEXT("Can't pre-allocate capture file space"),
  468.                                TEXT("Error"),
  469. #ifdef BIDI
  470.                                 MB_RTL_READING |
  471. #endif
  472.                                 MB_OK | MB_ICONEXCLAMATION) ;
  473.             break ;
  474.  
  475.         case IDM_F_EXIT:
  476.             DestroyWindow(hWnd) ;
  477.             break;
  478.  
  479.         case IDM_E_COPY:
  480.             capEditCopy(ghWndCap) ;
  481.             break;
  482.  
  483.         case IDM_E_PASTEPALETTE:
  484.             capPalettePaste(ghWndCap) ;
  485.             break;
  486.  
  487.         case IDM_O_PREVIEW:
  488.             // Toggle Preview
  489.             capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  490.             capPreview(ghWndCap, !gCapStatus.fLiveWindow) ;
  491.             break;
  492.  
  493.         case IDM_O_OVERLAY:
  494.             // Toggle Overlay
  495.             capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  496.             capOverlay(ghWndCap, !gCapStatus.fOverlayWindow) ;
  497.             break ;
  498.  
  499.         case IDM_O_AUDIOFORMAT:
  500. #ifdef  USE_ACM
  501.             {
  502.                 ACMFORMATCHOOSE cfmt;
  503.  
  504.                 // Ask the ACM what the largest wave format is.....
  505.                 acmMetrics(NULL,
  506.                             ACM_METRIC_MAX_SIZE_FORMAT,
  507.                             &dwSize);
  508.  
  509.                 // Get the current audio format
  510.                 dwSize = max (dwSize, capGetAudioFormatSize (ghWndCap));
  511.                 glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize) ;
  512.                 capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  513.  
  514.                 _fmemset (&cfmt, 0, sizeof (ACMFORMATCHOOSE));
  515.                 cfmt.cbStruct = sizeof (ACMFORMATCHOOSE);
  516.                 cfmt.fdwStyle =  ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT;
  517.                 cfmt.fdwEnum =   ACM_FORMATENUMF_HARDWARE |
  518.                                  ACM_FORMATENUMF_INPUT;
  519.                 cfmt.hwndOwner = hWnd;
  520.                 cfmt.pwfx =     glpwfex;
  521.                 cfmt.cbwfx =    dwSize;
  522.                 if (!acmFormatChoose(&cfmt))
  523.                     capSetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  524.  
  525.                 GlobalFreePtr(glpwfex) ;
  526.             }
  527. #else
  528.             // If not using ACM, remove the reference in the link line
  529.             // of makefile.
  530.  
  531.             // Get current audio format and then find required format
  532.             dwSize = capGetAudioFormatSize (ghWndCap);
  533.             if(!dwSize) break;
  534.             glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize) ;
  535.             capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  536.  
  537.             if (DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_AudioFormat), hWnd, AudioFormatProc))
  538.                 capSetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize);  // If the user has hit OK, set the new audio format
  539.  
  540.             GlobalFreePtr(glpwfex) ;
  541. #endif
  542.             break ;
  543.  
  544.         case IDM_O_VIDEOFORMAT:
  545.             if (gCapDriverCaps.fHasDlgVideoFormat) {
  546.                 // Only if the driver has a "Video Format" dialog box
  547.                 if (capDlgVideoFormat(ghWndCap)) {  // If successful,
  548.                     // Get the new image dimension and center capture window
  549.                     capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  550.                     SetWindowPos(ghWndCap, NULL, 0, 0, gCapStatus.uiImageWidth,
  551.                         gCapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE) ;
  552.                     CenterCaptureWindow(hWnd, ghWndCap) ;
  553.                 }
  554.             }
  555.             break;
  556.  
  557.         case IDM_O_VIDEOSOURCE:
  558.             if (gCapDriverCaps.fHasDlgVideoSource) {
  559.                 // Only if the driver has a "Video Source" dialog box
  560.                 capDlgVideoSource(ghWndCap) ;
  561.             }
  562.             break ;
  563.  
  564.         case IDM_O_VIDEODISPLAY:
  565.             if (gCapDriverCaps.fHasDlgVideoDisplay) {
  566.                 // Only if the driver has a "Video Display" dialog box
  567.                 capDlgVideoDisplay(ghWndCap) ;
  568.             }
  569.             break ;
  570.  
  571.         case IDM_O_PALETTE:
  572.             if (DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_MakePalette), hWnd, MakePaletteProc))
  573.                 // If the user has hit OK, capture palette with the
  574.                 // specified number of colors and frames
  575.                 capPaletteAuto(ghWndCap, gwPalFrames, gwPalColors) ;
  576.             break;
  577.  
  578.         case IDM_C_CAPTUREVIDEO:
  579.             gdwVideoNum = 0 ;  // Start counting video frames
  580.             // Capture video sequence
  581.             fResult = capCaptureSequence(ghWndCap) ;
  582.             break;
  583.  
  584.         case IDM_C_CAPTUREFRAME:
  585.             gdwFrameNum = 0 ;  // Start counting single frames
  586.             // Turn off overlay / preview (gets turned off by frame capture)
  587.         capPreview(ghWndCap, FALSE);
  588.         capOverlay(ghWndCap, FALSE);
  589.  
  590.             // Grab a frame
  591.             fResult = capGrabFrameNoStop(ghWndCap) ;
  592.             break;
  593.  
  594.         case IDM_C_CAPTURESETTINGS:
  595.             // Get the current setup for video capture
  596.             capCaptureGetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
  597.  
  598.             // Invoke a Dlg box to setup all the params
  599.             if (DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_CapSetUp), hWnd, CapSetUpProc))
  600.                 // If the user has hit OK, set the new setup info
  601.                 capCaptureSetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
  602.             break;
  603.  
  604.         case IDM_O_CHOOSECOMPRESSOR:
  605.             capDlgVideoCompression(ghWndCap);
  606.             break;
  607.  
  608.         case IDM_H_ABOUT:
  609.             DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_HelpAboutBox), hWnd, AboutProc) ;
  610.             break ;
  611.  
  612.         default:
  613.             // There is a chance, a driver change has been requested
  614.             if ( IsDriverIndex(wParam) ) {
  615.                 // If it's a valid driver index...
  616.                 if (wParam - IDM_O_DRIVERS != gwDeviceIndex) {
  617.                     // and a different one too then we need to do the rest
  618.  
  619.                     // Turn off preview/overlay, uncheck current driver option
  620.                     capPreview(ghWndCap, FALSE) ;
  621.                     capOverlay(ghWndCap, FALSE) ;
  622.                     CheckMenuItem(GetMenu(hWnd), gwDeviceIndex + IDM_O_DRIVERS,
  623.                                   MF_BYCOMMAND | MF_UNCHECKED) ;
  624.  
  625.                     // Connect to requested driver
  626.                     if ( capDriverConnect(ghWndCap, (wIndex = (WORD) (wParam - IDM_O_DRIVERS))) ) {
  627.                         // Connect worked fine -- update menu, start new driver...
  628.                         CheckMenuItem(GetMenu(hWnd), wParam, MF_BYCOMMAND | MF_CHECKED) ;
  629.                         gwDeviceIndex = (WORD) (wParam - IDM_O_DRIVERS) ;
  630.                         StartNewVideoChannel(hWnd, ghWndCap, gwDeviceIndex) ;
  631.                         CenterCaptureWindow(hWnd, ghWndCap) ;
  632.                     }
  633.                     else {
  634.                         // if connect failed, re-connect back to previous driver
  635.                         if (! capDriverConnect(ghWndCap, gwDeviceIndex)) {
  636.                             MessageBox(hWnd, TEXT("Now can't connect back to previous driver !!"),
  637.                                        TEXT("Error"),
  638. #ifdef BIDI
  639.                             MB_RTL_READING |
  640. #endif
  641.  
  642.                             MB_OK | MB_ICONSTOP) ;
  643.                             return -1L ;
  644.                         }
  645.                         else
  646.                             // Re-start previous driver as it was before
  647.                             StartNewVideoChannel(hWnd, ghWndCap, gwDeviceIndex) ;
  648.                             CenterCaptureWindow(hWnd, ghWndCap) ;
  649.                     }
  650.                 }   // end of if ( != gwDeviceIndex)
  651.             }   // end of if (IsDriverIndex())
  652.             else {
  653.                 wsprintf(achBuffer, TEXT("How could you specify this (%u) Driver Index ?"),
  654.                          wParam - IDM_O_DRIVERS) ;
  655.                 MessageBox(hWnd, achBuffer, TEXT("Oops!!"),
  656. #ifdef BIDI
  657.                 MB_RTL_READING |
  658. #endif
  659.                 MB_OK | MB_ICONEXCLAMATION) ;
  660.             }
  661.  
  662.             break ;
  663.     }
  664.  
  665.     return 0L ;
  666. }
  667.  
  668.  
  669. //
  670. // MainWndProc: Application Main Window Procedure
  671. //
  672. LONG FAR PASCAL MainWndProc(HWND hWnd, UINT Message, UINT wParam, LONG lParam)
  673. {
  674. ////////////////////////////////////////////////////////////////////////
  675. //  hWnd:      Application main window handle
  676. //  Message:   Next message to be processed
  677. //  wParam:    WORD param for the message
  678. //  lParam:    LONG param for the message
  679. ////////////////////////////////////////////////////////////////////////
  680.  
  681.     switch (Message) {
  682.         case WM_COMMAND:
  683.             MenuProc(hWnd, wParam, lParam) ;
  684.             break ;
  685.  
  686.         case WM_CREATE:
  687.         {
  688.             TCHAR    achDeviceName[80] ;
  689.             TCHAR    achDeviceVersion[100] ;
  690.             TCHAR    achBuffer[100] ;
  691.             WORD    wDriverCount = 0 ;
  692.             WORD    wIndex ;
  693.             DWORD   dwError ;
  694.             HMENU   hMenu ;
  695.  
  696.             // First create the capture window
  697.             ghWndCap = capCreateCaptureWindow((LPTSTR)TEXT("Capture Window"),
  698.                                               WS_CHILD | WS_VISIBLE,
  699.                                               0, 0, 160, 120,
  700.                                               (HWND) hWnd, (int) 0) ;
  701.  
  702.             hMenu = GetSubMenu(GetMenu(hWnd), 2) ;  // 2 for "Option"
  703.  
  704. #if ENABLE_ERROR_CALLBACK
  705.   #ifdef WIN32
  706.             // Register the status and error callbacks before driver connect
  707.             capSetCallbackOnError(ghWndCap, ErrorCallbackProc) ;
  708.   #else
  709.             fpErrorCallback = MakeProcInstance((FARPROC)ErrorCallbackProc, ghInstApp) ;
  710.             capSetCallbackOnError(ghWndCap, fpErrorCallback) ;
  711.   #endif
  712. #endif
  713.  
  714. #if ENABLE_STATUS_CALLBACK
  715.   #ifdef WIN32
  716.             capSetCallbackOnStatus(ghWndCap, StatusCallbackProc) ;
  717.   #else
  718.             fpStatusCallback = MakeProcInstance((FARPROC)StatusCallbackProc, ghInstApp) ;
  719.             capSetCallbackOnStatus(ghWndCap, fpStatusCallback) ;
  720.   #endif
  721. #endif
  722.  
  723. #if ENABLE_VIDEOFRAME_CALLBACKS
  724.   #ifdef WIN32
  725.             capSetCallbackOnVideoStream(ghWndCap, VideoCallbackProc) ;
  726.             capSetCallbackOnFrame(ghWndCap, FrameCallbackProc) ;
  727.   #else
  728.             fpVideoCallback = MakeProcInstance((FARPROC)VideoCallbackProc, ghInstApp) ;
  729.             capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback) ;
  730.  
  731.             fpFrameCallback = MakeProcInstance((FARPROC)FrameCallbackProc, ghInstApp) ;
  732.             capSetCallbackOnFrame(ghWndCap, fpFrameCallback) ;
  733.   #endif
  734. #endif
  735.             // Try to connect one of the MSVIDEO drivers
  736.             for (wIndex = 0 ; wIndex < MAXVIDDRIVERS ; wIndex++) {
  737.                 if (capGetDriverDescription(wIndex,
  738.                            (LPTSTR)achDeviceName, sizeof(achDeviceName)/ sizeof(TCHAR),
  739.                            (LPTSTR)achDeviceVersion, sizeof(achDeviceVersion)/sizeof(TCHAR))) {
  740.  
  741.                     // There is such a driver in the "system.ini" file.
  742.                     // Append driver name to "Options" list in menu
  743.                     wsprintf(achBuffer, TEXT("&%d %s"), wIndex, (LPTSTR)achDeviceName) ;
  744.                     AppendMenu(hMenu, MF_ENABLED, IDM_O_DRIVERS+wIndex, achBuffer) ;
  745.  
  746.                     if (wDriverCount++ == 0) {
  747.                         // Only if no other driver is already connected
  748.                         dwError = capDriverConnect(ghWndCap, wIndex);
  749.                         if (dwError) {
  750.                             CheckMenuItem(GetMenu(hWnd), IDM_O_DRIVERS+wIndex, MF_BYCOMMAND | MF_CHECKED) ;
  751.                             gwDeviceIndex = wIndex ;
  752.                         }
  753.                     }
  754.                 } // end of if (capGetDriverDesc..())
  755.             }
  756.  
  757.             // Now refresh menu, position capture window, start driver etc
  758.             DrawMenuBar(hWnd) ;
  759.             CenterCaptureWindow(hWnd, ghWndCap) ;
  760.             StartNewVideoChannel(hWnd, ghWndCap, gwDeviceIndex) ;
  761.  
  762.             break ;
  763.         }
  764.  
  765.         case WM_MOVE:
  766.         case WM_SIZE:
  767.             CenterCaptureWindow(hWnd, ghWndCap) ;
  768.             break ;
  769.  
  770.         case WM_PALETTECHANGED:
  771.         case WM_QUERYNEWPALETTE:
  772.             // Pass the buck to Capture window proc
  773.             PostMessage(ghWndCap, Message, wParam, lParam) ;
  774.             break ;
  775.  
  776.         case WM_INITMENU:
  777.         {
  778.             BOOL          fResult ;
  779.  
  780.             // Initially check if "Options.PastePalette" should be enabled
  781.             fResult = IsClipboardFormatAvailable(CF_PALETTE) ?
  782.                       MF_ENABLED : MF_GRAYED ;
  783.             EnableMenuItem((HMENU) wParam, IDM_E_PASTEPALETTE, fResult) ;
  784.  
  785.         // Check/Uncheck Preview and Overlay
  786.             capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  787.             CheckMenuItem((HMENU)wParam, IDM_O_PREVIEW, gCapStatus.fLiveWindow
  788.                         ? MF_CHECKED : MF_UNCHECKED);
  789.             CheckMenuItem((HMENU)wParam, IDM_O_OVERLAY,gCapStatus.fOverlayWindow
  790.                         ? MF_CHECKED : MF_UNCHECKED);
  791.         }
  792.  
  793.         case WM_PAINT:
  794.         {
  795.             HDC           hDC ;
  796.             PAINTSTRUCT   ps ;
  797.  
  798.             hDC = BeginPaint(hWnd, &ps) ;
  799.  
  800.             // Included in case the background is not a pure color
  801.             SetBkMode(hDC, TRANSPARENT) ;
  802.  
  803.             EndPaint(hWnd, &ps) ;
  804.             break ;
  805.         }
  806.  
  807.         case WM_CLOSE:
  808.             // Disable and free all the callbacks
  809. #if ENABLE_ERROR_CALLBACK
  810.             capSetCallbackOnError(ghWndCap, NULL) ;
  811.   #ifndef WIN32
  812.             FreeProcInstance(fpErrorCallback) ;
  813.   #endif
  814. #endif
  815.  
  816. #if ENABLE_STATUS_CALLBACK
  817.             capSetCallbackOnStatus(ghWndCap, NULL) ;
  818.   #ifndef WIN32
  819.             FreeProcInstance(fpStatusCallback) ;
  820.   #endif
  821. #endif
  822.  
  823. #if ENABLE_VIDEOFRAME_CALLBACKS
  824.             capSetCallbackOnFrame(ghWndCap, NULL) ;
  825.             capSetCallbackOnVideoStream(ghWndCap, NULL) ;
  826.   #ifndef WIN32
  827.             FreeProcInstance(fpFrameCallback) ;
  828.             FreeProcInstance(fpVideoCallback) ;
  829.   #endif
  830. #endif
  831.             // Destroy child windows, modeless dialogs, then this window...
  832.  
  833.             DestroyWindow(ghWndCap) ;
  834.             DestroyWindow(hWnd) ;
  835.             break ;
  836.  
  837.         case WM_DESTROY:
  838.             PostQuitMessage(0) ;
  839.             break ;
  840.  
  841.         default:
  842.             return DefWindowProc(hWnd, Message, wParam, lParam) ;
  843.     }
  844.  
  845.     return 0L;
  846. }   // End of MainWndProc
  847.