天天看点

win32 摄像头捕获系统vfw

//win32 摄像头捕获系统vfw  

//  VideoRecord.h  

///  用于定义一些资源ID  

#include "resource.h"  

//#define EXIT  104  

#define HELP  105  

#define MINIMIZE 106  

//#define DISPLAY  107  

#define BUTTONSIZE  15  

#define PHOTO   108  

#define RECORDVIDEO 109  

// #define RESOURCE 110  

// #define FORMAT   111  

#define CONNECT 112  

#include <Windows.h>  

#include <STRING>  

#include <vfw.h>  

#include "VideoRecord.h"  

#pragma comment(lib, "vfw32.lib")  

LRESULT WINAPI MainWndProc( HWND, UINT, WPARAM, LPARAM );  

LRESULT WINAPI SelCapDrcProc( HWND, UINT, WPARAM, LPARAM );  

int EnumCapDrv();  

VOID APIENTRY HandlePopupMenu(HWND, POINT);  // 右键弹出菜单回调函数  

WORD WINAPI VideoThreadProc( LPVOID lParam); // 视频捕捉线程函数  

////////////////全局变量  

HANDLE ghInstance;  // 应用程序实例  

HWND hwndMain;  // 主窗口句柄  

HWND hwndVideo;  // 视频捕捉窗口句柄  

HWND hwndSelCapDrvDlg; // 选择捕捉驱动对话框句柄  

HWND hwndSelCapDrvLBox; // 选择驱动对话框列举驱动名称列表框句柄  

HWND hwndExit;  

HWND hwndMin;  

HWND hwndHelp;  

HWND hwndPhoto;  

HWND hwndRecord;  

HWND hwndBtnExit;  

HWND hwndSource;  

HWND hwndFormat;  

HWND hwndConnect;  

HANDLE hVideoTread; // 视频采集线程  

HRGN hRoundRgn; // 窗口修正区域  

CAPDRIVERCAPS capDrvCaps; // 驱动性能  

bool bRecordFileOpen = false;  // 录像开始标志  

bool bPhotoFileOpen = false;  // 照相开始标志  

bool bRecording = false;  // 判断是否正在录像  

bool bThreadEnd = false; // 判断视频线程是否终止  

char recordFile[260]; //保持录像标志  

char photoFile[260]; // 保持照相标志  

char gachBuffer[260]; // 保存错误信息  

//////////////////////////////////////////////////////////////////////////////  

// ErrorCallbackProc:    错误回调函数,过capSetCallbackOnError宏来注册回调   

// hWnd:              捕获窗口句柄   

// nErrID:              错误代码   

// lpErrorText:          关于错误的文本信息   

///////////////////////////////////////////////////////////////////////////////   

LRESULT CALLBACK ErrorCallbackProc(HWND hWnd,int nErrID,LPSTR lpErrorText)  

{  

    if(!hwndMain)  

        return FALSE;  

    if(nErrID==0)  

        return TRUE;//清除旧的错误  

    wsprintf(gachBuffer,"Error# %d",nErrID);//显示错误标识和文本  

    MessageBox(hWnd, lpErrorText, gachBuffer,MB_OK | MB_ICONEXCLAMATION);   

    return (LRESULT) TRUE;  

}  

/////////////////////////////////////  

int PASCAL WinMain( IN HINSTANCE hInstance,   

                   IN HINSTANCE hPrevInstance,   

                   IN LPSTR lpCmdLine,   

                   IN int nShowCmd )  

    WNDCLASS wndClass;  

    MSG msg;  

    char className[] = "VideoClass";  

    // 如果不是前实例  

    if (!hPrevInstance)  

    {  

        wndClass.lpszClassName = className;  

        wndClass.lpfnWndProc = MainWndProc;  

        wndClass.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;  

        wndClass.hInstance = hInstance;  

        wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);  

        wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);  

        wndClass.hbrBackground = CreateSolidBrush( RGB(200,200,100) );  

        wndClass.lpszMenuName = NULL;  

        wndClass.cbClsExtra = 0;  

        wndClass.cbWndExtra = 0;  

        RegisterClass( &wndClass );  

    }  

    ghInstance = hInstance;  

    // 创建主窗口  

    hwndMain = CreateWindow(className,  

        "视频监控系统",  

        WS_POPUP|WS_OVERLAPPED,  

        GetSystemMetrics(SM_CXFULLSCREEN)/2 - 600/2,  

        GetSystemMetrics(SM_CYFULLSCREEN)/2-600/2,  

        600, 600,  

        NULL,  

        hInstance,  

        NULL);  

    ShowWindow(hwndMain, nShowCmd);  

    // 设定主窗口主要区域  

    SetWindowRgn(hwndMain, hRoundRgn, 1);  

    while( GetMessage(&msg, NULL, 0, 0))  

        TranslateMessage(&msg);//该函数将虚拟键消息转换为字符消息。  

        //字符消息被寄送到调用线程的消息队列里,当下一次线程调用函数GetMessage或PeekMessage时被读出  

        DispatchMessage(&msg);//该函数调度一个消息给窗口程序。  

        //通常调度从GetMessage取得的消息。消息被调度到的窗口程序即是MainProc()函数  

    return msg.wParam;  

LRESULT CALLBACK MainWndProc( HWND hMain, UINT msg, WPARAM wParam, LPARAM lParam )  

    HDC hdc = GetDC(hMain);  

    RECT rc;   // 客户区  

    POINT pt;  // 鼠标位置  

    HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);  

    switch(msg)  

    case WM_LBUTTONDBLCLK:  

        SetFocus(hMain);  

        break;  

    case WM_RBUTTONDOWN:  

        GetClientRect(hMain, (LPRECT)&rc);  

        pt.y = HIWORD(lParam);  

        pt.x = LOWORD(lParam);  

        if ( PtInRect(&rc, pt) )  

        {  

            HandlePopupMenu(hMain, pt);  

        }  

    case WM_PAINT:  

        RECT helpRect, minRect, exitRect;  

        HRGN helpRgn, minRgn, exitRgn;  

        FrameRgn(hdc, hRoundRgn, CreateSolidBrush(RGB(0,0,0)), 2, 2);  

        BringWindowToTop(hwndSelCapDrvDlg);  

        return DefWindowProc(hMain, msg, wParam, lParam);  

    case WM_CREATE:  

        // 注册错误提示回调函数  

        capSetCallbackOnError(hwndVideo, (FARPROC)ErrorCallbackProc);  

        // 主窗口主要圆角矩形区域  

        hRoundRgn = CreateRoundRectRgn(100, 70, 500, 460, 20, 20);  

        // 捕捉视频区域s  

        hwndVideo = capCreateCaptureWindow((LPSTR)"My Capture Window",  

            WS_CHILD|WS_VISIBLE,  

            140, 100, 320, 280,  

            (HWND)hMain,  

            (int)1);  

        hwndExit = CreateWindow("button",    // 建立一个按钮,更多如BUTTON,COMBOBOX,LISTBOX  

            "x",    // button text  

            WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON|BS_CENTER|BS_VCENTER,  

            470, 75, BUTTONSIZE, BUTTONSIZE,  

            hMain,  

            (HMENU)EXIT,  

            (HINSTANCE)ghInstance,  

            (LPVOID)NULL );  

        hwndMin = CreateWindow("button",    // 建立一个按钮,更多如BUTTON,COMBOBOX,LISTBOX  

            "-",    // button text  

            450, 75, BUTTONSIZE, BUTTONSIZE,  

            (HMENU)MINIMIZE,  

        hwndHelp = CreateWindow("button",    // 建立一个按钮,更多如BUTTON,COMBOBOX,LISTBOX  

            "?",    // button text  

            WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON/*|BS_CENTER|BS_VCENTER*/,  

            430, 75, BUTTONSIZE, BUTTONSIZE,  

            (HMENU)HELP,  

        hwndPhoto = CreateWindow("button",  

            "照 相",  

            WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,  

            150, 410, 50, 20,  

            (HMENU)PHOTO,  

        SendMessage(hwndPhoto, WM_SETFONT, (WPARAM)hFont, 1);  // 设置按钮字体为系统默认字体  

        hwndRecord = CreateWindow("button",  

            "录 像",  

            WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|BS_VCENTER|BS_CENTER,  

            220, 410, 50, 20,  

            (HMENU)RECORDVIDEO,  

        SendMessage(hwndRecord, WM_SETFONT, (WPARAM)hFont, 1);// 设置按钮字体为系统默认字体  

        hwndBtnExit = CreateWindow("button",   // 退出按钮  

            "退 出",  

            400, 410, 50, 20,  

        SendMessage(hwndBtnExit, WM_SETFONT, (WPARAM)hFont, 1);  

        // 设置按钮区域  

        GetClientRect(hwndHelp, &helpRect);  

        GetClientRect(hwndMin, &minRect);  

        GetClientRect(hwndExit, &exitRect);  

        helpRgn = CreateEllipticRgnIndirect(&helpRect);  

        minRgn = CreateEllipticRgnIndirect(&minRect);  

        exitRgn = CreateEllipticRgnIndirect(&exitRect);  

        SetWindowRgn(hwndExit,exitRgn,1);  

        SetWindowRgn(hwndMin,minRgn,1);                               

        SetWindowRgn(hwndHelp,helpRgn,1);  

        // 创建选择驱动对话框  

        hwndSelCapDrvDlg = CreateDialog((HINSTANCE)ghInstance,  

            MAKEINTRESOURCE(DLG_SELCAPDRIVER),  

            0, (DLGPROC)SelCapDrcProc);  

        hwndSelCapDrvLBox = GetDlgItem(hwndSelCapDrvDlg, LISTBOX_SELCAPDRIVER);  

        EnumCapDrv();  

    case WM_COMMAND:  

        CAPSTATUS capStatus;  

        switch(wParam)  

        case EXIT:  // 退出系统  

            SendMessage(hMain, WM_SYSCOMMAND, SC_CLOSE, 0);  

            break;  

        case MINIMIZE: // 最小化  

            SendMessage(hMain, WM_SYSCOMMAND, SC_MINIMIZE, 0);  

        case HELP:  // 帮助按钮  

            SendMessage(hMain, WM_SYSCOMMAND, SC_CONTEXTHELP, 0);  

        case RESOURCE: // 视频源选项  

            if (capDrvCaps.fHasDlgVideoSource)  

            {  

                capDlgVideoSource(hwndVideo);  

            }  

        case FORMAT:  // 视频格式选项  

            if (capDrvCaps.fHasDlgVideoFormat)  

                capDlgVideoFormat(hwndVideo);  

        case CONNECT:  

        case DISPLAY: // 视频显示选项  

            if (capDrvCaps.fHasDlgVideoDisplay)  

                capDlgVideoDisplay(hMain);  

                capGetStatus(hwndVideo, &capStatus, sizeof(CAPSTATUS));// 得到当前捕获窗口的状态  

                SetWindowPos(hwndVideo, NULL, 0, 0, capStatus.uiImageWidth, capStatus.uiImageHeight, SWP_NOZORDER|SWP_NOMOVE);  

        case PHOTO:  // 抓取图片  

            if ( capFileSaveDIB(hwndVideo, "test.bmp") ){  

                MessageBox(hMain, "Save Bmp File Succeeded!", "photo save", MB_OK|MB_ICONINFORMATION);  

            else break;  

            if (!bPhotoFileOpen)  

                OPENFILENAME ofnp;  // open file name structure  

                ZeroMemory(&ofnp, sizeof(OPENFILENAME));  

                ofnp.lStructSize = sizeof(OPENFILENAME);  

                ofnp.hwndOwner = hMain;  

                ofnp.lpstrFile = photoFile;  

                ofnp.lpstrFilter = "*.bmp";  

                ofnp.nMaxFile = sizeof(photoFile);  

                ofnp.nFilterIndex = 1;  

                ofnp.nMaxFileTitle = 0;  

                ofnp.lpstrInitialDir = NULL;  

                ofnp.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;  

                // 显示保存文件对话框  

                if (GetSaveFileName(&ofnp) == TRUE)  

                {  

                    bPhotoFileOpen = TRUE;  

                    strcpy(photoFile, ofnp.lpstrFile);  

                    strcat(photoFile, ".bmp");  

                    capDriverConnect(hwndPhoto, 0);  // 与驱动连接  

                    capOverlay(hwndPhoto, TRUE); // //使用 hardware overlay   

                    //使 video input directlyinto framebuffer,使不用 CPU  

                    capPreview(hwndVideo, TRUE);  // 抓取图像显示在视窗  

                    capPreviewScale(hwndVideo, TRUE); // 使图像延伸到所设定的视窗大小  

                    capPreviewRate(hwndVideo, 1000/30); // 每秒图像变化张数  

                    capPreview(hwndVideo, TRUE); // 预览图像显示  

                    capGrabFrameNoStop(hwndVideo);  

                    capEditCopy(hwndVideo);  

                    if (capFileSaveDIB(hwndVideo, photoFile)){  

                        MessageBox(hMain, "Save Bmp File Succeeded!", "photo save", MB_OK|MB_ICONINFORMATION);  

                    }  

                    break;  

                }  

        case RECORDVIDEO:  // 录制视频  

            if (HIWORD(wParam) == BN_CLICKED && (HWND)lParam == hwndRecord)  

                OPENFILENAME ofnp;  

                if (!bRecordFileOpen)  

                    ZeroMemory(&ofnp, sizeof(OPENFILENAME));  

                    ofnp.lStructSize = sizeof(OPENFILENAME);  

                    ofnp.nMaxFile = sizeof(recordFile);  

                    ofnp.hwndOwner = hMain;  

                    ofnp.lpstrFile = recordFile;  

                    ofnp.lpstrFilter = "*.avi";  

                    ofnp.lpstrInitialDir = NULL;  

                    ofnp.nFilterIndex = 1;  

                    ofnp.lpstrFileTitle = NULL;  

                    ofnp.nMaxFileTitle = 0;  

                    ofnp.Flags = OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST;  

                    // 显示保存文件对话框  

                    if (GetSaveFileName(&ofnp) == TRUE)  

                    {  

                        strcpy(recordFile, ofnp.lpstrFile);  

                        strcat(recordFile, ".avi");  

                        bRecordFileOpen = TRUE;  

                        // 创建视频采集线程  

                        DWORD id;  

                        SECURITY_ATTRIBUTES sa;  

                        sa.nLength = sizeof(SECURITY_ATTRIBUTES);  

                        sa.lpSecurityDescriptor = NULL;  

                        sa.bInheritHandle = TRUE;  

                        hVideoTread = CreateThread(&sa,  

                            (ULONG)0,  

                            (LPTHREAD_START_ROUTINE)VideoThreadProc,  

                            (LPVOID)(ULONG)0,  

                            0,  

                            &id);  

                        // 如果创建线程失败,弹出提示对话框  

                        if (hVideoTread == NULL)  

                        {  

                            MessageBox(NULL, "Video Thread Create Failure!", "Thread", MB_OK|MB_ICONINFORMATION);     

                        }  

                if (bRecordFileOpen)  // 已经打开一个选择对话框  

                    if (bRecording)  // 已经在录制视频中  

                        bThreadEnd = true;  

                        // 结束录制,并保存  

                        if ( capFileSaveAs(hwndVideo, recordFile) ){  

                            MessageBox(NULL, "Save Avi File Succeeded!", "RecordVideo", MB_OK|MB_ICONINFORMATION);  

                        SetWindowText(hwndRecord, "录 像");  

                        bRecording = false;  

                        break;  

                    else  // 没有录像但是选择了一个文件  

                        int rt = 0;  

                        rt = MessageBox(hMain, "Do you want write over that file?", "系统提示", MB_YESNO|MB_ICONINFORMATION);  

                        if (rt == IDYES)  // 继续录制,覆盖当前文件  

                        {     

                            if (capCaptureSequence(hwndRecord))  

                            {  

                                bRecording = true;  

                                SetWindowText(hwndRecord, "停 止");  

                            }     

                        else  

                            bRecordFileOpen = false;  

                            SendMessage(hMain, WM_COMMAND, MAKEWPARAM(RECORDVIDEO, BN_CLICKED), (LPARAM)hwndRecord);  

                }     

    case WM_DESTROY:  

        capSetCallbackOnError(hwndVideo, NULL);  

        capPreview(hwndVideo, FALSE); // 停止预览  

        capCaptureAbort(hwndVideo);  // 停止捕获  

        capDriverDisconnect(hwndVideo); // 断开驱动连接  

        PostQuitMessage(0);  

    default:  

    return 0;  

LRESULT WINAPI SelCapDrcProc( HWND hMian, UINT msg, WPARAM wParam, LPARAM lParam )  

//  ShowWindow(hwndSelCapDrvDlg, SW_SHOW);  

    case WM_INITDIALOG:  

        return TRUE;  

        case BTN_SEL:  

            int sel = 0;  

            SendMessage(hwndSelCapDrvLBox, LB_GETSELITEMS, 1, sel );  // 获取选择的驱动  

            SendMessage(hwndVideo, WM_CAP_DRIVER_CONNECT, sel, 0L);   // 连接驱动  

            SendMessage(hwndSelCapDrvDlg, WM_CLOSE, 0, 0);   // 关闭对话框  

            SendMessage(hwndVideo, WM_CAP_DRIVER_GET_CAPS, sizeof(CAPDRIVERCAPS), (long)(LPVOID)&capDrvCaps); // 更新驱动的能力  

            if (capDrvCaps.fHasOverlay)  

                capOverlay(hwndVideo, TRUE);  

            capPreviewRate(hwndVideo, 66);   //设置视频捕获速率提高到66 miliseconds  

            if ( !capPreview(hwndVideo, TRUE))   //用CapPreview启动预览功能  

                MessageBox(NULL, "预览启动失败", "提示", MB_OK|MB_ICONINFORMATION);  

                SendMessage(hMian, WM_COMMAND, EXIT, 0);  

                return FALSE;  

    case WM_CLOSE:  

        DestroyWindow(hwndSelCapDrvDlg);  

    return (0L);  

int EnumCapDrv()  

    char drvName[100];  

    char drvVesion[100];  

    char drvStr[200];  

    for (int i = 0; i < 5; i++)  // 扫面获取驱动信息  

        if ( capGetDriverDescription(i, drvName, sizeof(drvName), drvVesion, sizeof(drvVesion)) )  

            strcpy(drvStr, drvName);  

            strcat(drvStr, "  ");  

            strcat(drvStr, drvVesion);  

            SendMessage(hwndSelCapDrvLBox, LB_ADDSTRING, 0, (LPARAM)drvStr); // 向列表框增加字符串  

            SendMessage(hwndSelCapDrvLBox, LB_SETITEMDATA, i, (LPARAM)i);  

VOID APIENTRY HandlePopupMenu( HWND hwnd, POINT pt )  

    HMENU hmenu;  

    HMENU hPopupMenu;  

    hmenu = LoadMenu((HINSTANCE)ghInstance, MAKEINTRESOURCE(IDR_POPUPMENU));  

    if(hmenu == NULL) return;  

    // 获取子菜单  

    hPopupMenu = GetSubMenu(hmenu, 0);  

    // 弹出菜单使用屏幕坐标,所以转换鼠标点击坐标到屏幕坐标  

    ClientToScreen(hwnd, &pt);  

    TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hwnd, NULL);  

    DestroyMenu(hmenu); // 销毁指定菜单,并释放此菜单占用的内存  

WORD WINAPI VideoThreadProc( LPVOID lParam )  

    // 捕获视频  

    if( capCaptureSequence(hwndVideo) ) //该函数调控启动流视频和音频捕获到一个文件,你能使用这个功能发送消息  

        SetWindowText(hwndRecord, "停 止");  

        MessageBox(NULL, "Start to capture video.", "提示", MB_OK|MB_ICONINFORMATION);  

        bRecording = true;  

    while(!bThreadEnd);  

    MessageBox(NULL, "Leaving Record Thread", "Thread",NULL);  

继续阅读