自作ウィンドウに表示する

今までの例では、再生用に新しいウィンドウが開いてしまいます。 ここでは、自作ウィンドウに絵を表示する方法を説明します。 (注意)ここの例では、サンプルを簡潔にするためにエラー処理を書いていません。

サンプルコード

自作ウィンドウに映像を貼り付けるためには、まず、自分でウィンドウを作らないといけません。 今度のサンプルコードではMFCを利用して自作ウィンドウを作ってみました。 とりあえず、以下を書いて試してみましょう。

コンパイルが通らない場合には、以下の3点を確認してみてください。

  • 構成プロパティ > リンカ > 入力 > 追加する依存関係 に strmiids.libが入っているか。DirectXと思われるリンカのエラーが山のように出たらこれを疑ってください。
  • 構成プロパティ > 全般 で MFCを利用するようになっているか?(共有DLL、staticどちらでも可)。MFCと思われるリンカのエラーが山のように出たらこれを疑ってください。
  • 構成プロパティ > リンカ > システム > サブシステム が ConsoleでなくWindowsになっているか。「未解決の外部シンボル _main が _mainCRTStartup から参照されました」というエラーが出たら疑ってください。


#include <afxwin.h>

#include <dshow.h>

class CMainWin : public CFrameWnd
{
public:
	CMainWin();
	~CMainWin();
	DECLARE_MESSAGE_MAP()
};

CMainWin::CMainWin()
{
 Create(NULL, "Sample");
}

CMainWin::~CMainWin()
{
}

class CApp : public CWinApp
{
public:
	BOOL InitInstance();
};

#define	FILENAME L"c:\\DXSDK\\Samples\\Media\\butterfly.mpg"

BOOL CApp::InitInstance()
{
 m_pMainWnd = new CMainWin;
 m_pMainWnd->ShowWindow(m_nCmdShow);
 m_pMainWnd->UpdateWindow();

 IGraphBuilder *pGraphBuilder;
 IMediaControl *pMediaControl;
 IMediaEvent *pMediaEvent;
 IVideoWindow *pVideoWindow;
 long eventCode;

 CoInitialize(NULL);

 CoCreateInstance(CLSID_FilterGraph,
	NULL,
	CLSCTX_INPROC,
	IID_IGraphBuilder,
	(LPVOID *)&pGraphBuilder);

 pGraphBuilder->QueryInterface(IID_IMediaControl,
	(LPVOID *)&pMediaControl);

 pGraphBuilder->QueryInterface(IID_IMediaEvent,
	(LPVOID *)&pMediaEvent);

 pMediaControl->RenderFile(FILENAME);

 pGraphBuilder->QueryInterface(IID_IVideoWindow,
	(LPVOID *)&pVideoWindow);
 pVideoWindow->put_Owner((OAHWND)m_pMainWnd->GetSafeHwnd());

 pVideoWindow->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS);

 RECT rect;
 m_pMainWnd->GetClientRect(&rect);
 pVideoWindow->SetWindowPosition(0, 0,
	rect.right - rect.left, rect.bottom - rect.top);

 pVideoWindow->SetWindowForeground(OATRUE);
 pVideoWindow->put_Visible(OATRUE);

 pMediaControl->Run();

 pMediaEvent->WaitForCompletion(-1, &eventCode);

 pMediaEvent->Release();
 pVideoWindow->Release();
 pMediaControl->Release();
 pGraphBuilder->Release();
 CoUninitialize();

 return true;
}

BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd)
END_MESSAGE_MAP()

CApp App;

サンプルはMFCで書いてありますが、MFC以外でももちろん同じことはできます。 コードを短く保つために全てをInitInstance()内に詰め込んでいますが、これは良い方法ではありませんので、用途に応じて書き直してください。 このサンプルは再生中にウィンドウが固まります。 これは、InitInstance()の中でWaitForCompletion()をしてしまっていて、再生が終了するまでInitInstance()が終了しないためです。 この問題を回避するには、Threadを使ったり、アプリケーションに再生状態を持たせたりしましょう。

「WaitForCompletion()のようにブロッキングするメソッドを使いたくない!」という方は、SetNotifyWindow()を使うことをお勧めいたします。 SetNotifyWindow()を使ったイベント取得方法に関しては、こちらをご覧ください。