📄 mainframe.cpp
字号:
}
// Store the image to the stream
hr = AVIStreamWrite(hVideoStream, // stream pointer
RunningIndex, // time of this frame
1, // number to write
pDst, // pointer to data
This->m_ptrBitmaps[BufferIndex]->GetTotalPixelBytes(),// size of this frame
AVIIF_KEYFRAME, // flags....
NULL,
NULL);
++RunningIndex;
if (hr != AVIERR_OK)
throw BcamException(hr, "CMainFrame::GrabThreadProc");
if(STORE_TEXT_STREAM)
{
SYSTEMTIME SystemTime;
GetLocalTime(&SystemTime);
CString Buffer;
Buffer.Format("%02d.%02d.%04d %02d:%02d:%02d.%04d",
SystemTime.wDay, SystemTime.wMonth, SystemTime.wYear,
SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, SystemTime.wMilliseconds);
// Store some tect comments to the image
hr = AVIStreamWrite(hTextStream,
RunningIndex,
1,
(void*)(LPCSTR)Buffer,
Buffer.GetLength() + 1,
RunningIndex % (DELTA_FRAMES_PER_KEY_FRAME + 1) == 0 ? AVIIF_KEYFRAME : 0,
NULL,
NULL);
if (hr != AVIERR_OK)
throw BcamException(hr, "CMainFrame::GrabThreadProc");
}
}
else if(RunningIndex == MAX_NUM_FRAMES)
{
::MessageBox(This->m_hWnd, "Capture stopped after MAX_NUM_FRAMES", "StoreAVI", MB_ICONINFORMATION + MB_OK);
// Make sure this messagebox is shown only once
++RunningIndex;
// Press the stop button
This->PostMessage(WM_COMMAND, ID_GRAB_STOP, NULL );
}
// Notfy the GDI thread that the buffer with the BufferIndex has been grabbed
This->PostMessage(WM_GRAB_FINISHED, *(WPARAM*)&BufferIndex, *(LPARAM*)&ElapsedTime );
}
break;
// This means the queue is empty now ==> suicide
case NotifyQuit:
// Tell the GdiThread to clean up
This->PostMessage(WM_GRAB_STOPPED, 0, 0 );
// Finish thread
goto Cleanup;
// Don't care about other function codes like AsyncSetGain etc.
default:
ErrorCode = 1;
break;
}
}
}
catch (BcamException& e )
{
// Forward error to GdiThread for display
BcamException* pE = new BcamException(e);
This->PostMessage(WM_ERROR, (unsigned int)pE, 0);
return e.Error();
}
catch (...)
{
// Forward error to GdiThread for display
BcamException* pE = new BcamException(DISP_E_EXCEPTION, "CMainFrame::GrabThreadProc");
This->PostMessage(WM_ERROR, (unsigned int)pE, 0);
return DISP_E_EXCEPTION;
}
Cleanup:
if (hVideoStream)
AVIStreamClose(hVideoStream);
if (hTextStream )
AVIStreamClose(hTextStream );
if (hAviFile)
AVIFileClose(hAviFile);
// Close operating support for AVI files
AVIFileExit();
CoUninitialize();
return 0;
}
/*!
Called if the #GrabThreadProc receives a finished grab command. The wParam includes the buffer's index.
Enqueues the buffer's index to the #m_BufferQueue. The BufferQueue will be emplied by #OnIdle.
*/
LRESULT CMainFrame::OnGrabFinished(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
try
{
// store the index of the grabbed buffer in the buffer queue
m_BufferQueue.push(*(unsigned int*)&wParam);
// Update framerate statistics
float ElapsedTime = *((float*)&lParam);
if(ElapsedTime > FLT_EPSILON || ElapsedTime < -FLT_EPSILON)
m_Fps.Add(1.0 / ElapsedTime);
// Show framerate
CString Buffer;
Buffer.Format("%3.1f fps", m_Fps.Avg());
m_StatusBar.SetPaneText(ID_FPS_PANE, Buffer);
// Show framecounter
Buffer.Format("%lu", m_FrameCounter);
m_StatusBar.SetPaneText(ID_FRAME_COUNTER_PANE, Buffer);
// increase framecounter
m_FrameCounter++;
}
CATCH_MSGBOX( "CMainFrame::OnGrabFinished" )
return 0;
}
/*!
Called each time all messages in the message queue of the GUI thread are processed and
no more messages are waiting.
- If the #m_BufferQueue contains buffer indices these are removes. For each buffer
a new grab command is enqueued. When the grab commands are finished they turn up in
the #GrabThreadProc. The most recent buffer is put to m_view for display.
- Updates the user interface's enable stati.
*/
BOOL CMainFrame::OnIdle()
{
try
{
// If the grab is to be stopped, don't enqueue buffers any more
if(m_LiveGrabbing)
{
// For all buffer which might have been pushed to the queue by OnGrabFinished
while(0 < m_BufferQueue.size())
{
// Get the buffer's index from the queue
unsigned int BufferIndex = m_BufferQueue.front();
m_BufferQueue.pop();
// If more than one buffer is in the queue display only the most recent
if(0 < m_BufferQueue.size() )
{
// Enqueue a new Grab command
m_Bcam.GrabImageAsync(
(char*)m_ptrBitmaps[BufferIndex]->GetPixels(),
m_ptrBitmaps[BufferIndex]->GetTotalPixelBytes(),
(void*)BufferIndex,
USE_ONESHOT);
}
else
{
// If the image is monochrome the most recent buffer is hold
// by BitmapView; if the image is Bayer the SetBitmap function
// will do a RGB copy so the buffer can be enqueued again
// immediately
if(!m_IsBayerImage)
{
// Enqueue the buffer currently being displayed
if(m_DisplayedBufferIndex != -1)
{
// Enqueue a new Grab command
m_Bcam.GrabImageAsync(
(char*)m_ptrBitmaps[m_DisplayedBufferIndex]->GetPixels(),
m_ptrBitmaps[m_DisplayedBufferIndex]->GetTotalPixelBytes(),
(void*)BufferIndex,
USE_ONESHOT);
}
// Remeber which buffer is now displayed
m_DisplayedBufferIndex = BufferIndex;
}
// Update View
m_view.SetBitmap(m_ptrBitmaps[BufferIndex], m_IsBayerImage);
// see comment above
if(m_IsBayerImage)
{
// Enqueue a new Grab command
m_Bcam.GrabImageAsync(
(char*)m_ptrBitmaps[BufferIndex]->GetPixels(),
m_ptrBitmaps[BufferIndex]->GetTotalPixelBytes(),
(void*)BufferIndex,
USE_ONESHOT);
}
}
}
}
// Update the user interface
UpdateUI();
}
CATCH_MSGBOX( "CMainFrame::OnIdle" )
return FALSE;
}
/*!
Called if the user wants the live grab to stop. Enqueues a #NotifyQuit message to the grab
queue. Sets the #m_LiveGrabbing flag to false to prevent new grab commands from being enqueued.
When all commands currently being in the queue are finished the NotifyQuit message will turn up
in the #GrabThreadProc.
*/
LRESULT CMainFrame::OnGrabStop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
try
{
// This will prevent new images from being enqueued
m_LiveGrabbing = false;
// Enqueue a "clean-up" message which will show up after all images being currently
// in the queue have been received
m_Bcam.Notify(NotifyQuit, NULL);
}
CATCH_MSGBOX( "CMainFrame::OnGrabStop" )
return 0;
}
/*!
Called if the #GrabThreadProc receives a #NotifyQuit message. This means that the command queue is
empty now and everything can be cleaned up.
*/
LRESULT CMainFrame::OnGrabStopped(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
try
{
// Clean up queue
while(0 < m_BufferQueue.size())
m_BufferQueue.pop();
// forget about the displayed buffer
m_DisplayedBufferIndex = -1;
// switch off camera (in case we're using ContinuousShot)
if(!USE_ONESHOT)
m_Bcam.ContinuousShot = false;
// shutdown thread
m_GrabThread.Release(); // this waits for the thread to die
// Release bandwidth, isoch channels and isoch transfer contexts
// This is optional since closing the driver will trigger this automatically
m_Bcam.Close();
// Close driver
m_Bcam.Close();
// We could take away the Bitmap from the view
//but since it's reference counted we leavi ti there for display
//m_view.SetBitmap(NULL);
// Delete bitmaps
for(int i=0; i<NUM_BUFFERS; ++i)
m_ptrBitmaps[i].Release();
// Reset frame rate display
m_Fps.Reset();
m_StatusBar.SetPaneText(ID_FPS_PANE, "");
}
CATCH_MSGBOX( "CMainFrame::OnGrabStopped" )
return 0;
}
/*!
Called if an error occurred in the #GrabThreadProc. Shows an error message box.
*/
LRESULT CMainFrame::OnError(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// Show the error message coming from another thread
BcamException* pE = (BcamException*)wParam;
CString Buffer, B;
Buffer += (B.Format("Exception 0x%X occurred\n", pE->Error() ), B);
Buffer += (B.Format("Message = %s\n", pE->Description() ), B);
Buffer += (B.Format("Context = %s\n", pE->Context()), B);
MessageBox(Buffer, _T("CMainFrame::OnError"), MB_OK | MB_ICONEXCLAMATION);
delete pE;
return 0;
}
/*!
Makes sure the application terminates cleanly if closed via the system menu
*/
LRESULT CMainFrame::OnSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
if(wParam == SC_CLOSE)
{
if(m_LiveGrabbing)
{
// Enqueue a "clean-up" message which will show up after all images being currently
// in the queue have been received
m_Bcam.Notify(NotifyQuit, NULL);
// Wait until the GrabThread died
::WaitForSingleObject((HANDLE)m_GrabThread,INFINITE);
// The rest will clean up itselfe via the destructors
}
}
bHandled = false;
return 0;
}
LRESULT CMainFrame::OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
if((bool)m_view.m_ptrBitmap)
m_view.ReleaseBitmap();
return 0;
}
LRESULT CMainFrame::OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
CFileDialog dlg(TRUE, _T("bmp"), NULL, 0, _T("Bitmap Files (*.bmp)\0*.bmp\0All Files (*.*)\0*.*\0"), m_hWnd);
if(dlg.DoModal() == IDOK)
{
try
{
CDibPtr ptrBitmap;
ptrBitmap.LoadBMP(dlg.m_szFileName);
m_view.SetBitmap(ptrBitmap);
}
CATCH_MSGBOX( "CMainFrame::OnFileOpen" )
}
return 0;
}
LRESULT CMainFrame::OnFileSave(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
if(!m_view.m_ptrBitmap)
return 0;
CFileDialog dlg(FALSE, _T("bmp"), _T("Temp.bmp"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("Bitmap Files (*.bmp)\0*.bmp\0All Files (*.*)\0*.*\0"), m_hWnd);
if(dlg.DoModal() == IDOK)
{
try
{
m_view.m_ptrBitmap->StoreBMP(dlg.m_szFileName);
}
CATCH_MSGBOX( "CMainFrame::OnFileSave" )
}
return 0;
}
LRESULT CMainFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
try
{
if(m_LiveGrabbing)
{
// Enqueue a "clean-up" message which will show up after all images being currently
// in the queue have been received
m_Bcam.Notify(NotifyQuit, NULL);
// Wait until the GrabThread died
::WaitForSingleObject((HANDLE)m_GrabThread,INFINITE);
// The rest will clean up itselfe via the destructors
}
}
CATCH_MSGBOX( "CMainFrame::OnFileExit" )
PostMessage(WM_CLOSE);
return 0;
}
LRESULT CMainFrame::OnEditCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
try
{
if(!m_LiveGrabbing && (bool)m_view.m_ptrBitmap)
{
m_view.m_ptrBitmap->CopyToClipboard();
}
}
CATCH_MSGBOX( "CMainFrame::OnEditCopy" )
return 0;
}
void CMainFrame::UpdateUI()
{
// update UI elements
UIEnable(ID_FILE_NEW, !m_LiveGrabbing);
UIEnable(ID_FILE_OPEN, !m_LiveGrabbing);
UIEnable(ID_FILE_SAVE, !m_LiveGrabbing && (bool)m_view.m_ptrBitmap);
UIEnable(ID_GRAB_LIVE, !m_LiveGrabbing);
UIEnable(ID_GRAB_STOP, m_LiveGrabbing);
UIEnable(ID_EDIT_COPY, !m_LiveGrabbing && (bool)m_view.m_ptrBitmap);
// These functions are not yet implemented so they have to be disabled always
UIEnable(ID_FILE_PRINT, false);
UIEnable(ID_FILE_PRINT_PREVIEW, false);
UIEnable(ID_FILE_PRINT_SETUP, false);
UIUpdateToolBar();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -