既然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
}
没有评论:
发表评论