📄 movieview.cpp
字号:
}
return NOERROR;
}
//Perform frame by frame updates and blits. Set the stream
//state to STOP if there are no more frames to update.
void CMovieView::RenderToSurface(BOOL bSingleBlit)
{
HRESULT hr;
POINT point;
CRect rect, rect2;
if (!m_bFileLoaded || !m_bAppactive) return;
if (!m_bPaused)
{
//update each frame
if (m_pSample->Update(0, NULL, NULL, 0) != S_OK)
{
m_bAppactive = FALSE;
m_pMMStream->SetState(STREAMSTATE_STOP);
}
}
rect.top = rect.left = 0;
rect.bottom = m_video_height;
rect.right = m_video_width;
if (!bSingleBlit)
{
// performs a couple of operations including a blit.
//blit from the offscreen surface #2 (video sample-backbuffer)
// to the offscreen surface #1 (copy-backbuffer)
hr = m_pDDSOffscreen->Blt(&rect, m_pDDSOffscreen2, &rect, DDBLT_WAIT, NULL);
if(FAILED(hr))
{
AfxMessageBox("Blt failed");
ExitCode();
}
}
//stretchblit from the offscreen surface #1 to the primary surface
//get window coordinates to blit into
GetClientRect(&rect2); // rectangle for the primary surface
point.x = rect2.top; // transfrom rect into screen coordinates
point.y = rect2.left;
ClientToScreen(&point);
rect2.left = point.x;
rect2.top = point.y;
point.x = rect2.right;
point.y = rect2.bottom;
ClientToScreen(&point);
rect2.right = point.x;
rect2.bottom= point.y;
// In single blit mode, choose the sample-backbuffer to stretch-blit from
// Otherwise, blit from the copy-backbuffer
IDirectDrawSurface *surface= bSingleBlit ? m_pDDSOffscreen2 : m_pDDSOffscreen;
hr = m_pPrimarySurface->Blt(&rect2, surface, &rect, DDBLT_WAIT, NULL);
if(FAILED(hr))
{
AfxMessageBox(_T("Blt failed"));
ExitCode();
}
}
void CMovieView::DestroyObjects()
{
//Release MultiMedia streaming Objects
if (m_pMMStream != NULL) {
m_pMMStream->Release();
m_pMMStream= NULL;
}
if (m_pSample != NULL) {
m_pSample->Release();
m_pSample = NULL;
}
if (m_pDDStream != NULL) {
m_pDDStream->Release();
m_pDDStream= NULL;
}
if (m_pPrimaryVidStream != NULL) {
m_pPrimaryVidStream->Release();
m_pPrimaryVidStream= NULL;
}
// Release DirectDrawEx interfaces
if (m_pDDSOffscreen != NULL) {
m_pDDSOffscreen->Release();
m_pDDSOffscreen= NULL;
}
if (m_pDDSOffscreen2 != NULL) {
m_pDDSOffscreen2->Release();
m_pDDSOffscreen2= NULL;
}
if (m_pDDClipper != NULL) {
m_pDDClipper->Release();
m_pDDClipper= NULL;
}
if (m_pPrimarySurface != NULL) {
m_pPrimarySurface->Release();
m_pPrimarySurface= NULL;
}
if (m_pDD3 != NULL) {
m_pDD3->Release();
m_pDD3= NULL;
}
if (m_pDD != NULL) {
m_pDD->Release();
m_pDD= NULL;
}
if (m_pDDF != NULL) {
m_pDDF->Release();
m_pDDF= NULL;
}
}
void CMovieView::ExitCode()
{
DestroyObjects();
::PostQuitMessage(0);
CoUninitialize();
}
afx_msg void CMovieView::OnFileOpen()
{
//If a file is already open - call STOP first
if (m_bAppactive && m_bFileLoaded)
{
m_pMMStream->SetState(STREAMSTATE_STOP);
// as the routine OnFileOpen can be called a couple of times, each time
// the multimedia stream and directDraw surfaces should be released before
// we start the whole story once again...
DestroyObjects();
}
if (m_pDD==NULL)
{
HRESULT hr = InitDDrawEx(); // initialize DirectDrawEx
if (FAILED(hr)) ExitCode();
}
static BOOL bOpen = TRUE;
GetOpenMovieFile(m_szFilename);
if (bOpen)
{
HRESULT hr = RenderFileToMMStream(m_szFilename);
if (FAILED(hr))
{
// file format not supported
// hence destroy stream
DestroyObjects();
m_bAppactive = m_bFileLoaded = FALSE;
}
else
{
hr = InitRenderToSurface();
if (FAILED(hr))
{
ExitCode();
}
m_bAppactive = m_bFileLoaded = TRUE;
m_bPaused = FALSE; //Take care of any old pauses
//Now set the multimedia stream to RUN
hr = m_pMMStream->SetState(STREAMSTATE_RUN);
if (FAILED(hr))
{
ExitCode();
}
}
} // end if (bOpen)
}
// Display the open dialog box to retrieve the user-selected movie file
BOOL CMovieView::GetOpenMovieFile(LPSTR szName)//LPSTR szName
{
OPENFILENAME ofn;
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = AfxGetMainWnd()->m_hWnd;
ofn.lpstrFilter = NULL;
ofn.lpstrFilter = "Video (*.avi;*.mov;*.mpg;*.mpeg)\0*.avi;*.mov;*.mpg;*.mpeg\0All Files (*.*)\0*.*\0";
ofn.lpstrCustomFilter = NULL;
ofn.nFilterIndex = 1;
*szName = 0;
ofn.lpstrFile = szName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.lpstrFileTitle = NULL;
ofn.lpstrDefExt = NULL;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST;
return ::GetOpenFileName((LPOPENFILENAME)&ofn);
}
afx_msg void CMovieView::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
{
if (nChar==VK_SPACE)
switchPlayPause();
}
afx_msg void CMovieView::OnLButtonDown( UINT nFlags, CPoint point )
{
switchPlayPause();
}
void CMovieView::switchPlayPause()
{
// pause
if (!m_bPaused && m_bFileLoaded)
{
m_pMMStream->GetTime(&m_StreamTime);
m_pMMStream->SetState(STREAMSTATE_STOP);
//m_bAppactive = FALSE;
m_bPaused = TRUE;
}
else // play
{
if (m_bPaused)
{ // If its in a paused state, seek and run
m_pMMStream->Seek(m_StreamTime);
m_pMMStream->SetState(STREAMSTATE_RUN);
m_bAppactive = TRUE;
m_bPaused = FALSE;
}
}
}
afx_msg void CMovieView::OnStart()
{
if (m_bFileLoaded)
{
if (!m_bAppactive) // Restart the stream
m_StreamTime=0;
if (!m_bAppactive || m_bPaused) // seek to restart or to end the pause state
{
m_pMMStream->Seek(m_StreamTime);
m_pMMStream->SetState(STREAMSTATE_RUN); // run
}
m_bAppactive = TRUE;
m_bPaused = FALSE;
}
else
{
AfxMessageBox(_T("Please select a movie file first."));
}
}
afx_msg void CMovieView::OnPause()
{
// Pause if not already in a paused state and you have a file loaded
if (!m_bPaused && m_bFileLoaded)
{
m_pMMStream->GetTime(&m_StreamTime);
m_pMMStream->SetState(STREAMSTATE_STOP);
m_bAppactive = FALSE;
m_bPaused = TRUE;
}
}
afx_msg void CMovieView::OnStop()
{
if (m_bFileLoaded)
{
m_pMMStream->SetState(STREAMSTATE_STOP);
m_StreamTime = 0; // Reset the stream time to 0
m_pMMStream->Seek(m_StreamTime); //Run one frame to reset video
m_pMMStream->SetState(STREAMSTATE_RUN);
RenderToSurface();
m_pMMStream->SetState(STREAMSTATE_STOP); // Stop for real this time
m_StreamTime = 0;
}
m_bAppactive = FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CMovieView diagnostics
#ifdef _DEBUG
void CMovieView::AssertValid() const
{
CView::AssertValid();
}
void CMovieView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMovieDoc* CMovieView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMovieDoc)));
return (CMovieDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMovieView message handlers
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -