自作ウィンドウに表示する
今までの例では、再生用に新しいウィンドウが開いてしまいます。 ここでは、自作ウィンドウに絵を表示する方法を説明します。 (注意)ここの例では、サンプルを簡潔にするためにエラー処理を書いていません。
サンプルコード
自作ウィンドウに映像を貼り付けるためには、まず、自分でウィンドウを作らないといけません。 今度のサンプルコードでは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()を使ったイベント取得方法に関しては、こちらをご覧ください。