2013年3月22日星期五

基于DirectX的VC++的视频采集。(DirectX与VC部分)


既然Java的JMF只有VFW的方式采集视频卡(我目前没发现其他的,也许有吧),但是提供了很强大的JNI接口,并且JMF的示例代码中,有各种平台视频捕捉的示例。下面是一个完整的Java+VC DLL实现的例子。
本篇分成如下几步:
一。 DirectShow环境配置。
二。 VC++的DirectX采集视频的独立程序
三。 VC++程序DLL封装
四。 Java通过JNI接口调用DLL


一。DirectX环境配置方法如下:
1。先从http://hotdl.com/dl/showfile.php?id=640&category=52下载Direct Show 9.0b或者以下版本,因为9.0c只有的DirectX将DSHOW分离出去了,不包含所需要的文件。
2。 在项目中包含所需要的头文件,顺利别弄错:
#include <streams.h>
#include <atlbase.h>
#include <dshow.h>
#include <windows.h>
#include <qedit.h>
3。 在VC的菜单中选择Project|Settings|Link,增加需要使用到的库
quartz.lib strmbasd.lib strmiids.lib winmm.lib uuid.lib
注 意,使用空格分开(很久没用VC了,用逗号,分号都不好用,猜了好半天,呵呵)。DirectShow SDK建议,DirectShow应用程序应该至少连接库文件strmiids.lib和quartz.lib。前者定义了DirectShow标准的 CLSID和IID,后者定义了导出函数AMGetErrorText(如果应用程序中没有使用到这个函数,也可以不连接这个库)。如果程序里包含了头文 件streams.h,则一般库文件还要连接strmbasd.lib、uuid.lib、winmm.lib。
4。 将DirectX SDK的Include和Lib目录配置到VC的系统目录中去,并且放在标准的VC目录之前,以保证编译器能够拿到最新版本的源文件。选择 Tools|Options|Directories,在弹出的对话框中的Show directories for中选择Include files,配置如下(假设DirectX SDK安装在D:\DXSDK目录下,VC安装在C:\Program Files下):
    D:\DXSDK\Include
    D:\DXSDK\SAMPLES\C++\DIRECTSHOW\BASECLASSES  //如果将生成的
strmbasd.lib拷到include目录下,即可不要此路径
    D:\DXSDK\SAMPLES\C++\COMMON\INCLUDE  //可要可不要
    C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE
    C:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE
    C:\Program Files\Microsoft Visual Studio\VC98\ATL\INCLUDE
再在Show directories for中选择Library files,配置如下:
    D:\DXSDK\Lib
    D:\DXSDK\SAMPLES\C++\DIRECTSHOW\BASECLASSES\DEBUG
    D:\DXSDK\SAMPLES\C++\DIRECTSHOW\BASECLASSES\RELEASE
    C:\PROGRAM FILES\MICROSOFT SDK\LIB
    C:\Program Files\Microsoft Visual Studio\VC98\LIB
    C:\Program Files\Microsoft Visual Studio\VC98\MFC\LIB

5。 配置时的问题【一定要注意】
1)include和lib的路径前后顺序一定要“非常严格按照上面顺序排列”,否则
  1.1 DXSDK\Include和VC98\INCLUDE有头文件名是重名的,例如control.h,strmif.h。所以要优先选择DXSDK的文件声明。
  2.1 DXSDK\Lib和VC98\LIB对 DWORD_PTR 这个数据类型的声明顺序出现编译上连接的歧异!!!!
2)BASECLASSES\DEBUG 和BASECLASSES\RELEASE目录和目录里面是内容是没有的,如果你在应用程序中使用了BASECLASSES里面的 class,function,filter,interface,就要先用VC编译baseclasses.dsw,编译时请分别选定DEBUG和 RELEASE,因为baseclasses.dsw有4个版本,而且默认下都不是DEBUG和RELEASE。编译后生成两个重要文 件:strmbasd.lib(Debug),STRMBASE.lib(Release),在以后将用到。

6。这个时候编译DirectShow的程序,可能会出现以下错误:
   --------------------Configuration: vdclient - Win32 Debug--------------------
Compiling...
CDXGraph.cpp
c:\dxsdk\include\strmif.h(1018) : error C2146: syntax error : missing ';' before identifier 'HSEMAPHORE'
c:\dxsdk\include\strmif.h(1018) : fatal error C1004: unexpected end of file found

解决的办法是,将#include "c:\dxsdk\include\strmif.h"加入VC的"stdafx.h"文件中
编译运行,如果成功的话,再把#include "c:\dxsdk\include\strmif.h"从"stdafx.h"中删除掉

二。 VC++的DirectX采集视频的独立程序
新建一个基于Dialog的MFC的exe工程,参考http://www.programfan.com/article/showarticle.asp?id=2868,基本上就能实现了。
这里将我调试过的程序也贴出来,留个笔记。

对话框添加一个下拉列表框(IDC_COMBO)、两个按钮(IDC_CAPTURE、IDC_BUTTON1)和一个Picture控件(ID:IDC_STATIC_SCREEN),
成员变量为:
CStatic m_staticScreen; // IDC_STATIC_SCREEN
CComboBox m_ListCtrl; // IDC_COMBO
下面是程序(CaptureVideo类实现捕捉,内嵌了一个CSampleGrabberCB类;CCaptureVideoDlg是显示界面)

// CaptureVideo.h : main header file for the CAPTUREVIDEO application
//
#if !defined(AFX_CAPTUREVIDEO_H__552A7044_3272_4219_9D11_8F3FB2606F66__INCLUDED_)
#define AFX_CAPTUREVIDEO_H__552A7044_3272_4219_9D11_8F3FB2606F66__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#ifndef __AFXWIN_H__
 #error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h"  // main symbols
#include <streams.h>
#include <atlbase.h>
#include <dshow.h>
#include <windows.h>
#include <qedit.h>
#include "Tlhelp32.h"
//#include <olectl.h>
//#include <ddraw.h>

#ifndef SAFE_RELEASE
#define SAFE_RELEASE( x ) \
if ( NULL != x ) \
{ \
x->Release( ); \
x = NULL; \
}
#endif

/////////////////////////////////////////////////////////////////////////////
// CCaptureVideo:
// See CaptureVideo.cpp for the implementation of this class
//
class CSampleGrabberCB;
class CCaptureVideo : public CWinApp
{
public:
 friend class CSampleGrabberCB;
   
public:
 void GrabOneFrame(BOOL bGrab);
 HRESULT Init(int iDeviceID,HWND hWnd);
 int EnumDevices(HWND hList);
 CCaptureVideo();
 virtual ~CCaptureVideo();
 bool   CCaptureVideo::CloseApplication(CString   sAppToClose,   CString   sAppToUpdate,    
      CString   sFilename);
private:
 HWND m_hWnd;
 IGraphBuilder *m_pGB;
 ICaptureGraphBuilder2* m_pCapture;
 IBaseFilter* m_pBF;
 IMediaControl* m_pMC;
 IVideoWindow* m_pVW;
 CComPtr<ISampleGrabber> m_pGrabber;
protected:
 void FreeMediaType(AM_MEDIA_TYPE& mt);
 bool BindFilter(int deviceId, IBaseFilter **pFilter);
 void ResizeVideoWindow();
 HRESULT SetupVideoWindow();
 HRESULT InitCaptureGraphBuilder();

// Overrides
 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CCaptureVideo)
 public:
 virtual BOOL InitInstance();
 //}}AFX_VIRTUAL
// Implementation
 //{{AFX_MSG(CCaptureVideo)
  // NOTE - the ClassWizard will add and remove member functions here.
  //    DO NOT EDIT what you see in these blocks of generated code !
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CAPTUREVIDEO_H__552A7044_3272_4219_9D11_8F3FB2606F66__INCLUDED_)
// CaptureVideo.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "CaptureVideo.h"
#include "CaptureVideoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CCaptureVideo
BEGIN_MESSAGE_MAP(CCaptureVideo, CWinApp)
 //{{AFX_MSG_MAP(CCaptureVideo)
  // NOTE - the ClassWizard will add and remove mapping macros here.
  //    DO NOT EDIT what you see in these blocks of generated code!
 //}}AFX_MSG
 ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCaptureVideo construction
BOOL bOneShot=FALSE;//全局变量
class CSampleGrabberCB : public ISampleGrabberCB {
 public:
  long lWidth;
  long lHeight;
  TCHAR m_szFileName[MAX_PATH];// 位图文件名称
  CSampleGrabberCB( )//constructor
  {
   strcpy(m_szFileName, "c:\\donaldo.bmp");
  }
  //run only once when init
  STDMETHODIMP_(ULONG) AddRef() {return 2;}
  //not run
  STDMETHODIMP_(ULONG) Release() { return 1; }
  //not run
  STDMETHODIMP QueryInterface(REFIID riid, void ** ppv){
   if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ){ 
    *ppv = (void *) static_cast<ISampleGrabberCB*> ( this );
    return NOERROR;
   } 
   return E_NOINTERFACE;
  }
  //not run
  STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample ){
   return 0;
  }
  //this function runs in a seperate thread when started.
  STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize ){
   if( !bOneShot )return 0;
   if (!pBuffer)return E_POINTER;
   SaveBitmap(pBuffer, lBufferSize);
   bOneShot = FALSE;
   return 0;
  }
  //创建位图文件
  BOOL SaveBitmap(BYTE * pBuffer, long lBufferSize )
  {
   HANDLE hf = CreateFile(
   m_szFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
   CREATE_ALWAYS, NULL, NULL );
   if( hf == INVALID_HANDLE_VALUE )return 0;
   // 写文件头 
   BITMAPFILEHEADER bfh;
   memset( &bfh, 0, sizeof( bfh ) );
   bfh.bfType = 'MB';
   bfh.bfSize = sizeof( bfh ) + lBufferSize + sizeof( BITMAPINFOHEADER );
   bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );
   DWORD dwWritten = 0;
   WriteFile( hf, &bfh, sizeof( bfh ), &dwWritten, NULL );
   // 写位图格式
   BITMAPINFOHEADER bih;
   memset( &bih, 0, sizeof( bih ) );
   bih.biSize = sizeof( bih );
   bih.biWidth = lWidth;
   bih.biHeight = lHeight;
   
   bih.biPlanes = 1;
   bih.biBitCount = 24;
   WriteFile( hf, &bih, sizeof( bih ), &dwWritten, NULL );
   // 写位图数据
   WriteFile( hf, pBuffer, lBufferSize, &dwWritten, NULL );
   CloseHandle( hf );
   return 0;
  }
};
CSampleGrabberCB mCB;
//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCaptureVideo::CCaptureVideo()
{//COM Library Intialization
 if(FAILED(CoInitialize(NULL))) /*, COINIT_APARTMENTTHREADED)))*/
 {
  AfxMessageBox("CoInitialize Failed!\r\n");
  return;
 }
 m_hWnd = NULL;
 m_pVW = NULL;
 m_pMC = NULL;
 m_pGB = NULL;
 m_pCapture = NULL;
}
CCaptureVideo::~CCaptureVideo()
{
 // Stop media playback
 if(m_pMC)m_pMC->Stop();
 if(m_pVW){
  m_pVW->put_Visible(OAFALSE);
  m_pVW->put_Owner(NULL);
 }
 SAFE_RELEASE(m_pCapture);
 SAFE_RELEASE(m_pMC);
 SAFE_RELEASE(m_pGB);
 SAFE_RELEASE(m_pBF);
 CoUninitialize( );
}
int CCaptureVideo::EnumDevices(HWND hList)
{
 if (!hList)
 return -1;
 int id = 0;
 //枚举视频扑捉设备
 ICreateDevEnum *pCreateDevEnum;
 HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);
 if (hr != NOERROR)return -1;
 CComPtr<IEnumMoniker> pEm;
 hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
 if (hr != NOERROR)return -1;
 pEm->Reset();
 ULONG cFetched;
 IMoniker *pM;
 while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
 {
   IPropertyBag *pBag;
   hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
   if(SUCCEEDED(hr)) 
   {
    VARIANT var;
    var.vt = VT_BSTR;
    hr = pBag->Read(L"FriendlyName", &var, NULL);
    if (hr == NOERROR)
    {
     TCHAR str[2048];
     id++;
     WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1, str, 2048, NULL, NULL);
     ::SendMessage(hList, CB_ADDSTRING, 0,(LPARAM)str);
     SysFreeString(var.bstrVal);
    }
    pBag->Release();
   }
   pM->Release();
 }
 return id;
}
HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
{
 HRESULT hr;
 hr = InitCaptureGraphBuilder();
 if (FAILED(hr)){
  AfxMessageBox("Failed to get video interfaces!");
  return hr;
 }
 // Bind Device Filter. We know the device because the id was passed in
 if(!BindFilter(iDeviceID, &m_pBF))return S_FALSE;
 hr = m_pGB->AddFilter(m_pBF, L"Capture Filter");
 // hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, 
 // m_pBF, NULL, NULL);
 // create a sample grabber
 hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
 if( !m_pGrabber ){
  AfxMessageBox("Fail to create SampleGrabber, maybe qedit.dll is not registered?");
  return hr;
 }
 CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
 //设置视频格式
 AM_MEDIA_TYPE mt; 
 ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
 mt.majortype = MEDIATYPE_Video;
 mt.subtype = MEDIASUBTYPE_RGB24;
 hr = m_pGrabber->SetMediaType(&mt);
 if( FAILED( hr ) ){
  AfxMessageBox("Fail to set media type!");
  return hr;
 }
 hr = m_pGB->AddFilter( pGrabBase, L"Grabber" );
 if( FAILED( hr ) ){
  AfxMessageBox("Fail to put sample grabber in graph");
  return hr;
 }
 // try to render preview/capture pin
 hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
 if( FAILED( hr ) )
 hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
 if( FAILED( hr ) ){
  AfxMessageBox("Can’t build the graph");
  return hr;
 }
 hr = m_pGrabber->GetConnectedMediaType( &mt );
 if ( FAILED( hr) ){
  AfxMessageBox("Failt to read the connected media type");
  return hr;
 }
 VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
 mCB.lWidth = vih->bmiHeader.biWidth;
 mCB.lHeight = vih->bmiHeader.biHeight;
 FreeMediaType(mt);
 hr = m_pGrabber->SetBufferSamples( FALSE );
 hr = m_pGrabber->SetOneShot( FALSE );
 hr = m_pGrabber->SetCallback( &mCB, 1 );
 //设置视频捕捉窗口
 m_hWnd = hWnd ; 
 SetupVideoWindow();
 hr = m_pMC->Run();//开始视频捕捉
  if(FAILED(hr)){AfxMessageBox("Couldn’t run the graph!");return hr;}
  return S_OK;
 }
bool CCaptureVideo::BindFilter(int deviceId, IBaseFilter **pFilter)
 {
 if (deviceId < 0)
 return false;
 // enumerate all video capture devices
 CComPtr<ICreateDevEnum> pCreateDevEnum;
 HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
 IID_ICreateDevEnum, (void**)&pCreateDevEnum);
 if (hr != NOERROR)
 {
  return false;
 }
 CComPtr<IEnumMoniker> pEm;
 hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
 if (hr != NOERROR)
 {
  return false;
 }
 pEm->Reset();
 ULONG cFetched;
 IMoniker *pM;
 int index = 0;
 while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= deviceId)
 {
  IPropertyBag *pBag;
  hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
  if(SUCCEEDED(hr)) 
  {
   VARIANT var;
   var.vt = VT_BSTR;
   hr = pBag->Read(L"FriendlyName", &var, NULL);
   if (hr == NOERROR)
   {
    if (index == deviceId)
    {
     pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);
    }
    SysFreeString(var.bstrVal);
   }
   pBag->Release();
  }
  pM->Release();
  index++;
 }
 return true;
}
HRESULT CCaptureVideo::InitCaptureGraphBuilder()
{
 HRESULT hr;
 //AfxMessageBox("1");
 // 创建IGraphBuilder接口
 hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB);
 // 创建ICaptureGraphBuilder2接口
 //AfxMessageBox("2");
 hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
 IID_ICaptureGraphBuilder2, (void **) &m_pCapture);
 if (FAILED(hr))return hr;
 m_pCapture->SetFiltergraph(m_pGB);
 hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
 if (FAILED(hr))return hr;
 hr = m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *) &m_pVW);
 if (FAILED(hr))return hr;
 return hr;
}
HRESULT CCaptureVideo::SetupVideoWindow()
{
 HRESULT hr;
 hr = m_pVW->put_Owner((OAHWND)m_hWnd);
 if (FAILED(hr))return hr;
 hr = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
 if (FAILED(hr))return hr;
 ResizeVideoWindow();
 hr = m_pVW->put_Visible(OATRUE);
 return hr;
}
void CCaptureVideo::ResizeVideoWindow()
{
 if (m_pVW){
  //让图像充满整个窗口
  CRect rc;
  ::GetClientRect(m_hWnd,&rc);
  m_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);
 } 
}
bool   CCaptureVideo::CloseApplication(CString   sAppToClose,   CString   sAppToUpdate,    
      CString   sFilename)  
  {  
   //   Declare   variables  
   HANDLE   hProcessSnap   =   NULL;  
   PROCESSENTRY32   pe32   =   {NULL};  
   CString   sCompare,   sTemp;  
   CString   sProcesFilename   =   "javaw.exe";//m_pPath->ExtractFilename(sFilename);  
//   CLanguage   *   pLanguage   =   CLanguage::Instance();  
   
   #if   (_MFC_VER   <   0x0700)  
   sProcesFilename.MakeLower();  
   #else  
   CString   sLowerTemp;  
   sLowerTemp   =   sProcesFilename;  
   sProcesFilename   =   sLowerTemp.MakeLower();  
   #endif  
   
   hProcessSnap   =   CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,   0);  
   
   pe32.dwSize   =   sizeof(PROCESSENTRY32);  
   if   (Process32First(hProcessSnap,   &pe32))  
   {  
     
  do{  
    sCompare.Format("%s",   pe32.szExeFile);  
   
    #if   (_MFC_VER   <   0x0700)  
    sCompare.MakeLower();  
    #else  
    CString   sLowerTemp;  
    sLowerTemp   =   sCompare;  
    sCompare   =   sLowerTemp.MakeLower();  
    #endif  
   
    //   Check   if   we   found   the   right   process  
     if   (sCompare   ==   sProcesFilename)  
     {  

    
   
     //   Get   handle   to   process  
     HANDLE   hProcess   =   OpenProcess  
     (PROCESS_ALL_ACCESS,   FALSE,   pe32.th32ProcessID);  
   
     //   Exit   process  
     DWORD   exCode;  
     GetExitCodeProcess(hProcess,   &exCode);  
     TerminateProcess(hProcess,   exCode);  
   
     //   Wait   until   process   is   finished  
     if   (WaitForSingleObject(hProcess,   30000)   ==   WAIT_TIMEOUT)  
     return   false;  
     }  
    }while(Process32Next(hProcessSnap,   &pe32));  
   }  
   else  
   {  
  return   false;  
   }  
   
   return   true;  
  }  
void CCaptureVideo::GrabOneFrame(BOOL bGrab)
{
 bOneShot = bGrab;
}
void CCaptureVideo::FreeMediaType(AM_MEDIA_TYPE& mt)
{
 if (mt.cbFormat != 0) {
  CoTaskMemFree((PVOID)mt.pbFormat);
  // Strictly unnecessary but tidier
  mt.cbFormat = 0;
  mt.pbFormat = NULL;
  }
  if (mt.pUnk != NULL) {
  mt.pUnk->Release();
  mt.pUnk = NULL;
 }
/////////////////////////////////////////////////////////////////////////////
// The one and only CCaptureVideo object
CCaptureVideo m_cap;
/////////////////////////////////////////////////////////////////////////////
// CCaptureVideo initialization
BOOL CCaptureVideo::InitInstance()
{
 AfxEnableControlContainer();
 // Standard initialization
 // If you are not using these features and wish to reduce the size
 //  of your final executable, you should remove from the following
 //  the specific initialization routines you do not need.
#ifdef _AFXDLL
 Enable3dControls();   // Call this when using MFC in a shared DLL
#else
 Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
 CCaptureVideoDlg dlg;
 m_pMainWnd = &dlg;
 int nResponse = dlg.DoModal();
 if (nResponse == IDOK)
 {
  // TODO: Place code here to handle when the dialog is
  //  dismissed with OK
 }
 else if (nResponse == IDCANCEL)
 {
  // TODO: Place code here to handle when the dialog is
  //  dismissed with Cancel
 }
 // Since the dialog has been closed, return FALSE so that we exit the
 //  application, rather than start the application's message pump.
 return FALSE;
}
// CaptureVideoDlg.h : header file
//
#if !defined(AFX_CAPTUREVIDEODLG_H__6A8D401D_0B75_43B6_B468_F7FE19BD116F__INCLUDED_)
#define AFX_CAPTUREVIDEODLG_H__6A8D401D_0B75_43B6_B468_F7FE19BD116F__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/////////////////////////////////////////////////////////////////////////////
// CCaptureVideoDlg dialog
class CCaptureVideoDlg : public CDialog
{
// Construction
public:
 CCaptureVideoDlg(CWnd* pParent = NULL); // standard constructor
   
// Dialog Data
 //{{AFX_DATA(CCaptureVideoDlg)
 enum { IDD = IDD_CAPTUREVIDEO_DIALOG };
 CStatic m_staticScreen;
 CComboBox m_ListCtrl;
 //}}AFX_DATA
 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CCaptureVideoDlg)
 protected:
 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
 //}}AFX_VIRTUAL
// Implementation
protected:
 HICON m_hIcon;
 // Generated message map functions
 //{{AFX_MSG(CCaptureVideoDlg)
 virtual BOOL OnInitDialog();
 afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
 afx_msg void OnPaint();
 afx_msg HCURSOR OnQueryDragIcon();
 virtual void OnOK();
 afx_msg void OnButton1();
 afx_msg void OnCapture();
 afx_msg void OnButton2();
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CAPTUREVIDEODLG_H__6A8D401D_0B75_43B6_B468_F7FE19BD116F__INCLUDED_)
// CaptureVideoDlg.cpp : implementation file
//
#include "stdafx.h"
#include "CaptureVideo.h"
#include "CaptureVideoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CCaptureVideo m_cap;
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
 CAboutDlg();
// Dialog Data
 //{{AFX_DATA(CAboutDlg)
 enum { IDD = IDD_ABOUTBOX };
 //}}AFX_DATA
 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CAboutDlg)
 protected:
 virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 //}}AFX_VIRTUAL
// Implementation
protected:
 //{{AFX_MSG(CAboutDlg)
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
 //{{AFX_DATA_INIT(CAboutDlg)
 //}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CAboutDlg)
 //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
 //{{AFX_MSG_MAP(CAboutDlg)
  // No message handlers
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCaptureVideoDlg dialog
CCaptureVideoDlg::CCaptureVideoDlg(CWnd* pParent /*=NULL*/)
 : CDialog(CCaptureVideoDlg::IDD, pParent)
{
 //{{AFX_DATA_INIT(CCaptureVideoDlg)
 //}}AFX_DATA_INIT
 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
// m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);


}
void CCaptureVideoDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CCaptureVideoDlg)
 DDX_Control(pDX, IDC_STATIC_SCREEN, m_staticScreen);
 DDX_Control(pDX, IDC_COMBO, m_ListCtrl);
 //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCaptureVideoDlg, CDialog)
 //{{AFX_MSG_MAP(CCaptureVideoDlg)
 ON_WM_SYSCOMMAND()
 ON_WM_PAINT()
 ON_WM_QUERYDRAGICON()
 ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
 ON_BN_CLICKED(IDC_CAPTURE, OnCapture)
 ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCaptureVideoDlg message handlers
BOOL CCaptureVideoDlg::OnInitDialog()
{
 CDialog::OnInitDialog();
 // Add "About..." menu item to system menu.
 // IDM_ABOUTBOX must be in the system command range.
// ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
// ASSERT(IDM_ABOUTBOX < 0xF000);
 CMenu* pSysMenu = GetSystemMenu(FALSE);
 if (pSysMenu != NULL)
 {
  CString strAboutMenu;
  strAboutMenu.LoadString(IDS_ABOUTBOX);
  if (!strAboutMenu.IsEmpty())
  {
   pSysMenu->AppendMenu(MF_SEPARATOR);
   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  }
 }
 // Set the icon for this dialog.  The framework does this automatically
 //  when the application's main window is not a dialog
// SetIcon(m_hIcon, TRUE);   // Set big icon
// SetIcon(m_hIcon, FALSE);  // Set small icon

 // TODO: Add extra initialization here
 // TODO: Add extra initialization here
 m_cap.EnumDevices (m_ListCtrl);
 m_ListCtrl.SetCurSel (0);

 return TRUE;  // return TRUE  unless you set the focus to a control
}
void CCaptureVideoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
 {
  CAboutDlg dlgAbout;
  dlgAbout.DoModal();
 }
 else
 {
  CDialog::OnSysCommand(nID, lParam);
 }
}
// 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.
void CCaptureVideoDlg::OnPaint()
{
 if (IsIconic())
 {
  CPaintDC dc(this); // device context for painting
  SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  // Center icon in client rectangle
  int cxIcon = GetSystemMetrics(SM_CXICON);
  int cyIcon = GetSystemMetrics(SM_CYICON);
  CRect rect;
  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 system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CCaptureVideoDlg::OnQueryDragIcon()
{
 return (HCURSOR) m_hIcon;
}
void CCaptureVideoDlg::OnOK()
{

 CDialog::OnOK();
}
void CCaptureVideoDlg::OnButton1()
{
 m_cap.GrabOneFrame(true);

}
void CCaptureVideoDlg::OnCapture()
{
 // TODO: Add your control notification handler code here
  //视频捕捉
 UpdateData();
 HWND hWnd = m_staticScreen.GetSafeHwnd() ;
 HRESULT hr = m_cap.Init(m_ListCtrl.GetCurSel (),hWnd);
 GetDlgItem(IDOK)->EnableWindow(FALSE);

}
void CCaptureVideoDlg::OnButton2()
{
 m_cap.CloseApplication("a","b","c");
 // TODO: Add your control notification handler code here

}

没有评论:

发表评论