DVDを再生する(MFC)
前述したDVD再生サンプルでは、自作のウィンドウではなくDefaultのウィンドウを利用しての再生でした。 ここでは、MFCの自作ウィンドウを使ってDVDを再生する方法を説明したいと思います。 (注意)ここの例では、サンプルを簡潔にするためにエラー処理を書いていません。
MFCを使ったウィンドウでのDVD再生サンプル
このサンプルのMFC部分は、「MPEGファイルを再生する3」で説明した内容とほぼ同じです。 違いはDVD graphを作成する部分と、RenderFileをしていないという2点だけです。
このコードは、DVDドライブに入っているDVDをはじめから再生します。 DVDの再生開始は、ウィンドウ内で何らかのキーを押した後に行われます。 ウィンドウ内でキーを押した時にDVDがドライブに入っていない場合には動作しません。 また、私の環境では何故かVisual Studioから起動すると画面が現れませんでした。 もし、動かない場合にはコマンドプロンプトから実行してみてください。
#include <afxwin.h>
#include <dshow.h>
#define WM_GRAPH_NOTIFY (WM_APP + 1)
class CMainWin : public CFrameWnd
{
public:
CMainWin();
~CMainWin();
DECLARE_MESSAGE_MAP()
private:
IDvdGraphBuilder *pDvdGraphBuilder;
IGraphBuilder *pGraphBuilder;
IMediaControl *pMediaControl;
IMediaEventEx *pMediaEventEx;
IVideoWindow *pVideoWindow;
bool bRunning;
protected:
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
LRESULT OnGraphNotify(WPARAM wParam, LPARAM lParam);
};
CMainWin::CMainWin()
{
Create(NULL, "Sample");
bRunning = false;
CoInitialize(NULL);
}
CMainWin::~CMainWin()
{
if (pMediaEventEx != NULL) {
pMediaEventEx->Release();
}
if (pMediaControl != NULL) {
pMediaControl->Release();
}
if (pVideoWindow != NULL) {
pVideoWindow->Release();
}
if (pGraphBuilder != NULL) {
pGraphBuilder->Release();
}
CoUninitialize();
}
void
CMainWin::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (bRunning == false) {
CoCreateInstance(CLSID_DvdGraphBuilder,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDvdGraphBuilder,
(LPVOID *)&pDvdGraphBuilder);
AM_DVD_RENDERSTATUS stat;
pDvdGraphBuilder->RenderDvdVideoVolume(NULL,
AM_DVD_HWDEC_PREFER, &stat);
pDvdGraphBuilder->GetFiltergraph(&pGraphBuilder);
pGraphBuilder->QueryInterface(IID_IMediaControl,
(LPVOID *)&pMediaControl);
pGraphBuilder->QueryInterface(IID_IMediaEventEx,
(LPVOID *)&pMediaEventEx);
pMediaEventEx->SetNotifyWindow((OAHWND)GetSafeHwnd(),
WM_GRAPH_NOTIFY, NULL);
pGraphBuilder->QueryInterface(IID_IVideoWindow,
(LPVOID *)&pVideoWindow);
pVideoWindow->put_Owner((OAHWND)GetSafeHwnd());
pVideoWindow->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS);
RECT rect;
GetClientRect(&rect);
pVideoWindow->SetWindowPosition(0, 0,
rect.right - rect.left,
rect.bottom - rect.top);
pVideoWindow->put_Visible(OATRUE);
pVideoWindow->SetWindowForeground(OATRUE);
pMediaControl->Run();
bRunning = true;
}
}
// イベントが発生すると呼び出される
LRESULT
CMainWin::OnGraphNotify(WPARAM wParam, LPARAM lParam)
{
long evCode;
LONG param1, param2;
// イベントを全て取得
while (SUCCEEDED(pMediaEventEx->GetEvent(&evCode,
¶m1, ¶m2, 0))) {
pMediaEventEx->FreeEventParams(evCode, param1, param2);
switch (evCode) {
case EC_COMPLETE:
// 再生終了
MessageBox("EC_COMPLETE");
break;
}
}
return NOERROR;
}
class CApp : public CWinApp
{
public:
BOOL InitInstance();
};
BOOL CApp::InitInstance()
{
m_pMainWnd = new CMainWin;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return true;
}
BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd)
ON_WM_CHAR()
ON_MESSAGE(WM_GRAPH_NOTIFY, OnGraphNotify)
END_MESSAGE_MAP()
CApp App;