📄 playwnd.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//=========================================================================
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
//
//=========================================================================
#include <windows.h>
#include <mmsystem.h>
#include <streams.h>
#include <commctrl.h>
#include <commdlg.h>
#include "playwnd.h"
//
// Global data
//
HWND ghApp=0, ghCB=0;
HINSTANCE ghInst;
TCHAR g_szFileName[MAX_PATH]={0};
PLAYSTATE g_psCurrent=psSTOPPED;
BOOL g_bAudioOnly=FALSE;
LONG g_lVolume=VOLUME_FULL;
// Collection of interfaces
IGraphBuilder *pGB = NULL;
IMediaControl *pMC = NULL;
IMediaEventEx *pME = NULL;
IVideoWindow *pVW = NULL;
IBasicAudio *pBA=NULL;
IBasicVideo *pBV = NULL;
IMediaSeeking *pMS = NULL;
HRESULT PlayMovieInWindow(LPTSTR szFile)
{
WCHAR wFile[MAX_PATH];
HRESULT hr;
RETAILMSG(1, (TEXT("Playing media %s...\r\n"), szFile));
// Clear open dialog remnants before the slow-running RenderFile()
UpdateWindow(ghApp);
#ifndef UNICODE
MultiByteToWideChar(CP_ACP, 0, szFile, -1, wFile, MAX_PATH);
#else
if (_tcslen(szFile) < MAX_PATH)
lstrcpy(wFile, szFile);
else
return E_FAIL;
#endif
// Get the interface for DirectShow's GraphBuilder
JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB));
if(SUCCEEDED(hr))
{
// Have the graph construct its the appropriate graph automatically
JIF(pGB->RenderFile(wFile, NULL));
// QueryInterface for DirectShow interfaces
JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC));
JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME));
JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS));
// Query for video interfaces, which may not be relevant for audio files
JIF(pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW));
JIF(pGB->QueryInterface(IID_IBasicVideo, (void **)&pBV));
// Query for audio interfaces, which may not be relevant for video-only files
JIF(pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA));
// Is this an audio-only file (no video component)?
CheckVisibility();
if (!g_bAudioOnly)
{
JIF(pVW->put_Owner((OAHWND)ghApp));
JIF(pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN));
}
// Have the graph signal event via window callbacks for performance
JIF(pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0));
if (g_bAudioOnly)
{
JIF(InitAudioWindow());
}
else
{
JIF(InitVideoWindow());
}
// Let's get ready to rumble!
ShowWindow(ghApp, SW_SHOWNORMAL);
UpdateWindow(ghApp);
SetForegroundWindow(ghApp);
SetFocus(ghApp);
UpdateMainTitle();
// Run the graph to play the media file
JIF(pMC->Run());
g_psCurrent=psRUNNING;
SetFocus(ghApp);
}
return hr;
}
HRESULT InitVideoWindow(void)
{
LONG lHeight, lWidth;
HRESULT hr = S_OK;
RECT rect;
int nTitleHeight = GetSystemMetrics(SM_CYCAPTION);
int nBorderWidth = GetSystemMetrics(SM_CXBORDER);
int nBorderHeight = GetSystemMetrics(SM_CYBORDER);
JIF(pBV->GetVideoSize(&lWidth, &lHeight));
// RETAILMSG(1, (TEXT(" Video size: %d x %d\r\n"), lWidth, lHeight));
SetWindowPos(ghApp, NULL, 0, 0, lWidth, lHeight+nTitleHeight, SWP_NOMOVE | SWP_NOOWNERZORDER);
CommandBar_DrawMenuBar(ghCB, 0);
// Account for size of title bar and borders for exact match
// of window client area to default video size
SetWindowPos(ghApp, NULL, 0, 0, lWidth + 2*nBorderWidth,
lHeight + nTitleHeight*2 + 2*nBorderHeight,
SWP_NOMOVE | SWP_NOOWNERZORDER);
GetClientRect(ghApp, &rect);
JIF(pVW->SetWindowPosition(rect.left, rect.top +nTitleHeight, rect.right, rect.bottom+nTitleHeight));
return hr;
}
HRESULT InitAudioWindow(void)
{
SetWindowPos(ghApp, NULL, 0, 0,
DEFAULT_AUDIO_WIDTH,
DEFAULT_AUDIO_HEIGHT,
SWP_NOMOVE | SWP_NOOWNERZORDER);
CommandBar_DrawMenuBar(ghCB, 0);
// Do something different for audio-only files
PaintAudioWindow();
return S_OK;
}
void PaintAudioWindow(void)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
HBRUSH hBrush;
hdc = BeginPaint(ghApp, &ps);
GetClientRect(ghApp, &rect);
// Show white if playing an audio file, gray if not
if (pMC)
hBrush = (HBRUSH) GetStockObject(WHITE_BRUSH);
else
hBrush = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
FillRect(hdc, &rect, hBrush);
EndPaint(ghApp, &ps);
}
void CheckVisibility(void)
{
long lVisible;
HRESULT hr;
g_bAudioOnly = FALSE;
if (!pVW)
{
g_bAudioOnly = TRUE;
RETAILMSG(1, (TEXT("No VideoWindow interface. Assuming audio/MIDI file or unsupported video codec.\r\n")));
return;
}
if (!pBV)
{
g_bAudioOnly = TRUE;
RETAILMSG(1, (TEXT("No BasicVideo interface. Assuming audio/MIDI file or unsupported video codec.\r\n")));
return;
}
hr = pVW->get_Visible(&lVisible);
if (FAILED(hr))
{
// If this is an audio-only clip, get_Visible() won't work.
//
// Also, if this video is encoded with an unsupported codec,
// we won't see any video, although the audio will work if it is
// of a supported format.
//
if (hr == E_NOINTERFACE)
{
g_bAudioOnly = TRUE;
RETAILMSG(1, (TEXT("Video window not visible. Assuming audio/MIDI file or unsupported video codec.\r\n")));
}
else
{
RETAILMSG(1, (TEXT("Failed(%08lx) in pVW->get_Visible()!\r\n"), hr));
}
return;
}
}
void PauseClip(void)
{
if (!pMC)
return;
// Play/pause
if((g_psCurrent == psPAUSED) || (g_psCurrent == psSTOPPED))
{
pMC->Run();
g_psCurrent = psRUNNING;
}
else
{
pMC->Pause();
g_psCurrent = psPAUSED;
}
UpdateMainTitle();
}
void StopClip(void)
{
if ((!pMC) || (!pMS))
return;
// Stop and reset postion to beginning
if((g_psCurrent == psPAUSED) || (g_psCurrent == psRUNNING))
{
LONGLONG pos = 0;
pMC->Stop();
g_psCurrent = psSTOPPED;
pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning ,
NULL, AM_SEEKING_NoPositioning);
// Display the first frame to indicate the reset condition
pMC->Pause();
}
UpdateMainTitle();
}
void OpenClip()
{
HRESULT hr;
// If no filename specified by command line, show open dlg
if(g_szFileName[0] == L'\0')
{
TCHAR szFilename[MAX_PATH];
UpdateMainTitle();
// If no filename was specified on the command line, then our video
// window has not been created or made visible. Make our main window
// visible and bring to the front to allow file selection.
InitAudioWindow();
ShowWindow(ghApp, SW_SHOWNORMAL);
SetForegroundWindow(ghApp);
if (! GetClipFileName(szFilename))
{
DWORD dwDlgErr = CommDlgExtendedError();
// Don't show output if user cancelled the selection (no dlg error)
if (dwDlgErr)
{
RETAILMSG(1, (TEXT("GetClipFileName Failed! Error=0x%x\r\n"), GetLastError()));
RETAILMSG(1, (TEXT(" Dlg Error=0x%x\r\n"), dwDlgErr));
}
return;
}
lstrcpy(g_szFileName, szFilename);
}
hr = PlayMovieInWindow(g_szFileName);
if (FAILED(hr))
{
RETAILMSG(1, (TEXT("PlayMovieInWindow failed! Error=0x%x\r\n"), hr));
PostMessage(ghApp, WM_COMMAND, ID_FILE_EXIT, 0);
}
}
BOOL GetClipFileName(LPTSTR szName)
{
OPENFILENAME ofn={0};
*szName = 0;
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = ghApp;
ofn.lpstrFilter = NULL;
ofn.lpstrFilter = FILE_FILTER_TEXT;
ofn.lpstrCustomFilter = NULL;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrInitialDir = DEFAULT_MEDIA_PATH;
ofn.lpstrTitle = TEXT("Open Media File...\0");
ofn.lpstrFileTitle = NULL;
ofn.lpstrDefExt = TEXT("*\0");
ofn.Flags = OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST;
return GetOpenFileName((LPOPENFILENAME)&ofn);
}
void CloseClip()
{
if(pMC)
pMC->Stop();
g_psCurrent = psSTOPPED;
CloseInterfaces();
}
void CloseInterfaces(void)
{
// Relinquish ownership (IMPORTANT!) after hiding
if(pVW)
{
pVW->put_Visible(OAFALSE);
pVW->put_Owner(NULL);
}
HELPER_RELEASE(pMC);
HELPER_RELEASE(pME);
HELPER_RELEASE(pMS);
HELPER_RELEASE(pBV);
HELPER_RELEASE(pBA);
HELPER_RELEASE(pVW);
HELPER_RELEASE(pGB);
// Clear file name to allow selection of new file with open dialog
g_szFileName[0] = L'\0';
// Redraw menu bar since we've probably resized the main window
CommandBar_DrawMenuBar(ghCB, 0);
// No current media state
g_psCurrent = psINIT;
RECT rect;
GetClientRect(ghApp, &rect);
InvalidateRect(ghApp, &rect, TRUE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -