質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Q&A

解決済

1回答

1455閲覧

MCIWndCreate関数のdwStyleについて

mery

総合スコア27

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

0グッド

1クリップ

投稿2019/01/12 22:26

前提・実現したいこと

MCIWndCreate関数のdwStyleの説明には、MCIWNDF_SHOWPOSフラグは「ウィンドウタイトルバーに、MCI デバイスのコンテンツ内の現在位置を表示する。」と書いてあったのですが使ってみてもタイトルバーに何も表示されません。
MCIWNDF_SHOWMODEフラグとMCIWNDF_SHOWNAMEフラグについても試したのですが両方とも何も表示されませんでした。
動画は普通に再生できました。
これらのフラグを有効にしてタイトルバーに情報を正しく表示するにはどうすればいいですか?

該当のソースコード

#include <windows.h> #include<Vfw.h> #pragma comment(lib,"vfw32.lib") LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); TCHAR szClassName[] = TEXT("MCITEST"); //ウィンドウクラス HINSTANCE hinst;//インスタンスハンドル格納用 int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; BOOL bRet; WNDCLASSEX wc; HWND hWnd; ATOM atom; hinst=hCurInst;//インスタンスハンドルをグローバル変数にコピー wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc;//プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hCurInst;//インスタンス wc.hIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = szClassName; wc.hIconSm = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); if ((atom = RegisterClassEx(&wc)) == 0) return FALSE; hWnd = CreateWindow(MAKEINTATOM(atom), TEXT("MCIウィンドウ作成"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinst, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { if (bRet == -1) { break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int)msg.wParam; } //ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { static HWND hmci;//MCIWndCreate関数から返されるハンドル保存用 switch (msg) { case WM_CREATE: hmci=MCIWndCreate( hWnd, hinst, WS_CHILD | WS_VISIBLE | MCIWNDF_SHOWPOS,//ウィンドウスタイルを指定 TEXT("test.wmv")); break; case WM_SIZE: MoveWindow(hmci,0,0,LOWORD(lp),HIWORD(lp),FALSE); break; case WM_ERASEBKGND: break; case WM_DESTROY: MCIWndDestroy(hmci);//MCIウィンドウを破棄する PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

補足情報(FW/ツールのバージョンなど)

Microsoft Visual C++ 2010 Express C言語
WIN32 ユニコードビルド Windows7

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

MCIWNDF_SHOWPOSMCIWNDF_SHOWMODEで指定した情報はMCIWndCreateで作成したウィンドウのタイトルバーに表示されるものです。ご提示のコードですと
hmci = MCIWndCreate(hWnd, hinst, WS_CHILD | WS_VISIBLE | MCIWNDF_SHOWPOS, TEXT("test.wmv"))
とのようにhWndを親にしてウィンドウを作成しているので、タイトルバーは消え、情報は表示されません。以下のように親ウィンドウ指定をNULLにして通常のWS_OVERLAPPEDWINDOWスタイルにすればタイトルバーが出現し、情報が表示されます。

C

1hmci = MCIWndCreate( 2 NULL, 3 hinst, 4 WS_OVERLAPPEDWINDOW | WS_VISIBLE | MCIWNDF_SHOWPOS | MCIWNDF_SHOWMODE | MCIWNDF_SHOWNAME, 5 TEXT("D:/project/test.wmv") 6); 7 8if (hmci != NULL) { 9 if (MCIWndCanPlay(hmci)) { 10 MCIWndPlay(hmci); 11 } 12 else { 13 MessageBox(hWnd, _T("Unable to play"), _T("ERROR"), MB_OK); 14 } 15}

この場合は別途 CreateWindowで作成したウィンドウと同じレベルになるので、そちらは消すか、連携するようコードを書く必要があると思います。

尚、上記コードを実行すると以下のようなウィンドウが出てtest.wmvを再生します。
実行例


コメントを受けて追記:2019/01/13 21:21

MCIウィンドウを閉じてもプログラムが終了していないようです(リビルドするとデバッグを中止しますか?というメッセージが出る)。

ShowWindowを無効にしてもCreateWindowで作成したウィンドウは生きていて、かつメッセージループがあるからです。そのウィンドウも終了させないとプログラムは正しく終了しませんMCIWndCreateで作成したウィンドウの終了を検知して、アプリケーション(=WinMain)全体を終了するようなかたちにしなければなりません。

ご質問内容と主旨からすると今回はあくまでMCIウィンドウだけ使いたい、とのことだと思いましたので、メインウィンドウとしてMCIのウィンドウのみを使う方法をサンプルとして提示させていただきたいと思います。

他サイト様のサンプルコードなどを見てみるとMCIWndCreateで作成したウィンドウをメインにするようなものは見当たらず、主に子ウィンドウとして使うことが多いようでしたので、あまり一般的なコードではないかもしれないことをご承知おきください。

通常ですとMCIWndCreateで作成したウィンドウはそれ自体で閉じていて、WM_...メッセージをハンドリングすることはできません。そこで「ウィンドウのサブクラス化」を利用し、既定のMCIウィンドウのプロシージャに割り込んでWM_...メッセージを横取りします。尚、32ビットと64ビットそれぞれでビルドすることでどちらも動作します。

C

1#include <Windows.h> 2#include <Vfw.h> 3#pragma comment(lib, "vfw32.lib") 4 5static LRESULT CALLBACK SubclassWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 6 7static HINSTANCE g_hInstance = NULL; 8 9static WNDPROC g_PrevWndProc = NULL; 10 11int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) 12{ 13 UNREFERENCED_PARAMETER(hPrevInst); 14 UNREFERENCED_PARAMETER(lpsCmdLine); 15 UNREFERENCED_PARAMETER(nCmdShow); 16 17 g_hInstance = hCurInst; 18 19 HWND hWnd = MCIWndCreate( 20 NULL, 21 g_hInstance, 22 WS_OVERLAPPEDWINDOW | WS_VISIBLE | MCIWNDF_SHOWPOS | MCIWNDF_SHOWMODE | MCIWNDF_SHOWNAME, 23 TEXT("D:/project/test.wmv") 24 ); 25 26 if (hWnd != NULL) { 27 // サブクラス化して、自ウィンドウプロシージャ内でメッセージをハンドリングできるようにする。 28 TCHAR szClassName[256]; 29 GetClassName(hWnd, szClassName, _countof(szClassName)); 30#ifdef _WIN64 31 g_PrevWndProc = (WNDPROC)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_WNDPROC); 32 SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)SubclassWndProc); 33#else 34 g_PrevWndProc = (WNDPROC)(LONG_PTR)GetWindowLongPtr(hWnd, GWL_WNDPROC); 35 SetWindowLongPtr(hWnd, GWL_WNDPROC, (LONG_PTR)SubclassWndProc); 36#endif 37 38 if (MCIWndCanPlay(hWnd)) { 39 MCIWndPlay(hWnd); 40 } 41 else { 42 MessageBox(NULL, TEXT("Unable to play"), TEXT("ERROR"), MB_OK); 43 } 44 } 45 46 MSG msg; 47 BOOL bRet; 48 while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { 49 if (bRet == -1) { 50 break; 51 } 52 else { 53 TranslateMessage(&msg); 54 DispatchMessage(&msg); 55 } 56 } 57 return (int)msg.wParam; 58} 59 60static LRESULT CALLBACK SubclassWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 61{ 62 LRESULT lResult = 0; 63 switch (msg) { 64 case WM_SIZING: 65 // ウィンドウサイズ変更中は無視する 66 break; 67 68 case WM_DESTROY: 69 // WM_DESTROYだけハンドリングする - 自分のメッセージループを抜ける 70 PostQuitMessage(0); 71 break; 72 73 default: 74 // その他のWindowメッセージをデフォルトのウィンドウプロシージャに任せる 75 lResult = CallWindowProc(g_PrevWndProc, hWnd, msg, wParam, lParam); 76 break; 77 } 78 return lResult; 79}

それとMCIウィンドウのウィンドウサイズを変更した時に再生ボタンの辺りがすごくちらつくようになりました。

これについてはご質問の範囲を逸脱するように思うのであまり詳細は述べられませんが、もともとのMCIのウィンドウの動作に依存するので制御には限界があると思います。ちらつきの原因はウィンドウサイズの変更中にWM_PAINTメッセージが発生し、子ウィンドウの再描画が連続して発生しているのだと考えられます。上記サンプルコードではウィンドウのサイズ変更中に受信するWM_SIZINGメッセージを無視するかたちにして再描画させないようにしてみたので、試してみて、ご自分でも対応を考えてみてください。

基本的にはMCIのウィンドウを使う限りにおいて既定の動きを許容するしかないと思うので、それを踏まえて実装していく必要があると思います。そもそもですが、上記のようにMCIのウィンドウをメインとするよりは子ウィンドウにして制御する方が簡単だと思いますし、タイトルバーに情報が載らなくなるのは仕方ありません。もちろん上記のサブクラス化が最良だ、と言う訳ではなく、質問者さんの要望するアプリケーションのかたちで解決法は変わってくると思うので、その点もお含みおきください。今回はあくまで「タイトルバーにMCIWNDF_SHOWPOSで指定した情報を載せたい」が主眼です。

投稿2019/01/13 02:56

編集2019/01/13 12:27
dodox86

総合スコア9183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mery

2019/01/13 05:46

回答ありがとうございました。教えて頂いた方法で試してみたらタイトルバーに情報を表示することができました。 しかし、最初に表示していたウィンドウの消し方が分かりません。 とりあえずShowWindow(hWnd, nCmdShow);の行を消したらMCIウィンドウだけが表示されるようになったのですが、MCIウィンドウを閉じてもプログラムが終了していないようです(リビルドするとデバッグを中止しますか?というメッセージが出る)。 それとMCIウィンドウのウィンドウサイズを変更した時に再生ボタンの辺りがすごくちらつくようになりました。 これらを解決するにはどうすればいいですか?
dodox86

2019/01/13 12:24 編集

最初に表示していたウィンドウは必ずしも必要ではありません。最終的に求めるアプリケーションのかたちによります。詳細を追記しましたのでご覧ください。
mery

2019/01/14 02:33

回答ありがとうございました。 残念ながらちらつきの問題は解決しませんでしたが、教えて頂いたサンプルコードは大変参考になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問