/**************************************************************************
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
* PURPOSE.
*
* Copyright 1992 - 1998 Microsoft Corporation. All Rights Reserved.
*
**************************************************************************/
/****************************************************************************
*
* captest.c: Source Code for the CapTest Sample Program
*
* Microsoft Video for Windows Capture Class Sample Program
*
***************************************************************************/
#define ENABLE_ERROR_CALLBACK 1
#define ENABLE_STATUS_CALLBACK 1
#define ENABLE_VIDEOFRAME_CALLBACKS 0
#define INC_OLE2
#include <windows.h>
#include <windowsx.h>
#include <commdlg.h>
#include <vfw.h>
#include <mmreg.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <dos.h>
#include "captest.h"
//
// Global Variables
//
TCHAR gachAppName[] = TEXT("CapTestApp") ;
TCHAR gachIconName[] = TEXT("CapTestIcon") ;
TCHAR gachMenuName[] = TEXT("CapTestMenu") ;
TCHAR gachMCIDeviceName[21] = TEXT("VideoDisc") ; // default MCI device
TCHAR gachString[128] ;
TCHAR gachBuffer[200] ;
HINSTANCE ghInstApp ;
HWND ghWndMain ;
HWND ghWndCap ;
HANDLE ghAccel ;
WORD gwDeviceIndex ;
WORD gwPalFrames = DEF_PALNUMFRAMES ;
WORD gwPalColors = DEF_PALNUMCOLORS ;
WORD gwCapFileSize ;
DWORD gdwFrameNum ;
DWORD gdwVideoNum ;
CAPSTATUS gCapStatus ;
CAPDRIVERCAPS gCapDriverCaps ;
CAPTUREPARMS gCapParms ;
LPWAVEFORMATEX glpwfex ;
// MakeProcInstance is only required for 16-bit apps
#ifndef WIN32
FARPROC fpErrorCallback;
FARPROC fpStatusCallback;
FARPROC fpFrameCallback;
FARPROC fpVideoCallback;
#endif
// Function prototypes
//
LONG FAR PASCAL MainWndProc(HWND, UINT, UINT, LONG) ;
LRESULT FNWCALLBACK ErrorCallbackProc(HWND, int, LPTSTR) ;
LRESULT FNWCALLBACK StatusCallbackProc(HWND, int, LPTSTR) ;
LRESULT FNWCALLBACK FrameCallbackProc(HWND, LPVIDEOHDR) ;
LRESULT FNWCALLBACK VideoCallbackProc(HWND, LPVIDEOHDR) ;
//
// WinMain: Application Entry Point Function
//
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
///////////////////////////////////////////////////////////////////////
// hInstance: handle for this instance
// hPrevInstance: handle for possible previous instances
// lpszCmdLine: long pointer to exec command line
// nCmdShow: Show code for main window display
///////////////////////////////////////////////////////////////////////
MSG msg ;
WNDCLASS wc ;
ghInstApp = hInstance ;
if (! hPrevInstance) {
// If it's the first instance, register the window class
wc.lpszClassName = gachAppName ;
wc.hInstance = hInstance ;
wc.lpfnWndProc = MainWndProc ;
wc.hCursor = LoadCursor(NULL, IDC_ARROW) ;
wc.hIcon = LoadIcon(hInstance, gachIconName) ;
wc.lpszMenuName = gachMenuName ;
wc.hbrBackground = GetStockObject(WHITE_BRUSH) ;
wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.cbClsExtra = 0 ;
wc.cbWndExtra = 0 ;
if (! RegisterClass(&wc)) {
LoadString(ghInstApp, IDS_ERR_REGISTER_CLASS, gachString, sizeof(gachString)/sizeof(TCHAR)) ;
MessageBox(NULL, gachString, NULL,
#ifdef BIDI
MB_RTL_READING |
#endif
MB_ICONEXCLAMATION) ;
return 0 ;
}
}
// Create Application's Main window
ghWndMain =
#ifdef BIDI
//
// unfortunately you can't just #ifdef the CreateWindow line and leave
// the parameters common: on Win32, CreateWindow is a macro and does not
// expand correctly if you ifdef only the 'CreateWindow(' line.
//
CreateWindowEx(WS_EX_BIDI_SCROLL | WS_EX_BIDI_MENU |WS_EX_BIDI_NOICON,
gachAppName,
TEXT("Capture Test App"),
WS_CAPTION |
WS_SYSMENU |
WS_MINIMIZEBOX |
WS_MAXIMIZEBOX |
WS_THICKFRAME |
WS_CLIPCHILDREN |
WS_OVERLAPPED,
CW_USEDEFAULT, 0,
320, 240,
NULL,
NULL,
ghInstApp,
NULL) ;
#else
CreateWindow (
gachAppName,
TEXT("Capture Test App"),
WS_CAPTION |
WS_SYSMENU |
WS_MINIMIZEBOX |
WS_MAXIMIZEBOX |
WS_THICKFRAME |
WS_CLIPCHILDREN |
WS_OVERLAPPED,
CW_USEDEFAULT, 0,
320, 240,
NULL,
NULL,
ghInstApp,
NULL) ;
#endif
if (ghWndMain == NULL) {
LoadString(ghInstApp, IDS_ERR_CREATE_WINDOW, gachString, sizeof(gachString)/sizeof(TCHAR)) ;
MessageBox(NULL, gachString, NULL,
#ifdef BIDI
MB_RTL_READING |
#endif
MB_ICONEXCLAMATION | MB_OK) ;
return IDS_ERR_CREATE_WINDOW ;
}
ShowWindow(ghWndMain, nCmdShow) ;
UpdateWindow(ghWndMain) ;
ghAccel = LoadAccelerators(ghInstApp, gachAppName) ;
// All set; get and process messages
while (GetMessage(&msg, NULL, 0, 0)) {
if (! TranslateAccelerator(ghWndMain, ghAccel, &msg)) {
TranslateMessage(&msg) ;
DispatchMessage(&msg) ;
}
}
return msg.wParam ;
} // End of WinMain
//
// ErrorCallbackProc: Error Callback Function
//
LRESULT FNWCALLBACK ErrorCallbackProc(HWND hWnd, int nErrID, LPTSTR lpErrorText)
{
////////////////////////////////////////////////////////////////////////
// hWnd: Application main window handle
// nErrID: Error code for the encountered error
// lpErrorText: Error text string for the encountered error
////////////////////////////////////////////////////////////////////////
if (!ghWndMain)
return FALSE;
if (nErrID == 0) // Starting a new major function
return TRUE; // Clear out old errors...
// Show the error ID and text
wsprintf(gachBuffer, TEXT("Error# %d"), nErrID) ;
MessageBox(hWnd, lpErrorText, gachBuffer,
#ifdef BIDI
MB_RTL_READING |
#endif
MB_OK | MB_ICONEXCLAMATION) ;
return (LRESULT) TRUE ;
}
//
// StatusCallbackProc: Status Callback Function
//
LRESULT FNWCALLBACK StatusCallbackProc(HWND hWnd, int nID, LPTSTR lpStatusText)
{
////////////////////////////////////////////////////////////////////////
// hWnd: Application main window handle
// nID: Status code for the current status
// lpStatusText: Status text string for the current status
////////////////////////////////////////////////////////////////////////
if (!ghWndMain)
return FALSE;
if (nID == 0) { // Zero means clear old status messages
SetWindowText(ghWndMain, (LPTSTR) gachAppName) ;
return (LRESULT) TRUE ;
}
// Show the status ID and status text...
wsprintf(gachBuffer, TEXT("Status# %d: %s"), nID, lpStatusText) ;
SetWindowText(ghWndMain, (LPTSTR)gachBuffer) ;
return (LRESULT) TRUE ;
}
//
// FrameCallbackProc: Frame Callback Function
// Called whenever a new frame is captured but not streaming
//
LRESULT FNWCALLBACK FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
{
////////////////////////////////////////////////////////////////////////
// hWnd: Application main window handle
// lpVHdr: long pointer to VideoHdr struct containing captured
// frame information
////////////////////////////////////////////////////////////////////////
if (!ghWndMain)
return FALSE;
wsprintf(gachBuffer, TEXT("Preview frame# %ld "), gdwFrameNum++) ;
SetWindowText(ghWndMain, (LPTSTR)gachBuffer) ;
return (LRESULT) TRUE ;
}
//
// VideoCallbackProc: Video Stream Callback Function
// Called whenever a new frame is captured while streaming
//
LRESULT FNWCALLBACK VideoCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
{
////////////////////////////////////////////////////////////////////////
// hWnd: Application main window handle
// lpVHdr: long pointer to VideoHdr struct containing captured
// frame information
////////////////////////////////////////////////////////////////////////
gdwVideoNum++; // Testing: just count the callbacks
return (LRESULT) TRUE ;
}
//
// CenterCaptureWindow: Placess Capture Window at the Center of Main Window
//
static void CenterCaptureWindow(HWND hWndM, HWND hWndC)
{
////////////////////////////////////////////////////////////////////////
// hWndM: Application main window handle
// hWndC: Capture window handle
////////////////////////////////////////////////////////////////////////
RECT MainRect ;
RECT CapRect ;
WORD wCapXPos ;
WORD wCapYPos ;
// Get the sizes of main and capture windows and
// calculate the location for centering
GetClientRect(hWndM, &MainRect) ;
GetClientRect(hWndC, &CapRect) ;
wCapXPos = max(0, (Width(MainRect) - Width(CapRect)) / 2) ;
wCapYPos = max(0, (Height(MainRect) - Height(CapRect)) / 2) ;
// Position the capture window at the required location
MoveWindow(hWndC, wCapXPos, wCapYPos, Width(CapRect),
Height(CapRect), TRUE) ;
}
//
// StartNewVideoChannel: Gets Selected Driver's Caps -- Updates menu,
// Checks Image Size -- Resizes display window,
// Enables Preview (at 15 FPS rate)
//
static void StartNewVideoChannel(HWND hWndM, HWND hWndC, WORD wIndex)
{
////////////////////////////////////////////////////////////////////////
// hWndM: Application main window handle
// hWndC: Capture window handle
// wIndex: Selected capture driver index
////////////////////////////////////////////////////////////////////////
HMENU hMenu = GetMenu(hWndM) ;
// Get capture driver settings and update menu
capDriverGetCaps(hWndC, &gCapDriverCaps, sizeof(CAPDRIVERCAPS)) ;
EnableMenuItem(hMenu, IDM_O_OVERLAY, MF_BYCOMMAND |
gCapDriverCaps.fHasOverlay ? MF_ENABLED : MF_GRAYED) ;
EnableMenuItem(hMenu, IDM_O_VIDEOFORMAT, MF_BYCOMMAND |
gCapDriverCaps.fHasDlgVideoFormat ? MF_ENABLED : MF_GRAYED) ;
EnableMenuItem(hMenu, IDM_O_VIDEOSOURCE, MF_BYCOMMAND |
gCapDriverCaps.fHasDlgVideoSource ? MF_ENABLED : MF_GRAYED) ;
EnableMenuItem(hMenu, IDM_O_VIDEODISPLAY, MF_BYCOMMAND |
gCapDriverCaps.fHasDlgVideoDisplay ? MF_ENABLED : MF_GRAYED) ;
// Get video format and adjust capture window
capGetStatus(hWndC, &gCapStatus, sizeof(CAPSTATUS)) ;
SetWindowPos(hWndC, NULL, 0, 0, gCapStatus.uiImageWidth,
gCapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE) ;
// Start preview by default
capPreviewRate(hWndC, MS_FOR_15FPS) ;
capPreview(hWndC, TRUE) ;
// Put check mark beside appropriate menu options
CheckMenuItem(hMenu, wIndex + IDM_O_DRIVERS, MF_BYCOMMAND | MF_CHECKED) ;
}
//
// MenuProc: Processes All Menu-based Operations
//
long FAR PASCAL MenuProc(HWND hWnd, UINT wParam, LONG lParam)
{
////////////////////////////////////////////////////////////////////////
// hWnd: Application main window handle
// hMenu: Application menu handle
// wParam: Menu option
// lParam: Additional info for any menu option
////////////////////////////////////////////////////////////////////////
OPENFILENAME ofn ;
DWORD dwError ;
WORD wIndex ;
BOOL fResult ;
DWORD dwSize ;
TCHAR achBuffer[_MAX_PATH] ;
TCHAR achFileName[_MAX_PATH] ;
TCHAR *szFileFilter = TEXT("Microsoft AVI\0")
TEXT("*.avi\0")
TEXT("All Files\0")
TEXT("*.*\0") ;
HMENU hMenu = GetMenu(hWnd) ;
switch (wParam) {
case IDM_F_SETCAPTUREFILE:
{
LPTSTR p;
// Get current capture file name and
// then try to get the new capture file name
dwError = capFileGetCaptureFile(ghWndCap, achFileName,
sizeof(achFileName)/sizeof(TCHAR));
if (dwError) {
// Get just the path info
// Terminate the full path at the last backslash
lstrcpy (achBuffer, achFileName);
for (p = achBuffer + lstrlen(achBuffer); p > achBuffer; p--) {
if (*p == '\\') {
*(p+1) = '\0';
break;
}
}
_fmemset(&ofn, 0, sizeof(OPENFILENAME)) ;
ofn.lStructSize = sizeof(OPENFILENAME) ;
ofn.hwndOwner = hWnd ;
ofn.lpstrFilter = szFileFilter ;
ofn.nFilterIndex = 0 ;
ofn.lpstrFile = achFileName ;
ofn.nMaxFile = sizeof(achFileName)/sizeof(TCHAR) ;
ofn.lpstrFileTitle = NULL;
ofn.lpstrTitle = TEXT("Set Capture File") ;
ofn.nMaxFileTitle = 0 ;
ofn.lpstrInitialDir = achBuffer;
ofn.Flags =
#ifdef BIDI
OFN_BIDIDIALOG |
#endif
OFN_HIDEREADONLY |
OFN_NOREADONLYRETURN |
OFN_PATHMUSTEXIST ;
if (GetOpenFileName(&ofn))
// If the user has hit OK then set capture file name
capFileSetCaptureFile(ghWndCap, achFileName) ;
}
}
break;
case IDM_F_SAVEVIDEOAS:
// Get the current capture file name and
// then get the substitute file name to save video in
dwError = capFileGetCaptureFile(ghWndCap, achFileName, sizeof(achFileName)/sizeof(TCHAR));
if (dwError) {
_fmemset(&ofn, 0, sizeof(OPENFILENAME)) ;
ofn.lStructSize = sizeof(OPENFILENAME) ;
ofn.hwndOwner = hWnd ;
ofn.lpstrFilter = szFileFilter ;
ofn.nFilterIndex = 0 ;
ofn.lpstrFile = achFileName ;
ofn.nMaxFile = sizeof(achFileName)/sizeof(TCHAR) ;
ofn.lpstrFileTitle = NULL ;
ofn.lpstrTitle = TEXT("Save Video As...") ;
ofn.nMaxFileTitle = 0 ;
ofn.lpstrInitialDir = NULL ;
ofn.Flags =
#ifdef BIDI
OFN_BIDIDIALOG |
#endif
OFN_PATHMUSTEXIST ;
if (GetSaveFileName(&ofn))
// If the user has hit OK then set save file name
capFileSaveAs(ghWndCap, achFileName) ;
}
break;
case IDM_F_ALLOCATESPACE:
if (DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_AllocCapFileSpace),
hWnd, AllocCapFileProc))
// If user has hit OK then alloc requested capture file space
if (! capFileAlloc(ghWndCap, (long) gwCapFileSize * ONEMEG))
MessageBox(NULL, TEXT("Can't pre-allocate capture file space"),
TEXT("Error"),
#ifdef BIDI
MB_RTL_READING |
#endif
MB_OK | MB_ICONEXCLAMATION) ;
break ;
case IDM_F_EXIT:
DestroyWindow(hWnd) ;
break;
case IDM_E_COPY:
capEditCopy(ghWndCap) ;
break;
case IDM_E_PASTEPALETTE:
capPalettePaste(ghWndCap) ;
break;
case IDM_O_PREVIEW:
// Toggle Preview
capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
capPreview(ghWndCap, !gCapStatus.fLiveWindow) ;
break;
case IDM_O_OVERLAY:
// Toggle Overlay
capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
capOverlay(ghWndCap, !gCapStatus.fOverlayWindow) ;
break ;
case IDM_O_AUDIOFORMAT:
#ifdef USE_ACM
{
ACMFORMATCHOOSE cfmt;
// Ask the ACM what the largest wave format is.....
acmMetrics(NULL,
ACM_METRIC_MAX_SIZE_FORMAT,
&dwSize);
// Get the current audio format
dwSize = max (dwSize, capGetAudioFormatSize (ghWndCap));
glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize) ;
capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
_fmemset (&cfmt, 0, sizeof (ACMFORMATCHOOSE));
cfmt.cbStruct = sizeof (ACMFORMATCHOOSE);
cfmt.fdwStyle = ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT;
cfmt.fdwEnum = ACM_FORMATENUMF_HARDWARE |
ACM_FORMATENUMF_INPUT;
cfmt.hwndOwner = hWnd;
cfmt.pwfx = glpwfex;
cfmt.cbwfx = dwSize;
if (!acmFormatChoose(&cfmt))
capSetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
GlobalFreePtr(glpwfex) ;
}
#else
// If not using ACM, remove the reference in the link line
// of makefile.
// Get current audio format and then find required format
dwSize = capGetAudioFormatSize (ghWndCap);
if(!dwSize) break;
glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize) ;
capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
if (DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_AudioFormat), hWnd, AudioFormatProc))
capSetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize); // If the user has hit OK, set the new audio format
GlobalFreePtr(glpwfex) ;
#endif
break ;
case IDM_O_VIDEOFORMAT:
if (gCapDriverCaps.fHasDlgVideoFormat) {
// Only if the driver has a "Video Format" dialog box
if (capDlgVideoFormat(ghWndCap)) { // If successful,
// Get the new image dimension and center capture window
capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
SetWindowPos(ghWndCap, NULL, 0, 0, gCapStatus.uiImageWidth,
gCapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE) ;
CenterCaptureWindow(hWnd, ghWndCap) ;
}
}
break;
case IDM_O_VIDEOSOURCE:
if (gCapDriverCaps.fHasDlgVideoSource) {
// Only if the driver has a "Video Source" dialog box
capDlgVideoSource(ghWndCap) ;
}
break ;
case IDM_O_VIDEODISPLAY:
if (gCapDriverCaps.fHasDlgVideoDisplay) {
// Only if the driver has a "Video Display" dialog box
capDlgVideoDisplay(ghWndCap) ;
}
break ;
case IDM_O_PALETTE:
if (DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_MakePalette), hWnd, MakePaletteProc))
// If the user has hit OK, capture palette with the
// specified number of colors and frames
capPaletteAuto(ghWndCap, gwPalFrames, gwPalColors) ;
break;
case IDM_C_CAPTUREVIDEO:
gdwVideoNum = 0 ; // Start counting video frames
// Capture video sequence
fResult = capCaptureSequence(ghWndCap) ;
break;
case IDM_C_CAPTUREFRAME:
gdwFrameNum = 0 ; // Start counting single frames
// Turn off overlay / preview (gets turned off by frame capture)
capPreview(ghWndCap, FALSE);
capOverlay(ghWndCap, FALSE);
// Grab a frame
fResult = capGrabFrameNoStop(ghWndCap) ;
break;
case IDM_C_CAPTURESETTINGS:
// Get the current setup for video capture
capCaptureGetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
// Invoke a Dlg box to setup all the params
if (DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_CapSetUp), hWnd, CapSetUpProc))
// If the user has hit OK, set the new setup info
capCaptureSetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
break;
case IDM_O_CHOOSECOMPRESSOR:
capDlgVideoCompression(ghWndCap);
break;
case IDM_H_ABOUT:
DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_HelpAboutBox), hWnd, AboutProc) ;
break ;
default:
// There is a chance, a driver change has been requested
if ( IsDriverIndex(wParam) ) {
// If it's a valid driver index...
if (wParam - IDM_O_DRIVERS != gwDeviceIndex) {
// and a different one too then we need to do the rest
// Turn off preview/overlay, uncheck current driver option
capPreview(ghWndCap, FALSE) ;
capOverlay(ghWndCap, FALSE) ;
CheckMenuItem(GetMenu(hWnd), gwDeviceIndex + IDM_O_DRIVERS,
MF_BYCOMMAND | MF_UNCHECKED) ;
// Connect to requested driver
if ( capDriverConnect(ghWndCap, (wIndex = (WORD) (wParam - IDM_O_DRIVERS))) ) {
// Connect worked fine -- update menu, start new driver...
CheckMenuItem(GetMenu(hWnd), wParam, MF_BYCOMMAND | MF_CHECKED) ;
gwDeviceIndex = (WORD) (wParam - IDM_O_DRIVERS) ;
StartNewVideoChannel(hWnd, ghWndCap, gwDeviceIndex) ;
CenterCaptureWindow(hWnd, ghWndCap) ;
}
else {
// if connect failed, re-connect back to previous driver
if (! capDriverConnect(ghWndCap, gwDeviceIndex)) {
MessageBox(hWnd, TEXT("Now can't connect back to previous driver !!"),
TEXT("Error"),
#ifdef BIDI
MB_RTL_READING |
#endif
MB_OK | MB_ICONSTOP) ;
return -1L ;
}
else
// Re-start previous driver as it was before
StartNewVideoChannel(hWnd, ghWndCap, gwDeviceIndex) ;
CenterCaptureWindow(hWnd, ghWndCap) ;
}
} // end of if ( != gwDeviceIndex)
} // end of if (IsDriverIndex())
else {
wsprintf(achBuffer, TEXT("How could you specify this (%u) Driver Index ?"),
wParam - IDM_O_DRIVERS) ;
MessageBox(hWnd, achBuffer, TEXT("Oops!!"),
#ifdef BIDI
MB_RTL_READING |
#endif
MB_OK | MB_ICONEXCLAMATION) ;
}
break ;
}
return 0L ;
}
//
// MainWndProc: Application Main Window Procedure
//
LONG FAR PASCAL MainWndProc(HWND hWnd, UINT Message, UINT wParam, LONG lParam)
{
////////////////////////////////////////////////////////////////////////
// hWnd: Application main window handle
// Message: Next message to be processed
// wParam: WORD param for the message
// lParam: LONG param for the message
////////////////////////////////////////////////////////////////////////
switch (Message) {
case WM_COMMAND:
MenuProc(hWnd, wParam, lParam) ;
break ;
case WM_CREATE:
{
TCHAR achDeviceName[80] ;
TCHAR achDeviceVersion[100] ;
TCHAR achBuffer[100] ;
WORD wDriverCount = 0 ;
WORD wIndex ;
DWORD dwError ;
HMENU hMenu ;
// First create the capture window
ghWndCap = capCreateCaptureWindow((LPTSTR)TEXT("Capture Window"),
WS_CHILD | WS_VISIBLE,
0, 0, 160, 120,
(HWND) hWnd, (int) 0) ;
hMenu = GetSubMenu(GetMenu(hWnd), 2) ; // 2 for "Option"
#if ENABLE_ERROR_CALLBACK
#ifdef WIN32
// Register the status and error callbacks before driver connect
capSetCallbackOnError(ghWndCap, ErrorCallbackProc) ;
#else
fpErrorCallback = MakeProcInstance((FARPROC)ErrorCallbackProc, ghInstApp) ;
capSetCallbackOnError(ghWndCap, fpErrorCallback) ;
#endif
#endif
#if ENABLE_STATUS_CALLBACK
#ifdef WIN32
capSetCallbackOnStatus(ghWndCap, StatusCallbackProc) ;
#else
fpStatusCallback = MakeProcInstance((FARPROC)StatusCallbackProc, ghInstApp) ;
capSetCallbackOnStatus(ghWndCap, fpStatusCallback) ;
#endif
#endif
#if ENABLE_VIDEOFRAME_CALLBACKS
#ifdef WIN32
capSetCallbackOnVideoStream(ghWndCap, VideoCallbackProc) ;
capSetCallbackOnFrame(ghWndCap, FrameCallbackProc) ;
#else
fpVideoCallback = MakeProcInstance((FARPROC)VideoCallbackProc, ghInstApp) ;
capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback) ;
fpFrameCallback = MakeProcInstance((FARPROC)FrameCallbackProc, ghInstApp) ;
capSetCallbackOnFrame(ghWndCap, fpFrameCallback) ;
#endif
#endif
// Try to connect one of the MSVIDEO drivers
for (wIndex = 0 ; wIndex < MAXVIDDRIVERS ; wIndex++) {
if (capGetDriverDescription(wIndex,
(LPTSTR)achDeviceName, sizeof(achDeviceName)/ sizeof(TCHAR),
(LPTSTR)achDeviceVersion, sizeof(achDeviceVersion)/sizeof(TCHAR))) {
// There is such a driver in the "system.ini" file.
// Append driver name to "Options" list in menu
wsprintf(achBuffer, TEXT("&%d %s"), wIndex, (LPTSTR)achDeviceName) ;
AppendMenu(hMenu, MF_ENABLED, IDM_O_DRIVERS+wIndex, achBuffer) ;
if (wDriverCount++ == 0) {
// Only if no other driver is already connected
dwError = capDriverConnect(ghWndCap, wIndex);
if (dwError) {
CheckMenuItem(GetMenu(hWnd), IDM_O_DRIVERS+wIndex, MF_BYCOMMAND | MF_CHECKED) ;
gwDeviceIndex = wIndex ;
}
}
} // end of if (capGetDriverDesc..())
}
// Now refresh menu, position capture window, start driver etc
DrawMenuBar(hWnd) ;
CenterCaptureWindow(hWnd, ghWndCap) ;
StartNewVideoChannel(hWnd, ghWndCap, gwDeviceIndex) ;
break ;
}
case WM_MOVE:
case WM_SIZE:
CenterCaptureWindow(hWnd, ghWndCap) ;
break ;
case WM_PALETTECHANGED:
case WM_QUERYNEWPALETTE:
// Pass the buck to Capture window proc
PostMessage(ghWndCap, Message, wParam, lParam) ;
break ;
case WM_INITMENU:
{
BOOL fResult ;
// Initially check if "Options.PastePalette" should be enabled
fResult = IsClipboardFormatAvailable(CF_PALETTE) ?
MF_ENABLED : MF_GRAYED ;
EnableMenuItem((HMENU) wParam, IDM_E_PASTEPALETTE, fResult) ;
// Check/Uncheck Preview and Overlay
capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
CheckMenuItem((HMENU)wParam, IDM_O_PREVIEW, gCapStatus.fLiveWindow
? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem((HMENU)wParam, IDM_O_OVERLAY,gCapStatus.fOverlayWindow
? MF_CHECKED : MF_UNCHECKED);
}
case WM_PAINT:
{
HDC hDC ;
PAINTSTRUCT ps ;
hDC = BeginPaint(hWnd, &ps) ;
// Included in case the background is not a pure color
SetBkMode(hDC, TRANSPARENT) ;
EndPaint(hWnd, &ps) ;
break ;
}
case WM_CLOSE:
// Disable and free all the callbacks
#if ENABLE_ERROR_CALLBACK
capSetCallbackOnError(ghWndCap, NULL) ;
#ifndef WIN32
FreeProcInstance(fpErrorCallback) ;
#endif
#endif
#if ENABLE_STATUS_CALLBACK
capSetCallbackOnStatus(ghWndCap, NULL) ;
#ifndef WIN32
FreeProcInstance(fpStatusCallback) ;
#endif
#endif
#if ENABLE_VIDEOFRAME_CALLBACKS
capSetCallbackOnFrame(ghWndCap, NULL) ;
capSetCallbackOnVideoStream(ghWndCap, NULL) ;
#ifndef WIN32
FreeProcInstance(fpFrameCallback) ;
FreeProcInstance(fpVideoCallback) ;
#endif
#endif
// Destroy child windows, modeless dialogs, then this window...
DestroyWindow(ghWndCap) ;
DestroyWindow(hWnd) ;
break ;
case WM_DESTROY:
PostQuitMessage(0) ;
break ;
default:
return DefWindowProc(hWnd, Message, wParam, lParam) ;
}
return 0L;
} // End of MainWndProc