![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
趣味でゲームを作っているものです。ゲームのオープニングムービーでmpgファイルを再生したいのですが上手くいきません。詳細は以下の通りです。よろしくお願いします。
ゲームはウインドウモードで作成
ゲームウインドウ内にmpgファイルを再生
DirectXのバージョン DirectX9.0b
ビデオボード GeForce7900GT (ドライバは最新のものを使用)
不具合点
mpgファイルの再生中にウインドウが再描画されたとき(他のウインドウに隠されて
た後、再びアクティブにしたり、最小化後最大化など)ムービーの一部あるいは全部
が黒い画面になってしまいます。再描画されなければ上手くいきます。
また、aviファイルであれば、問題なく動作します。
具体的コード
<初期処理部>
RECT rc;
long w,h;
//COMライブラリの初期化
CoInitialize(NULL);
//GraphBuilder オブジェクトの作成
if(FAILED(CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void **)&pBuilder))){
MessageBox(NULL, "GraphBuilder オブジェクトの作成に失敗しました", NULL, MB_OK);
return E_FAIL;
}
//フィルタ・グラフの作成
if(FAILED(pBuilder->RenderFile(L"sample.mpg",NULL))){
MessageBox(NULL, "フィルタ・グラフの作成に失敗しました", NULL, MB_OK);
return E_FAIL;
}
// AVI描画用ウインドウを作成し...
if(FAILED(pBuilder->QueryInterface(IID_IVideoWindow,(void **)&pVideoWindow))){
MessageBox(0,"AVI描画用ウインドウの作成に失敗しました",NULL,MB_OK);
return E_FAIL;
}
// メインウインドウの子ウインドウに設定する
// ウインドウハンドルの設定
if(FAILED(pVideoWindow->put_Owner((OAHWND)hwnd))){
MessageBox(0,"AVI描画用ウインドウを子ウインドウにすることに失敗しました",NULL,MB_OK);
return E_FAIL;
}
// ウインドウスタイルの設定
if(FAILED(pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS ))){
MessageBox(0,"AVI描画用ウインドウを子ウインドウにすることに失敗しました",NULL,MB_OK);
return E_FAIL;
}
// ウインドウサイズの設定(メインウインドウに合わせる)
GetClientRect(hwnd,&rc);
w=rc.right;
h=rc.bottom;
if(FAILED(pVideoWindow->SetWindowPosition(0,0,w,h))){
MessageBox(0,"ウインドサイズの変更に失敗しました",NULL,MB_OK);
return E_FAIL;
}
// メディアコントロールの取得
if(FAILED(pBuilder->QueryInterface(IID_IMediaControl,(void **)&pMediaControl))){
MessageBox(0,"メディアコントロールの取得に失敗しました",NULL,MB_OK);
return 0;
}
// メディアイベントの取得
if(FAILED(pBuilder->QueryInterface(IID_IMediaEvent,(void **)&pMediaEvent))){
MessageBox(0,"メディアイベントの取得に失敗しました",NULL,MB_OK);
return 0;
}
//ウインドウメッセージの受け取り準備
if(FAILED(pBuilder->QueryInterface(IID_IMediaEventEx,(void **)&pMediaEventEx))){
MessageBox(0,"メディアイベントの作成に失敗しました",NULL,MB_OK);
return E_FAIL;
}
if(FAILED(pMediaEventEx->SetNotifyWindow((OAHWND)hwnd,WM_GRAPHNOTIFY,0))){
MessageBox(0,"メッセージの設定に失敗しました",NULL,MB_OK);
return E_FAIL;
}
<コールバック関数にて>
long ecode,param1,param2;//DirectShow用
switch(iMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
switch((CHAR)wParam)
{
case VK_ESCAPE:
PostQuitMessage(0);
return 0;
}
// DirectShow用
case WM_GRAPHNOTIFY:
while(SUCCEEDED(pMediaEventEx->GetEvent(&ecode,¶m1,¶m2,0))){
switch(ecode){
case EC_COMPLETE:
case EC_END_OF_SEGMENT:
case EC_WINDOW_DESTROYED:
if(FAILED(pMediaControl->Stop())){
MessageBox(0,"停止に失敗しました",NULL,MB_OK);
return 0;
}
GameStartFlag=true;
}
}
break;
}
return DefWindowProc (hWnd, iMsg, wParam, lParam) ;
No.2ベストアンサー
- 回答日時:
すんません。
フラグの照会でSW_RESTOREを無視していました。此方へ修正した方が良いかもしれません。
//追加
//フラグ照会用のタグ
typedef struct __flag_t
{
WORD fwSizeType;//WM_SIZE側のフラグ
int iCmdType;//DirectShowに渡す
int iOAFlag;//DirectShowに渡す
} flag_t;
//修正
//フラグの照会
static const flag_t _S_convert_flag(WORD fwSizeType)
{
const flag_t aflags[] =
{
{SIZE_MAXHIDE, SW_HIDE, OAFALSE},
{SIZE_MAXIMIZED, SW_MAXIMIZE, OATRUE},
{SIZE_MINIMIZED, SW_MINIMIZE, OATRUE},
{SIZE_RESTORED, SW_RESTORE, OATRUE},
{SIZE_MAXSHOW, SW_SHOW, OATRUE}
};
for(int i = 0; i < 5; ++i)
{
if(aflags[i].fwSizeType == fwSizeType)
return aflags[i];
}
return aflags[0];
}
プロシージャの中
+-----------------------------------------------------------------------
case WM_SIZE://修正
{
if(!pVideoWindow)break;
//パラメータの分解
const WORD fwSizeType = wParam;
const int nWidth = LOWORD(lParam);
const int nHeight = HIWORD(lParam);
const flag_t flag = ::_S_convert_flag(fwSizeType);//修正
//ビデオウィンドウのサイズ
pVideoWindow->SetWindowPosition(0, 0, nWidth, nHeight);
//ビデオウィンドウの表示ステートを外側のウィンドウの表示ステートと照会する
pVideoWindow->put_WindowState(flag.iCmdType);
//ビデオウィンドウを表示
pVideoWindow->put_Visible(flag.iOAFlag);
break;
}
-----------------------------------------------------------------------+
No.1
- 回答日時:
こんにちは。
確認出来ました。確かに表示がおかしくなります。
リサイズされた時の為に、WM_SIZEを処理して、pVideoWindow->put_Visible(OATRUE)を呼び出して対応すれば良いようです。
欠けた領域に関しては、DirectShowのビデオウィンドウにInvalidateRect()APIを使用して強引に解決出来るようです。
一通り出来ましたので、以下参考程度に。
#include<windows.h>
#include<dshow.h>
#pragma comment(lib, "strmbasd.lib")
static IGraphBuilder* pBuilder;
static IVideoWindow* pVideoWindow;
static IMediaControl* pMediaControl;
static IMediaEvent *pMediaEvent;
static IMediaEventEx *pMediaEventEx;
bool GameStartFlag = false;
const UINT WM_GRAPHNOTIFY = 0x00008001;
//関数プロトタイプ
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//DirectShowの初期化
static HRESULT _S_init(HWND hwnd)
{
RECT rc;
long w,h;
//COMライブラリの初期化
CoInitialize(NULL);
//GraphBuilder オブジェクトの作成
if(FAILED(CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void **)&pBuilder))){
MessageBox(NULL, "GraphBuilder オブジェクトの作成に失敗しました", NULL, MB_OK);
return E_FAIL;
}
//フィルタ・グラフの作成
if(FAILED(pBuilder->RenderFile(L"sample.mpg",NULL))){
MessageBox(NULL, "フィルタ・グラフの作成に失敗しました", NULL, MB_OK);
return E_FAIL;
}
// AVI描画用ウインドウを作成し...
if(FAILED(pBuilder->QueryInterface(IID_IVideoWindow,(void **)&pVideoWindow))){
MessageBox(0,"AVI描画用ウインドウの作成に失敗しました",NULL,MB_OK);
return E_FAIL;
}
// メインウインドウの子ウインドウに設定する
// ウインドウハンドルの設定
if(FAILED(pVideoWindow->put_Owner((OAHWND)hwnd))){
MessageBox(0,"AVI描画用ウインドウを子ウインドウにすることに失敗しました",NULL,MB_OK);
return E_FAIL;
}
// ウインドウスタイルの設定
if(FAILED(pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS ))){
MessageBox(0,"AVI描画用ウインドウを子ウインドウにすることに失敗しました",NULL,MB_OK);
return E_FAIL;
}
// ウインドウサイズの設定(メインウインドウに合わせる)
GetClientRect(hwnd,&rc);
w=rc.right;
h=rc.bottom;
if(FAILED(pVideoWindow->SetWindowPosition(0,0,w,h))){
MessageBox(0,"ウインドサイズの変更に失敗しました",NULL,MB_OK);
return E_FAIL;
}
// メディアコントロールの取得
if(FAILED(pBuilder->QueryInterface(IID_IMediaControl,(void **)&pMediaControl))){
MessageBox(0,"メディアコントロールの取得に失敗しました",NULL,MB_OK);
return 0;
}
// メディアイベントの取得
if(FAILED(pBuilder->QueryInterface(IID_IMediaEvent,(void **)&pMediaEvent))){
MessageBox(0,"メディアイベントの取得に失敗しました",NULL,MB_OK);
return 0;
}
//ウインドウメッセージの受け取り準備
if(FAILED(pBuilder->QueryInterface(IID_IMediaEventEx,(void **)&pMediaEventEx))){
MessageBox(0,"メディアイベントの作成に失敗しました",NULL,MB_OK);
return E_FAIL;
}
if(FAILED(pMediaEventEx->SetNotifyWindow((OAHWND)hwnd,WM_GRAPHNOTIFY,0))){
MessageBox(0,"メッセージの設定に失敗しました",NULL,MB_OK);
return E_FAIL;
}
return 0;
}
//フラグの照会
static int _S_convert_flag(WORD fwSizeType)
{
switch(fwSizeType)
{
case SIZE_MAXHIDE:return SW_HIDE;
case SIZE_MAXIMIZED:return SW_MAXIMIZE;
case SIZE_MINIMIZED:return SW_MINIMIZE;
case SIZE_RESTORED:
case SIZE_MAXSHOW:return SW_SHOW;
}
return SW_SHOW;
}
//ウィンドウの作成
static HWND _S_create()
{
WNDCLASSEX w = {sizeof(w)};
const char* pszClass = "DirectShowTest";
w.lpfnWndProc = (WNDPROC)WndProc;
w.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
w.lpszClassName = pszClass;
RegisterClassEx(&w);
HWND h = CreateWindow(pszClass,pszClass,WS_OVERLAPPEDWINDOW, 0,0,640,480,NULL,NULL,NULL,NULL);
return h;
}
//見ての通り
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
long ecode,param1,param2; //DirectShow用
switch(iMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
switch((CHAR)wParam)
{
case VK_ESCAPE:
PostQuitMessage(0);
return 0;
}
//此処を処理する
case WM_SIZE:
{
if(!pVideoWindow)break;
//パラメータの分解
const WORD fwSizeType = wParam;
const int nWidth = LOWORD(lParam);
const int nHeight = HIWORD(lParam);
//ビデオウィンドウのサイズ
pVideoWindow->SetWindowPosition(0, 0, nWidth, nHeight);
//ビデオウィンドウの表示ステートを外側のウィンドウの表示ステートと照会する
pVideoWindow->put_WindowState(::_S_convert_flag(fwSizeType));
//ビデオウィンドウを表示
pVideoWindow->put_Visible(OATRUE);
break;
}
//再描画
case WM_PAINT:
//DirectShowのビデオウィンドウを再描画させる
::InvalidateRect(::GetWindow(hWnd, GW_CHILD), NULL, TRUE);
break;
// DirectShow用
case WM_GRAPHNOTIFY:
while(SUCCEEDED(pMediaEventEx->GetEvent(&ecode,¶m1,¶m2,0)))
{
//此れを呼ばないといけない
pMediaEventEx->FreeEventParams(ecode, param1, param2);
switch(ecode)
{
case EC_COMPLETE:
case EC_END_OF_SEGMENT:
case EC_WINDOW_DESTROYED:
if(FAILED(pMediaControl->Stop()))
{
MessageBox(0,"停止に失敗しました",NULL,MB_OK);
return 0;
}
GameStartFlag=true;
}
}
break;
}
return DefWindowProc (hWnd, iMsg, wParam, lParam);
}
//見ての通り
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
{
MSG msg;
//ウィンドウの作成
HWND hWnd = ::_S_create();
//DirectShowの初期化
::_S_init(hWnd);
//再生
pMediaControl->Run();
//ビデオを表示する
pVideoWindow->put_Visible(OATRUE);
//ウィンドウを表示する
::ShowWindow(hWnd, SW_SHOW);
while(::GetMessage(&msg, NULL, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
return msg.wParam;
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・「I love you」 をかっこよく翻訳してみてください
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・昔のあなたへのアドバイス
- ・かっこよく答えてください!!
- ・あなたが好きな本屋さんを教えてください
- ・スタッフと宿泊客が全員斜め上を行くホテルのレビュー
- ・【大喜利】【投稿~8/27】 こんなガソリンスタンド二度と来るか!なぜそう思った?
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・【お題】動物のキャッチフレーズ
- ・【お題】甲子園での思い出の残し方
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・「それ、メッセージ花火でわざわざ伝えること?」
- ・自分用のお土産
- ・人生で一番お金がなかったとき
- ・一番好きなみそ汁の具材は?
- ・泣きながら食べたご飯の思い出
- ・ちょっと先の未来クイズ第1問
- ・ゴリラ向け動画サイト「ウホウホ動画」にありがちなこと
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ダイアログプログラムでEnterキ...
-
不明なエラー
-
LoadImageを使用し、タイトルバ...
-
Win32APIでウィンドウを中央に...
-
エラー Run-Time Check Failur...
-
エディットボックスの背景の色...
-
Win32のファイルダイアログのサ...
-
uwcs マクロについてご質問させ...
-
ゲームとかの解像度変更&全画...
-
PeekMessageについて
-
マイナスからプラスへ転じた時...
-
2÷3などの余りについて
-
エクセルで可視セルにのみ値貼...
-
fgetsなどのときのstdinのバッ...
-
C言語での引数の省略方法
-
プログラムでの数字につく”f”の...
-
DWORDの実際の型は何でしょうか
-
「Aに対するBの割合」と「Aに対...
-
信頼区間の1.96や1.65ってどこ...
-
Aの値からBの値を除するとは??
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Win32APIでウィンドウを中央に...
-
音量調節
-
オーバーレイみたいな処理がしたい
-
return文がない場合の戻り値は...
-
COMPORTマルチスレッドで例外発生
-
エラー Run-Time Check Failur...
-
C言語win32api、エディットボッ...
-
WM_CREATE について
-
キャレットの現在位置の表示 (W...
-
エディットボックスの背景の色...
-
エディットコントロール入力時...
-
LoadImageとSetCursorについて
-
C#のswitch文を簡略化したいの...
-
コンソールアプリケーションの...
-
ウィンドウハンドルがメッセー...
-
PeekMessageについて
-
Win32APIにて、ウィンドウ全体...
-
C++のcase文の書き方
-
MessageBoxについて
-
Directxについて
おすすめ情報