www.pudn.com > VisSDK.rar > ExCameraDoc.cpp


// ExCameraDoc.cpp : implementation of the CExCameraDoc class 
// 
// Copyright © 1997-2000 Microsoft Corporation, All Rights Reserved 
 
#include "stdafx.h" 
#include "VisImSrc.h" 
#include "ExCamera.h" 
 
#include  
 
#include "MainFrm.h" 
 
#include "ExCameraDoc.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CExCameraDoc 
 
IMPLEMENT_DYNCREATE(CExCameraDoc, CDocument) 
 
BEGIN_MESSAGE_MAP(CExCameraDoc, CDocument) 
	//{{AFX_MSG_MAP(CExCameraDoc) 
	ON_COMMAND(ID_DEC_SIZE, OnDecSize) 
	ON_COMMAND(ID_INC_SIZE, OnIncSize) 
	ON_UPDATE_COMMAND_UI(ID_DEC_SIZE, OnUpdateDecSize) 
	ON_UPDATE_COMMAND_UI(ID_INC_SIZE, OnUpdateIncSize) 
	ON_COMMAND(ID_UPDATE_DISPLAY, OnUpdateDisplay) 
	ON_UPDATE_COMMAND_UI(ID_UPDATE_DISPLAY, OnUpdateUpdateDisplay) 
	ON_COMMAND(ID_CAPTURE, OnCapture) 
	ON_UPDATE_COMMAND_UI(ID_CAPTURE, OnUpdateCapture) 
	ON_COMMAND(ID_GRAB, OnGrab) 
	ON_UPDATE_COMMAND_UI(ID_GRAB, OnUpdateGrab) 
	ON_COMMAND(ID_SELECT_DEVICE, OnSelectDevice) 
	ON_UPDATE_COMMAND_UI(ID_SELECT_DEVICE, OnUpdateSelectDevice) 
	ON_COMMAND(ID_GRAB_ONE, OnGrabOne) 
	ON_UPDATE_COMMAND_UI(ID_GRAB_ONE, OnUpdateGrabOne) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CExCameraDoc construction/destruction 
 
CExCameraDoc::CExCameraDoc() 
  : m_sequence(), 
	m_image(), 
	m_pThread(0), 
	m_fUpdateInBackground(false), 
	m_fGrabSingleFrame(false), 
	m_hwndView(0), 
	m_fKillThread(false), 
	m_cmsStart(0), 
	m_cmsEnd(0), 
	m_cFrameGrabbed(0), 
	m_cFrameDisplayed(0), 
	m_fUpdateDisplay(true), 
	m_timerGrabbed(10), 
	m_timerDisplayed(10), 
	m_dblRateGrabbed(0.0), 
	m_dblRateDisplayed(0.0) 
{ 
	VisAddProviderRegEntryForVFW(); 
 
	CVisImageSource imagesource1 = VisFindImageSource(); 
	if (imagesource1.IsValid()) 
		m_sequence.ConnectToSource(imagesource1); 
 
	if (m_sequence.HasImageSource()) 
	{ 
		assert(m_sequence.ImageSource().IsValid()); 
 
		// Get an image from the sequence. 
		GrabNext(); 
	} 
 
// Thread priority normal is okay here (we don't need a higher priority). 
//	m_pThread = AfxBeginThread(StaticThreadMain, this, THREAD_PRIORITY_TIME_CRITICAL); 
	m_pThread = AfxBeginThread(StaticThreadMain, this, THREAD_PRIORITY_NORMAL, 
			0, CREATE_SUSPENDED); 
} 
 
 
CExCameraDoc::~CExCameraDoc() 
{ 
	m_fUpdateInBackground = false; 
 
	m_sequence.DisconnectFromSource(); 
 
	if (m_pThread != 0) 
	{ 
		m_fKillThread = true; 
 
		if (m_hwndView == 0) 
			m_pThread->ResumeThread(); 
 
		WaitForSingleObject(m_pThread->m_hThread, INFINITE); 
	} 
 
	m_sequence.Clear(); 
	m_image.Deallocate(); 
} 
 
BOOL CExCameraDoc::OnNewDocument() 
{ 
	if (!CDocument::OnNewDocument()) 
		return FALSE; 
 
	// TODO: add reinitialization code here 
	// (SDI documents will reuse this document) 
 
	return TRUE; 
} 
 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CExCameraDoc serialization 
 
void CExCameraDoc::Serialize(CArchive& ar) 
{ 
	if (ar.IsStoring()) 
	{ 
		// TODO: add storing code here 
	} 
	else 
	{ 
		// TODO: add loading code here 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CExCameraDoc diagnostics 
 
#ifdef _DEBUG 
void CExCameraDoc::AssertValid() const 
{ 
	CDocument::AssertValid(); 
} 
 
void CExCameraDoc::Dump(CDumpContext& dc) const 
{ 
	CDocument::Dump(dc); 
} 
#endif //_DEBUG 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CExCameraDoc background thread 
UINT __cdecl CExCameraDoc::StaticThreadMain(void *pvDocument) 
{ 
	assert(pvDocument != 0); 
	return ((CExCameraDoc *) pvDocument)->ThreadMain(); 
} 
 
 
UINT CExCameraDoc::ThreadMain(void) 
{ 
	if (m_sequence.HasImageSource()) 
	{ 
		while (!m_fKillThread) 
		{ 
#ifdef VIS_WANT_MSG_LOOP_IN_DOC_THREAD 
			// LATER:  We can add a message loop if this thead creates 
			// windows. 
			MSG msg; 
			if (::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) 
			{ 
				::TranslateMessage(&msg); 
				::DispatchMessage(&msg); 
			} 
#endif // VIS_WANT_MSG_LOOP_IN_DOC_THREAD 
 
			if ((m_fUpdateInBackground) || (m_fGrabSingleFrame)) 
			{ 
				// Wait for next image, then update view. 
				GrabNext(2000); 
				m_fGrabSingleFrame = false; 
			} 
			else 
			{ 
				Sleep(50); 
			} 
		} 
	} 
 
	return 0; 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CExCameraDoc commands 
 
void CExCameraDoc::OnCapture()  
{ 
	assert(m_sequence.HasImageSource()); 
 
	bool fCur = m_sequence.ImageSource().UseContinuousGrab(); 
	m_sequence.ImageSource().SetUseContinuousGrab(!fCur); 
	 
	ResetStatusInfo(); 
 
	// Decrement the count of frames displayed to ignore the update 
	// that takes place right after button is pressed. 
	-- m_cFrameDisplayed; 
} 
 
void CExCameraDoc::OnUpdateCapture(CCmdUI* pCmdUI)  
{ 
	BOOL fEnable = (m_sequence.HasImageSource()); 
 
	BOOL fCapturing = (fEnable) 
			&& (m_sequence.ImageSource().UseContinuousGrab()); 
 
	pCmdUI->Enable(fEnable); 
	pCmdUI->SetCheck(fCapturing); 
} 
 
void CExCameraDoc::OnGrab()  
{ 
	// Change the update flag. 
	SetBackgroundUpdate(!FInBackgroundUpdate()); 
} 
 
void CExCameraDoc::OnUpdateGrab(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable(m_sequence.HasImageSource()); 
	pCmdUI->SetCheck(FInBackgroundUpdate()); 
} 
 
void CExCameraDoc::DeleteContents()  
{ 
	// The view will be soon be invalid, so we don't want the background 
	// thread to use it. 
	m_hwndView = 0; 
	 
	CDocument::DeleteContents(); 
} 
 
void CExCameraDoc::OnDecSize()  
{ 
	assert(m_sequence.HasImageSource()); 
	assert(m_sequence.ImageSource().IsValid()); 
 
	// Get the current size. 
	long dx = m_sequence.ImageSource().GetImSrcValue(evisimsrcWidth); 
	long dy = m_sequence.ImageSource().GetImSrcValue(evisimsrcHeight); 
 
	// Find 1/2 of the current size. 
	dx /= 2; 
	dy /= 2; 
 
	// Set the new size. 
	m_sequence.ImageSource().SetImSrcValue(evisimsrcWidth, dx); 
	m_sequence.ImageSource().SetImSrcValue(evisimsrcHeight, dy); 
} 
 
void CExCameraDoc::OnUpdateDecSize(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable(m_sequence.HasImageSource()); 
} 
 
void CExCameraDoc::OnIncSize()  
{ 
	assert(m_sequence.HasImageSource()); 
	assert(m_sequence.ImageSource().IsValid()); 
 
	// Get the current size. 
	long dx = m_sequence.ImageSource().GetImSrcValue(evisimsrcWidth); 
	long dy = m_sequence.ImageSource().GetImSrcValue(evisimsrcHeight); 
 
	// Find 2/1 of the current size. 
	dx *= 2; 
	dy *= 2; 
 
	// Set the new size. 
	m_sequence.ImageSource().SetImSrcValue(evisimsrcWidth, dx); 
	m_sequence.ImageSource().SetImSrcValue(evisimsrcHeight, dy); 
} 
 
void CExCameraDoc::OnUpdateIncSize(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable(m_sequence.HasImageSource()); 
} 
 
void CExCameraDoc::StartBackgroundUpdate(void) 
{ 
	if (!m_fUpdateInBackground) 
	{ 
		m_fUpdateInBackground = true; 
		ResetStatusInfo(); 
	} 
} 
 
void CExCameraDoc::StopBackgroundUpdate(void) 
{ 
	if (m_fUpdateInBackground) 
	{ 
		UpdateStatusInfo(); 
		m_fUpdateInBackground = false; 
	} 
} 
 
void CExCameraDoc::GrabNext(DWORD cmsTimeout) 
{ 
	// Wait for next image, then update view. 
	CExCameraImage imageT; 
 
	if (m_sequence.PopFront(imageT, cmsTimeout)) 
	{ 
		++ m_cFrameGrabbed; 
		if ((m_dblRateGrabbed = m_timerGrabbed.RateUpdate()) < 0.0) 
			m_dblRateGrabbed = 0.0; 
 
		m_image = imageT; 
		if ((m_fUpdateDisplay) && (m_hwndView != 0)) 
			::InvalidateRect(m_hwndView, 0, FALSE); 
		// UNDONE:  We should send a message to the main thread to update 
		// the frame rate diaplay after each image is grabbed. 
	} 
} 
 
void CExCameraDoc::ImageDisplayed(void) 
{ 
	if (m_fUpdateInBackground) 
	{ 
		++ m_cFrameDisplayed; 
		if ((m_dblRateDisplayed = m_timerDisplayed.RateUpdate()) < 0.0) 
			m_dblRateDisplayed = 0.0; 
 
		UpdateStatusInfo(); 
	} 
} 
 
void CExCameraDoc::DialogDisplayed(void) 
{ 
	if (m_fUpdateInBackground) 
	{ 
		ResetStatusInfo(); 
 
		// Decrement the count of frames displayed to ignore the update 
		// that takes place right after a dialog is displayed. 
		-- m_cFrameDisplayed; 
	} 
} 
 
void CExCameraDoc::ResetStatusInfo(void) 
{ 
	if (m_fUpdateInBackground) 
	{ 
		m_cmsEnd = m_cmsStart = timeGetTime(); 
		m_cFrameGrabbed = 0; 
		m_cFrameDisplayed = 0; 
 
		m_timerGrabbed.Reset(); 
		m_timerDisplayed.Reset(); 
		m_dblRateGrabbed = 0.0; 
		m_dblRateDisplayed = 0.0; 
	} 
} 
 
void CExCameraDoc::UpdateStatusInfo(void) 
{ 
	if (m_fUpdateInBackground) 
		m_cmsEnd = timeGetTime(); 
 
	CExCameraApp *pApp = (CExCameraApp *) AfxGetApp(); 
	assert(pApp != 0); 
//	((CMainFrame *) (pApp->m_pMainWnd))->ShowCFrameCms( 
//			m_cFrameGrabbed, m_cFrameDisplayed, 
//			m_cmsEnd - m_cmsStart); 
	((CMainFrame *) (pApp->m_pMainWnd))->ShowFrameRates( 
			m_dblRateGrabbed, m_dblRateDisplayed); 
} 
 
void CExCameraDoc::OnUpdateDisplay()  
{ 
	m_fUpdateDisplay = !m_fUpdateDisplay; 
	ResetStatusInfo(); 
} 
 
void CExCameraDoc::OnUpdateUpdateDisplay(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable(true); 
	pCmdUI->SetCheck(m_fUpdateDisplay); 
} 
 
void CExCameraDoc::OnSelectDevice()  
{ 
	// UNDONE:  Move the call to DisconnectFromSource into the 
	// VisFindImageSource function.  Remeber the device ID string so 
	// that we can reconnect if the dialog is cancelled. 
	m_sequence.DisconnectFromSource(); 
	VisFindImageSource(m_sequence, 0, true); 
} 
 
void CExCameraDoc::OnUpdateSelectDevice(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable(true); 
} 
 
void CExCameraDoc::OnGrabOne()  
{ 
	m_fGrabSingleFrame = true; 
} 
 
void CExCameraDoc::OnUpdateGrabOne(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable((m_sequence.HasImageSource()) 
			&& (!FInBackgroundUpdate())); 
}