Microsoft DirectX 8.0 |
このトピックでは、特定のウィンドウにビデオ再生をアタッチする方法を解説する。サンプル プログラムを示し、サンプルを理解するために必要な考え方を説明する。このサンプル プログラムは、「ファイルの再生法」で示したサンプルを基にしている。
このトピックは以下のセクションで構成される。
ビデオ ファイルをレンダリングするとき、フィルタ グラフにはビデオ レンダリング フィルタが含まれる。ビデオ レンダラは、圧縮されていないビデオ データを受け取り、ウィンドウ内の画面にそれをレンダリングする。指定しなければ、ビデオ再生ウィンドウは、自身の境界とタイトル バーを持つトップレベルのウィンドウになる。しかし、アプリケーションで作成した特定のウィンドウにビデオを表示することの方が多い。解決策は、レンダラのビデオ ウィンドウをアプリケーション ウィンドウの子ウィンドウにすることである。これを行うには、ビデオ ウィンドウのプロパティを設定して、ウィンドウの所有者、スタイル、および位置を指定する。
ビデオ レンダリング フィルタがサポートする IVideoWindow インターフェイスに、ビデオ ウィンドウのプロパティを設定および取得するためのメソッドが含まれている。しかし、フィルタ グラフ マネージャを使ってフィルタ グラフを構築した場合は、ビデオ レンダリング フィルタへのポインタを持っているとは限らない。そのため、フィルタ グラフ マネージャも IVideoWindow をサポートしている。フィルタ グラフ マネージャは、グラフ内で IVideoWindow を公開しているフィルタのリストを保持し、フィルタ グラフ マネージャの IVideoWindow メソッドが呼び出されると、これらのフィルタへの呼び出しを割り当てる。このようにして、アプリケーションが適切なフィルタを見つけなくても、フィルタ グラフ マネージャがそれぞれのフィルタの処理をサポートできる。
フィルタ グラフ マネージャは、これと同じ手法で IBasicVideo2 および IBasicAudio インターフェイスを公開している。これらのインターフェイスには、オーディオおよびビデオのプロパティを設定するためのメソッドが含まれる。それぞれのフィルタに対してこれらのインターフェイスを呼び出すのではなく、フィルタ グラフ マネージャに対して呼び出す。
このセクションでは、IVideoWindow インターフェイスを使って所有者やスタイルなど、ビデオ ウィンドウのプロパティを設定する方法を説明する。
注 : このトピックのサンプル プログラムでは、コードの大部分は標準のウィンドウ処理を行うものなので、ここでは説明しない。特に、WindowProc および WinMain 関数には、Microsoft® Windows® アプリケーションの典型的なフレームワークが含まれている。アプリケーションで定義する関数、PlayFile および CleanUp については説明する。
まず、フィルタ グラフ マネージャのインスタンスを生成し、IGraphBuilder::RenderFile メソッドを呼び出してフィルタ グラフを構築する。この処理の詳細については、「ファイルの再生法」を参照すること。
次に、再生を始める前に、以下のようにビデオ ウィンドウのプロパティを設定する。
IVideoWindow *pVidWin = NULL; pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin); pVidWin->put_Owner((OAHWND)g_hwnd);
pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
RECT grc; GetClientRect(g_hwnd, &grc); pVidWin->SetWindowPosition(0, 0, grc.right, grc.bottom);
GetClientRect 関数は、RECT 構造体をウィンドウのクライアント領域の座標で満たす。この座標は、クライアント領域の左上隅からのものであるため、left および top メンバは 0 で、right および bottom メンバがそれぞれ幅と高さを定義する。
アプリケーションが終了する前に、ビデオ ウィンドウの表示を False に設定することが重要である。そうしないと、ビデオ イメージが画面に残り、ユーザーはそれを除去することができない。次に、所有者を NULL にリセットする。そうしないと、間違ったウィンドウにメッセージが送信され、エラーが発生する可能性がある。
HRESULT hr = pVidWin->put_Visible(OAFALSE); hr = pVidWin->put_Owner(NULL);
以下のサンプル プログラムは、Test.avi という名前のファイルをアプリケーション ウィンドウの内部にレンダリングする。簡単であるため、以下の機能は省略している。
#include <windows.h> #include <dshow.h> #define CLASSNAME "VideoWindow" IGraphBuilder *pGraph = NULL; IMediaControl *pMediaControl = NULL; IVideoWindow *pVidWin = NULL; HWND g_hwnd; void PlayFile(void) { // フィルタ グラフ マネージャを生成する。 CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&pGraph); pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl); pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin); // グラフを構築する。 pGraph->RenderFile(L"Test.avi", NULL); // ビデオ ウィンドウを設定する。 pVidWin->put_Owner((OAHWND)g_hwnd); pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS); RECT grc; GetClientRect(g_hwnd, &grc); pVidWin->SetWindowPosition(0, 0, grc.right, grc.bottom); // グラフを実行する。 pMediaControl->Run(); } void CleanUp(void) { pVidWin->put_Visible(OAFALSE); pVidWin->put_Owner(NULL); pMediaControl->Release(); pVidWin->Release(); pGraph->Release(); } // メッセージ ハンドラ long FAR PASCAL WindowProc( HWND hwnd, UINT msg, UINT wParam, LONG lParam) { switch (msg) { case WM_DESTROY: CleanUp(); PostQuitMessage(0); break; default: return (DefWindowProc(hwnd, msg, wParam, lParam)); } return(NULL); } // メイン int PASCAL WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow ) { MSG msg; WNDCLASS wc; CoInitialize(NULL); ZeroMemory(&wc, sizeof wc); wc.lpfnWndProc = WindowProc; wc.hInstance = hInst; wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); wc.lpszMenuName = NULL; wc.lpszClassName = CLASSNAME; RegisterClass( &wc ); g_hwnd = CreateWindow( CLASSNAME, "DirectShow Sample", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL); ShowWindow( g_hwnd, nCmdShow ); UpdateWindow( g_hwnd ); PlayFile(); while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } CoUninitialize(); return msg.wParam; }