⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dxconstruction.cpp

📁 手掌采集程序
💻 CPP
字号:
// DXConstruction.cpp: implementation of the CDXConstruction class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "tryshot.h"
#include "tryshotDlg.h"
#include "DXConstruction.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDXConstruction::CDXConstruction()
{
	mBasicVideo=NULL;//
	mCGBer2=NULL;
	mEvent=NULL;//
	mGraph=NULL;//
	mMediaControl=NULL;//
	mSeeking=NULL;//
	mVideoWindow=NULL;//
	mSampleGrabber=NULL;//
	
	mObjectTableEntry=0;
	lWidth=640;
	lHeight=480;
}

CDXConstruction::~CDXConstruction()
{
	Release();
}

void CDXConstruction::Release()
{
	if (mBasicVideo)
	{
		mBasicVideo->Release();
		mBasicVideo=NULL;
	}
	if (mSampleGrabber)
	{
		mSampleGrabber->Release();
		mSampleGrabber=NULL;
	}
	if (mEvent)
	{
		mEvent->Release();
		mEvent=NULL;
	}
	
	if (mMediaControl) 
	{
		mMediaControl->Release();
		mMediaControl=NULL;
	}
	if (mSeeking)
	{
		mSeeking->Release();
		mSeeking=NULL;
	}
	if (mVideoWindow)
	{
		mVideoWindow->put_Visible(OAFALSE);
		mVideoWindow->put_MessageDrain((OAHWND)NULL);
		mVideoWindow->put_Owner(OAHWND(0));
		mVideoWindow->Release();
		mVideoWindow=NULL;
	}
	RemoveFromObjectTable();
	if (mCGBer2)
	{
		mCGBer2->Release();
		mCGBer2=NULL;
	}
	if (mGraph)
	{
		mGraph->Release();
		mGraph=NULL;
	}
}

void CDXConstruction::AddToObjectTable()
{
	IMoniker * pMoniker = 0;
    IRunningObjectTable * objectTable = 0;
    if (SUCCEEDED(GetRunningObjectTable(0, &objectTable))) 
	{
		WCHAR wsz[256];
		wsprintfW(wsz, L"FilterGraph %08p pid %08x", (DWORD_PTR)mGraph, GetCurrentProcessId());
		HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
		if (SUCCEEDED(hr)) 
		{
			hr = objectTable->Register(0, mGraph, pMoniker, &mObjectTableEntry);
			pMoniker->Release();
		}
		objectTable->Release();
	}
}

void CDXConstruction::RemoveFromObjectTable()
{
	IRunningObjectTable * objectTable = 0;
    if (SUCCEEDED(GetRunningObjectTable(0, &objectTable))) 
	{
        objectTable->Revoke(mObjectTableEntry);
        objectTable->Release();
		mObjectTableEntry = 0;
    }
}

BOOL CDXConstruction::Create()
{
	if (!mGraph)
	{
		if (SUCCEEDED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
			IID_IGraphBuilder, (void **)&mGraph)))
		{
			AddToObjectTable();

			return QueryInterfaces();
		}
		mGraph = 0;
	}
	return FALSE;
}

BOOL CDXConstruction::QueryInterfaces()
{
	if (mGraph)
	{
		HRESULT hr = NOERROR;
		hr |= mGraph->QueryInterface(IID_IMediaControl, (void **)&mMediaControl);
		//--------控制:run,pausing,stop......
		hr |= mGraph->QueryInterface(IID_IMediaEventEx, (void **)&mEvent);
		//--------    :事件提醒
		hr |= mGraph->QueryInterface(IID_IBasicVideo, (void **)&mBasicVideo);
		//            :用以设置视频属性
//		hr |= mGraph->QueryInterface(IID_IBasicAudio, (void **)&mBasicAudio);
		hr |= mGraph->QueryInterface(IID_IVideoWindow, (void **)&mVideoWindow);
		//            :设置视频窗口的宿主,位置,及其他属性
		//video render filter和filter graph manager都有这个接口,应用程序应该用filter graph的这个
		//当使用多个video render时,要使用render filter上的这个接口
		//使用video window作为子窗口的mfc程序必须定义一个空的WM_ERASEBKGND消息
		//否则子窗口绘制会发生错误
		//可以用CBaseVideoWindow类实现这个接口

		hr |= mGraph->QueryInterface(IID_IMediaSeeking, (void **)&mSeeking);
		//用以在视频流中定位
		if (mSeeking)
		{
			mSeeking->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME);
		}
		return SUCCEEDED(hr);
	}
	return FALSE;
}

BOOL CDXConstruction::RenderCaptureLink(ISampleGrabberCB *pCB)
{
	BOOL brlt=FALSE;
	IBaseFilter *pCap=NULL;
	if (GetCaptureDevice(&pCap))//采集设备
	{
		IBaseFilter *psgrdr=NULL;
		if (GetSGRdr(&psgrdr,pCB))//SampleRender
		{
			IBaseFilter *pNullRdr=NULL;
			if (GetNRdr(&pNullRdr))//Video_Render
			{
				if (Build_Capture_Graph(pCap,psgrdr,pNullRdr))//用CaptureGraphBuilder2构建捕捉链路
				{
					brlt=TRUE;
				}
				pNullRdr->Release();
			}
			psgrdr->Release();
		}
		pCap->Release();
	}
	return TRUE;
}

BOOL CDXConstruction::SetDisplayWindow(HWND inWindow)
{
	if (mVideoWindow)
	{
	//	long lVisible;
	//	mVideoWindow->get_Visible(&lVisible);
		// Hide the video window first
		mVideoWindow->put_Visible(OAFALSE);
		//----利用IVideoWindow接口的方法:
		//----设置窗口的可见性-----OAFALSE表示窗口隐藏
		HRESULT TPHR=mVideoWindow->put_Owner((OAHWND)inWindow);
		//--------------为video window设定视频在哪个窗口播放

		RECT windowRect;
		::GetClientRect(inWindow, &windowRect);
		//取得窗口大小
		mVideoWindow->put_Left(0);
		mVideoWindow->put_Top(0);
		mVideoWindow->put_Width(windowRect.right - windowRect.left);
		mVideoWindow->put_Height(windowRect.bottom - windowRect.top);
		mVideoWindow->put_WindowStyle(WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS);

		mVideoWindow->put_MessageDrain((OAHWND) inWindow);
		//指定video window向哪个窗口发送消息
		// Restore the video window
		if (inWindow != NULL)
		{
		//	mVideoWindow->put_Visible(lVisible);
			mVideoWindow->put_Visible(OATRUE);
		}
		else
		{
			mVideoWindow->put_Visible(OAFALSE);
		}
		return TRUE;
	}
	return FALSE;
}

BOOL CDXConstruction::SetNotifyWindow(HWND inWindow)
{
	if (mEvent)
	{
		mEvent->SetNotifyWindow((OAHWND)inWindow, WM_GRAPHNOTIFY, 0);
		return TRUE;
	}
	return FALSE;
}

BOOL CDXConstruction::Pause()
{
	if (mGraph && mMediaControl)
	{
		if (!IsPaused())
		{	
			if (SUCCEEDED(mMediaControl->Pause()))
			{
				return TRUE;
			}
		}
		else
		{
			return TRUE;
		}
	}
	return FALSE;
}

BOOL CDXConstruction::IsPaused()
{
	if (mGraph && mMediaControl)
	{
		OAFilterState state = State_Stopped;
		if (SUCCEEDED(mMediaControl->GetState(10, &state)))
		{
			return state == State_Paused;
		}
	}
	return FALSE;
}

BOOL CDXConstruction::Run()
{
	if (mGraph && mMediaControl)
	{
		if (!IsRunning())
		{
			if (SUCCEEDED(mMediaControl->Run()))
			{
				return TRUE;
			}
		}
		else
		{
			return TRUE;
		}
	}
	return FALSE;
}

BOOL CDXConstruction::IsRunning()
{
	if (mGraph && mMediaControl)
	{
		OAFilterState state = State_Stopped;
		if (SUCCEEDED(mMediaControl->GetState(10, &state)))
		{
			return state == State_Running;
		}
	}
	return FALSE;
}

BOOL CDXConstruction::Stop()
{
	if (mGraph && mMediaControl)
	{
		if (!IsStopped())
		{	
			if (SUCCEEDED(mMediaControl->Stop()))
			{
				return TRUE;
			}
		}
		else
		{
			return TRUE;
		}
	}
	return FALSE;
}

BOOL CDXConstruction::IsStopped()
{
	if (mGraph && mMediaControl)
	{
		OAFilterState state = State_Stopped;
		if (SUCCEEDED(mMediaControl->GetState(10, &state)))
		{
			return state == State_Stopped;
		}
	}
	return FALSE;
}

BOOL CDXConstruction::GetCaptureDevice(IBaseFilter **ppCap)
{
	BOOL brlt=FALSE;
	// Create the System Device Enumerator.
	HRESULT hr;
	ICreateDevEnum *pSysDevEnum = NULL;
	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
						  IID_ICreateDevEnum, (void **)&pSysDevEnum);
	if (FAILED(hr))
	{
		return brlt;
	}

	// Obtain a class enumerator for the video compressor category.
	IEnumMoniker *pEnumCat = NULL;
	hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
											&pEnumCat, 0);
	if (hr == S_OK)
	{
		// Enumerate the monikers.
		IMoniker *pMoniker = NULL;
		ULONG cFetched;
		pEnumCat->Reset();


		//////////////////////////////////////////////////////////////////////////
		
		// pEnumCat->Skip(1);

		//////////////////////////////////////////////////////////////////////////
		
		if (pEnumCat->Next(1,&pMoniker,&cFetched)==S_OK)
		{
			IPropertyBag *pPropBag;
			hr=pMoniker->BindToStorage(0,0,IID_IPropertyBag,(void**)&pPropBag);
			if (SUCCEEDED(hr))
			{
				VARIANT varName;
				VariantInit(&varName);
				hr=pPropBag->Read(L"FriendlyName",&varName,0);
//				char friendlyname [256];
//				friendlyname[0]=0;
//				WideCharToMultiByte(CP_ACP,0,varName.bstrVal,-1,friendlyname,256,NULL,NULL);
//				CString fnm=friendlyname;
//				if (SUCCEEDED(hr)) 
//				{
//					AfxMessageBox(fnm);
//				}
				if (ppCap)
				{
					hr=pMoniker->BindToObject(NULL,NULL,IID_IBaseFilter,(void**)ppCap);
					if (SUCCEEDED(hr))
					{
						if (mGraph && *ppCap)
						{
							if (SUCCEEDED(mGraph->AddFilter(*ppCap, varName.bstrVal)))
							{
								brlt=TRUE;
							}
						}
					}
				}
				VariantClear(&varName);
				pPropBag->Release();
			}
		}
        pMoniker->Release();
    }
    pEnumCat->Release();
	pSysDevEnum->Release();
	return brlt;
}
BOOL CDXConstruction::GetSGRdr(IBaseFilter **psgr,ISampleGrabberCB *pCB)
{
	BOOL brlt=FALSE;
	HRESULT hr;
	if (SUCCEEDED(CoCreateInstance(CLSID_SampleGrabber,
								   NULL,
								   CLSCTX_INPROC_SERVER,
								   IID_IBaseFilter,
								   (LPVOID *)psgr)))
	{
		hr=(*psgr)->QueryInterface(IID_ISampleGrabber,(void **)&mSampleGrabber);
		if (SUCCEEDED(hr))
		{
			//--------将Sample Grabber的格式订好-----------
			AM_MEDIA_TYPE amt;
			ZeroMemory(&amt,sizeof(AM_MEDIA_TYPE));
			amt.majortype=MEDIATYPE_Video;
			amt.subtype=MEDIASUBTYPE_RGB24;
			amt.pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(VIDEOINFOHEADER));
			if (amt.pbFormat!=NULL)
			{
				VIDEOINFOHEADER *pVH=(VIDEOINFOHEADER*)amt.pbFormat;
				ZeroMemory(pVH,sizeof(VIDEOINFOHEADER));
				pVH->bmiHeader.biBitCount=24;//每像素比特数
				pVH->bmiHeader.biWidth=lWidth;
				pVH->bmiHeader.biHeight=lHeight;
				pVH->bmiHeader.biPlanes=1;//必须是1
				pVH->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
				pVH->bmiHeader.biSizeImage=DIBSIZE(pVH->bmiHeader);
				amt.formattype=FORMAT_VideoInfo;
				amt.cbFormat=sizeof(VIDEOINFOHEADER);
				amt.bFixedSizeSamples=TRUE;
				amt.lSampleSize=DIBSIZE(pVH->bmiHeader);
				hr=mSampleGrabber->SetMediaType(&amt);
				if (SUCCEEDED(hr))
				{
					if (mGraph && *psgr)
					{
						if (SUCCEEDED(mGraph->AddFilter(*psgr,L"SampleGrabber")))
						{
							mSampleGrabber->SetBufferSamples(TRUE);
							mSampleGrabber->SetOneShot(FALSE);
							mSampleGrabber->SetCallback(pCB,1);
							brlt=TRUE;
						}
					}
				}
			}
			CoTaskMemFree(amt.pbFormat);
		}
	}
	return brlt;
}

BOOL CDXConstruction::GetNRdr(IBaseFilter **pNdr)
{
	BOOL brlt=FALSE;
	if (SUCCEEDED(CoCreateInstance(CLSID_VideoRenderer,
								   NULL,
								   CLSCTX_INPROC_SERVER,
								   IID_IBaseFilter,
								   (LPVOID *)pNdr)))
	{
		if (mGraph && *pNdr)
		{
			if (SUCCEEDED(mGraph->AddFilter(*pNdr,L"Null_Render")))
			{
				brlt=TRUE;
			}
		}
		
	}
	return brlt;
}

BOOL CDXConstruction::Build_Capture_Graph(IBaseFilter *pS,
										  IBaseFilter *psample,
										  IBaseFilter *pR)
{
	BOOL brlt=FALSE;
	if (SUCCEEDED(CoCreateInstance((REFCLSID)CLSID_CaptureGraphBuilder2,
								   NULL,
								   CLSCTX_INPROC_SERVER,
								   (REFIID)IID_ICaptureGraphBuilder2,
								   (void**)&mCGBer2)))
	{
		if (mGraph && mCGBer2)
		{
			if (SUCCEEDED(mCGBer2->SetFiltergraph(mGraph)))
			{
				//尝试用预览和捕捉模式连接链路
				if (SUCCEEDED(mCGBer2->RenderStream(&PIN_CATEGORY_PREVIEW,
									  &MEDIATYPE_Video,
									  pS,
									  psample,
									  pR)))
				{
					IAMStreamConfig *pConfig=NULL;
					if (SUCCEEDED(mCGBer2->FindInterface(&PIN_CATEGORY_CAPTURE,
														 &MEDIATYPE_Video,
														 pS,
														 IID_IAMStreamConfig,
														 (void**)&pConfig)))
					{
						//-------重新设定图像的尺寸-----
						AM_MEDIA_TYPE *pamt={0};
						if (SUCCEEDED(pConfig->GetFormat(&pamt)))
						{
							if((pamt->majortype==MEDIATYPE_Video) &&
							   (pamt->subtype==MEDIASUBTYPE_RGB24) &&
							   (pamt->formattype==FORMAT_VideoInfo) &&
							   (pamt->cbFormat>=sizeof(VIDEOINFOHEADER))&&
							   (pamt->pbFormat!=NULL))
							{
								VIDEOINFOHEADER *pVih=(VIDEOINFOHEADER*)pamt->pbFormat;
								pVih->bmiHeader.biWidth=lWidth;
								pVih->bmiHeader.biHeight=lHeight;
								if (SUCCEEDED(pConfig->SetFormat(pamt)))
								{
									brlt=TRUE;
								}
							}
							DeleteMediaType(pamt);
						}
					}
					SAFE_RELEASE(pConfig);
				}
			}
		}
	}
	return brlt;
}

BOOL CDXConstruction::Get_Photo(CString str,BYTE * pD, HWND hwnd_nmb)
{
	BOOL           brlt=FALSE;
	long           lbuffersize=0;
	mSampleGrabber->GetCurrentBuffer(&lbuffersize,NULL);
	char          *pBf=new char[lbuffersize];
	mSampleGrabber->GetCurrentBuffer(&lbuffersize,(long*)pBf);
	HANDLE hr=(CreateFile(   (LPCSTR)str,
							 GENERIC_WRITE,
							 FILE_SHARE_READ,
							 NULL,
							 CREATE_ALWAYS,
							 NULL,
							 NULL));
	if (SUCCEEDED(hr))
	{
		BITMAPFILEHEADER bfh;
		memset(&bfh,0,sizeof(BITMAPFILEHEADER));
		bfh.bfType='MB';
		bfh.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+lbuffersize;
		bfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
		DWORD dwWritten = 0;
        WriteFile(hr,//文件句柄
				  &bfh,//数据块
				  sizeof( bfh ),//尺寸(Byte)
				  &dwWritten,//记录写了多少个Byte
				  NULL );//将FileHeader准备好
		BITMAPINFOHEADER bih;
		memset(&bih,0,sizeof(BITMAPINFOHEADER));
		bih.biSize=sizeof(bih);
		bih.biWidth=lWidth;
		bih.biHeight=lHeight;
		bih.biPlanes=1;
		bih.biBitCount=24;
		dwWritten=0;
		WriteFile(hr,
				  &bih,
				  sizeof(bih),
				  &dwWritten,
				  NULL);
		dwWritten=0;
		WriteFile(hr,
				  pBf,
				  lbuffersize,
				  &dwWritten,
				  NULL);
		CloseHandle(hr);
		// Display the bitmap bits on the dialog's preview window
		memcpy(pD,pBf,lbuffersize);
		DisplayCapturedBits(pD, &bih, hwnd_nmb);
	}
	delete []pBf;
	return brlt;
}

BOOL CDXConstruction::DisplayCapturedBits(BYTE *pBuffer, BITMAPINFOHEADER *pbih, HWND hwnd_nmb)
{
	if (!hwnd_nmb || !pBuffer)
		return FALSE;
	RECT rc;
	::GetWindowRect( hwnd_nmb, &rc );
	long lStillWidth = rc.right - rc.left;
	long lStillHeight = rc.bottom - rc.top;
	HDC hdcStill = GetDC( hwnd_nmb );
	PAINTSTRUCT ps;
	BeginPaint(hwnd_nmb, &ps);
	SetStretchBltMode(hdcStill, COLORONCOLOR);
	StretchDIBits(  hdcStill, 0, 0, 
                    lStillWidth, lStillHeight, 
                    0, 0, lWidth, lHeight, 
                    pBuffer, 
                    (BITMAPINFO*) pbih, 
                    DIB_RGB_COLORS, 
                    SRCCOPY );
	EndPaint(hwnd_nmb, &ps);
	ReleaseDC( hwnd_nmb, hdcStill );
	return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -