楊舒凱的個人網頁
http://shukaiyang.myweb.hinet.net/ English   繁體中文
  自介與新消息     個人作品集     程式開發工具     線上教學課程     免費下載  
  簡介與下載   程式介面文件   範例程式碼

Video Grabber Library

這是簡單的 MFC 對話盒應用程式 vdoview.exe. 在 stdafx.h 與 vdoview.h 檔案當中都是些尋常的 MFC 典型程式碼, 幾乎所有的工作都是在 vdoview.cpp 完成的. 在底下的範例程式碼當中, 相關的述句都已經以黑色的粗體字標示.

在 CVideoApp::InitInstance( ) 呼叫了 CoInitialize(NULL) 以便啟用系統中的 COM 物件, 然後在 CVideoDlg::OnInitDialog( ) 中呼叫了 GrabberOpen( ) 來連接 camera 並指定 callback 函式GrabberCallback( ). 在 CVideoDlg 類別當中準備了一個 bitmap header 以便描繪接收到的影像. 所以當 Start 按鈕被按下, GrabberStart( ) 被呼叫以後, 這個 callback function 就會持續地收到影像, 所以它把影像複製到 pDlg->pBits 並且要求重繪畫面.

vdoview.h

/** @file vdoview.h
  * @brief Declarations.

  * The file declares the dialog and application classes of this dialog-based
    program that demonstrates the usage of vdograb.lib.

  * @author Shu-Kai Yang (http://shukaiyang.myweb.hinet.net/)
  * @date 2006/11/25 */

#include "resource.h" // main symbols

#define DEVICE_NAME NULL
// #define DEVICE_NAME L"USB 2.0 1.3M UVC WebCam"

class CVideoApp : public CWinApp
{
    // Overrides
    public:
    virtual BOOL InitInstance();

    // Implementation:
    DECLARE_MESSAGE_MAP()
};

// CVideoDlg dialog
class CVideoDlg : public CDialog
{
    public:
    // Dialog Data:
    enum { IDD = IDD_VDOVIEW_DIALOG };

    BITMAPINFOHEADER header;
    LPBYTE pBits;

    protected:
    HICON m_hIcon;

    // Construction
    public:
    CVideoDlg(CWnd * pParent = NULL);

    // Implementation
    protected:
    // Generated message map functions
    virtual BOOL OnInitDialog();
    afx_msg void OnDestroy();
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnBnClickedStart();
    afx_msg void OnBnClickedStop();
    DECLARE_MESSAGE_MAP()
};

vdoview.cpp

/** @file vdoview.cpp
 * @brief Implementations.

 * The file implements the dialog and application classes of the dialog-based
   application that demonstrates the usage of vdograb.dll. When the dialog is
   being initialized, it opened the video-capturing device (web camera). Then
   when the user clicks the "Start" button, the dialog receives the captured
   images via the callback function and renders the images. 

 * @author Shu-Kai Yang (http://shukaiyang.myweb.hinet.net/)
 * @date 2006/11/26 */

#include "stdafx.h"
#include "vdoview.h"
#include "../vdograb/vdograb.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// The one and only CVideoApp object:
CVideoApp theApp;
void GrabberCallback(void *, int, int, int);

// CVideoApp message map:
BEGIN_MESSAGE_MAP(CVideoApp, CWinApp)
END_MESSAGE_MAP()

// CVideoApp initialization"
BOOL CVideoApp::InitInstance()
{
    // Typical MFC initializations:
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);

    CWinApp::InitInstance();
    CoInitialize(NULL);

    // Disaplay a dialog and set it the main window of the application:
    CVideoDlg dlg;
    m_pMainWnd = &dlg;
    dlg.DoModal();

    CoUninitialize();
    return FALSE;
}

// CVideoDlg dialog
CVideoDlg::CVideoDlg(CWnd * pParent) : CDialog(CVideoDlg::IDD, pParent), pBits(NULL)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

    // Fill the dummy bitmap header for DIB rendering:
    header.biSize = sizeof(BITMAPINFOHEADER);
    header.biPlanes = 1;
    header.biBitCount = 24;
    header.biCompression = BI_RGB;
    header.biXPelsPerMeter = 120;
    header.biYPelsPerMeter = 120;
    header.biClrUsed = 0;
    header.biClrImportant = 0;
}

BEGIN_MESSAGE_MAP(CVideoDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_START, &CVideoDlg::OnBnClickedStart)
ON_BN_CLICKED(IDC_STOP, &CVideoDlg::OnBnClickedStop)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


// CVideoDlg message handlers:
BOOL CVideoDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Set the icon for this dialog:
    SetIcon(m_hIcon, TRUE);
    SetIcon(m_hIcon, FALSE);

    // Enable the video capturing at beginning:
    if (GrabberOpen(DEVICE_NAME, GrabberCallback) == FALSE)
    {  AfxMessageBox(L"Can not open the camera device!", MB_ICONSTOP | MB_OK);
    return FALSE; }

    return TRUE;
}

void CVideoDlg::OnDestroy()
{
    // Stop the video capturing when closing the window:
    GrabberClose();
    if (pBits) {  delete pBits;  }

    CDialog::OnDestroy();
}

// The system calls this function to obtain the cursor to display
// while the user drags the minimized window.
HCURSOR CVideoDlg::OnQueryDragIcon()
{   return static_cast<HCURSOR>(m_hIcon);  }

void CVideoDlg::OnBnClickedStart()
{
    if(GrabberStart() == FALSE)
    {   AfxMessageBox(L"Can not start the video capturing!", MB_ICONSTOP | MB_OK);  }
}

void CVideoDlg::OnBnClickedStop()
{   GrabberStop();  }

void CVideoDlg::OnPaint()
{
    CRect rect;

    if (IsIconic())
    {
        // If you add a minimize button to your dialog, you will need the code below to draw the
        // icon. For MFC applications using the document/view model, this is automatically done
        // for you by the framework.
        CPaintDC dc(this);
        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // Center icon in client rectangle:
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);

        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon:
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();

        // The captured data is already a bottom-up DIB image, so stretch it:
        CWnd * pCanvas = GetDlgItem(IDC_CANVAS);
        if((pCanvas) && (pBits))
        {
            CPaintDC dc(pCanvas);
            dc.SetStretchBltMode(HALFTONE);
            pCanvas->GetClientRect(&rect);
            ::StretchDIBits(dc.GetSafeHdc(), 0, 0, rect.Width(), rect.Height(),
                0, 0, header.biWidth, header.biHeight, pBits, (BITMAPINFO *)&header,
                DIB_RGB_COLORS, SRCCOPY);
        }
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Callback Function for the Library:
void GrabberCallback(void * pBits, int width, int height, int size)
{
    // Get the dialog window and Retrieve the canvas window for rendering:
    CVideoDlg * pDlg = (CVideoDlg *)(theApp.m_pMainWnd);
    if(pDlg == NULL) { return; }

    TRACE(L"GrabberCallback(%dx%d, %d bytes)\n", width, height, size);

    // Fill bitmap header for DIB rendering:
    pDlg->header.biWidth = width;
    pDlg->header.biHeight = height;
    pDlg->header.biSizeImage = size;

    // Copy the pixels to the dialog, allocating the memory when necessary:
    if (pDlg->pBits == NULL) { pDlg->pBits = new BYTE[size]; }
    if (pDlg->pBits) { memcpy(pDlg->pBits, pBits, size); }
    pDlg->Invalidate(FALSE);
}

Last updated at 2006 / 11 / 27 by Shu-Kai Yang.

您是自2008年1月以來的第 位訪客.