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

Windows编程

开发平台:

Visual C++

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