トップページ > 過去ログ > 記事閲覧
SetAlwaysRunFlagについて
名前:まく 日時: 2012/02/14 21:18

SetAlwaysRunFlagがFALSEで、非アクティブの時に画像と音楽の更新を止めたいんですが、SetActiveStateChangeCallBackFunctionを使って、自分で音楽を停止する処理を追加しないと駄目みたいな事が書いてあったんですが、SetActiveStateChangeCallBackFunctionの使い方がイマイチ分からないのですが、何とかSetAlwaysRunFlagがFALSEで音楽止まるようにならないですかね?

Page: 1 |

Re: SetAlwaysRunFlagについて ( No.1 )
名前:いっち 日時:2012/02/15 22:14

SetActiveStateChangeCallBackFunction の使い方は以下のような感じです。 ただし、以下のスレッドと同じような理由だと思いますが、 タスクバーを利用してウィンドウの表示非表示を切り替えた場合、 現状では SetActiveStateChangeCallBackFunction で音楽の再生/停止タイミングを 完全に判断することが出来ないかもしれません。 > h t t p ://hpcgi2.nifty.com/natupaji/bbs/patio.cgi?mode=view&no=2239 //- 以下、テストコード (サウンドファイルをご用意下さい) -// #include "DxLib.h" int sh; int CallbackProc( int state, void* ) { AppLogAdd( "state:%d\n", state ); switch ( state ) { case 0: // 非アクティブ StopSoundMem( sh ); break; case 1: // アクティブ PlaySoundMem( sh, DX_PLAYTYPE_LOOP, FALSE ); break; default: break; } return state; } int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) { ChangeWindowMode( TRUE ); SetWindowText( "DxLib:" DXLIB_VERSION_STR ); if ( DxLib_Init( ) == -1 ) return -1; int white = GetColor( 255, 255, 255 ); SetActiveStateChangeCallBackFunction( CallbackProc, 0 ); sh = LoadSoundMem( "" ); PlaySoundMem( sh, DX_PLAYTYPE_LOOP ); SetDrawScreen( DX_SCREEN_BACK ); while ( ProcessMessage( ) == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { ClearDrawScreen( ); DrawFormatString( 0, 0, white, "TEST" ); ScreenFlip( ); } DxLib_End( ); return 0; }
Re: SetAlwaysRunFlagについて ( No.2 )
名前:まく 日時:2012/02/16 07:29

ご解答ありがとうございます。 やはり完全には出来ないですよね。 現状は書いて頂いた、テストコードを試してみようと思います。
Re: SetAlwaysRunFlagについて ( No.3 )
名前:いっち 日時:2012/02/16 21:05

SetActiveStateChangeCallBackFunction の挙動に関しては一度管理人さんのご意見をお伺いするのが宜しいかと思います。
Re: SetAlwaysRunFlagについて ( No.4 )
名前:管理人 日時:2012/02/19 13:08

SetAlwaysRunFlag( TRUE ) ; で非アクティブ時にも動作するようにしていない場合は PlaySoundMem で鳴らした音は止めるようにしました よろしければこちらのバージョンをお試しになってみてください http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCCTest.exe // Dev-C++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibMinGWTest.exe // MinGW 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』を、 Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい) 尚、PlayMusic で MIDIファイルを演奏している場合は止まりません ( MIDIファイル演奏の一時停止、再開が容易に実装できる機能が存在しなかった為 )
Re: SetAlwaysRunFlagについて ( No.5 )
名前:まく(解決) 日時:2012/02/19 19:55

対応ありがとうございます! お陰様で、非アクティブになった際に、音が止まるようになりました!
Re: SetAlwaysRunFlagについて ( No.6 )
名前:いっち 日時:2012/02/19 20:21

レス(No.1)にも書きましたが SetActiveStateChangeCallBackFunction の仕様について確認させてください。 タスクバーを利用してウィンドウの表示非表示を切り替えた場合、 私の環境(WinXP)ではコールバックが2回立て続けに呼ばれます。 その際の第一引数(ActiveState)が1度目は FALSE(非アクティブ)、 2度目は TRUE(アクティブ)となるのですが、ウィンドウは非表示のままです。 SetActiveStateChangeCallBackFunction の利用目的を考えると好ましい挙動とは思えないのですが、これは仕様となるのでしょうか? ※関連> h t t p ://hpcgi2.nifty.com/natupaji/bbs/patio.cgi?mode=view&no=2239
Re: SetAlwaysRunFlagについて ( No.7 )
名前:管理人 日時:2012/03/04 20:24

私の環境で以下のようなプログラムを組んで試してみましたが、コールバック関数が 2回立て続けで呼ばれるということはありませんでした ( SetAlwaysRunFlag を FALSE にする場合は画面の更新が行われなくなりますので、 ErrorLogAdd のデバッグ出力を利用してコールバック関数が呼ばれたかどうかを確認しました ) よろしければ以下のプログラムがいっちさんの環境ではどのような結果になるか お試しになってみていただけないでしょうか? アクティブになったときにデバッグ出力に「Active」が出力されると同時に ActiveCount が +1 され、 非アクティブになったときはデバッグ出力に「NotActive」が出力されると同時に NotActiveCount が +1されます #include "DxLib.h" int ActiveCount = 0 ; int NotActiveCount = 0 ; // ウインドウのアクティブ状態に変化があったときに呼ばれるコールバック関数 int ActiveStateChange( int ActiveState, void *UserData ) { // アクティブに変化した場合にカウントする if( ActiveState != FALSE ) { ActiveCount ++ ; ErrorLogAdd( "Active\n" ) ; } else { NotActiveCount ++ ; ErrorLogAdd( "NotActive\n" ) ; } // 終了 return 0 ; } // WinMain関数 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // ウインドウモードで起動 ChangeWindowMode( TRUE ) ; SetAlwaysRunFlag( TRUE ) ; // DXライブラリ初期化処理 if( DxLib_Init() == -1 ) return -1 ; // ウインドウのアクティブ状態に変化があったときに呼ばれるコールバック関数をセットする( NULL をセットすると呼ばれなくなる ) SetActiveStateChangeCallBackFunction( ActiveStateChange, NULL ) ; // 描画先画面を裏にする SetDrawScreen( DX_SCREEN_BACK ) ; // ループ while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { // 画面を初期化 ClsDrawScreen() ; // 文字列の描画 DrawFormatString( 0, 0, GetColor( 255,255,255 ), "ActiveCount:%d", ActiveCount ) ; DrawFormatString( 0, 16, GetColor( 255,255,255 ), "NotActiveCount:%d", NotActiveCount ) ; // 表画面と裏画面を取り替えます ScreenFlip() ; } // DXライブラリ使用の終了処理 DxLib_End() ; // ソフトの終了 return 0 ; }
Re: SetAlwaysRunFlagについて ( No.8 )
名前:いっち 日時:2012/03/06 20:05

ご提供頂いたコードを実行したところ再現しました。 テストはリリースビルドを直接実行して行いました。(一応簡単に終わらせられる常駐ソフトなどは終了させています) 当該部分を抜粋しますと以下の様になります。(矢印以降の文は私が行った動作です) 3489:NotActive <- タスクバー上の自タスクボタンをクリックして非アクティブに 3690:Active 4685:Active <- タスクバー上の自タスクボタンをクリックしてアクティブに 6642:NotActive <- タスクバー上の自タスクボタンをクリックして非アクティブに 6807:Active 8187:Active <- タスクバー上の自タスクボタンをクリックしてアクティブに 11540:NotActive <- 他ウィンドウをクリックして非アクティブに 13118:Active <- 自ウィンドウをクリックしてアクティブに 正直なところ自分の環境に全く自信が無いので、 他に再現する方がいらっしゃらないようであれば他の作業を優先して下さい。 ログの全量は以下の通りです。 0:システムの情報を出力します 0: DXライブラリ Ver3.07b 0: 論理プロセッサの数 : 2 0: OS WindowsXP ( Build 2600 Service Pack 3 ) 100: CPU動作速度:大体2.41GHz 100: MMX命令を使用します 100: SSE命令が使用可能です 101: SSE2命令が使用可能です 101: CPUベンダ:GenuineIntel 102: CPU名: Intel(R) Pentium(R) 4 CPU 3.20GHz 103:COMの初期化... 成功しました 106:メモリ総量:2046.73MB 空きメモリ領域:1595.71MB 106:タイマーの精度を検査します 106:精度結果 更新回数 マルチメディアタイマー:0 パフォーマンスカウンター:60 107: パフォーマンスカウンターを使用します タイマー精度 : 3198520.000000 KHz 107: ソフトの二重起動検査... 二重起動はされていませんでした 108:ウインドウクラスを登録します... 登録に成功しました 109:ウインドウモード起動用のウインドウを作成します 115:ウインドウの作成に成功しました 135:IMEを無効にしました 135:ウインドウスタイルをウインドウモード用に変更します... 完了 138:DirectInput関係初期化処理 138: DirectInput7 の取得中... 成功 151: 引き続き初期化処理... 初期化成功 155: ジョイパッドの初期化... 164: 入力装置を見つけました 167: デバイスの登録名:ELECOM JC-PS201U series 168: デバイスの製品登録名:ELECOM JC-PS201U series 186: ジョイパッドの追加は正常に終了しました 186: ジョイパッドの初期化は正常に終了しました 186: マウスデバイスの初期化... 初期化成功 187: キーボードデバイスの初期化... 初期化成功 188:DirectInput 関連の初期化は正常に終了しました 191:DirectSound の初期化を行います 191:DirectSound インターフェースの取得を行います.... 成功 194:引き続きインターフェースの初期化処理... 成功 249: DirectSound デバイスを列挙します 250: モジュール名: ドライバ記述:プライマリ サウンド ドライバ 250: モジュール名: Envy24HF.sys ドライバ記述:Envy24 Family Audio (WDM) 251: 最大サンプリングレート:192.00KHz 最小サンプリングレート:8.00KHz 251: 総サウンドメモリ領域:0.00KB 空きサウンドメモリ領域:0.00KB 251: 利用可能サンプリング精度 251: プライマリ 16bit = OK 8bit = OK 252: セカンダリ 16bit = OK 8bit = OK 252: 利用可能チャンネル 252: プライマリ MONO = OK STEREO = OK 252: セカンダリ MONO = OK STEREO = OK 253:DirectSound の初期化は正常に終了しました 254:DirectDraw オブジェクトの取得を行います.... 成功 258:引き続き初期化処理... 初期化に成功しました 261:IDirect3D9Ex オブジェクトを取得します.... IDirect3D9 オブジェクトを取得します.... 成功 267:IDirect3DDevice9 オブジェクトを取得します.... ハードウエア頂点演算を使用します 567:成功 569:Driver:nv4_disp.dll Description:WinFast A6600 GT 569:画面のフォーマットは D3DFMT_X8R8G8B8 です 569:Zバッファのフォーマットは D3DFMT_D16 です 569:16bit カラーフォーマットは D_D3DFMT_R5G6B5 です 570:32bit カラーフォーマットは D_D3DFMT_X8R8G8B8 です 570:アルファ付き 16bit カラーフォーマットは D_D3DFMT_A4R4G4B4 です 570:アルファ付き 32bit カラーフォーマットは D_D3DFMT_A8R8G8B8 です 570:アルファテスト用 16bit カラーフォーマットは D_D3DFMT_A1R5G5B5 です 571:アルファテスト用 32bit カラーフォーマットは D_D3DFMT_A8R8G8B8 です 571:DXT1テクスチャフォーマットは D_D3DFMT_DXT1 です 571:DXT2テクスチャフォーマットは D_D3DFMT_DXT2 です 571:DXT3テクスチャフォーマットは D_D3DFMT_DXT3 です 572:DXT4テクスチャフォーマットは D_D3DFMT_DXT4 です 572:DXT5テクスチャフォーマットは D_D3DFMT_DXT5 です 572:描画用 16bit カラーフォーマットは D_D3DFMT_R5G5B5 です 572:描画用 32bit カラーフォーマットは D_D3DFMT_X8R8G8B8 です 573:描画用アルファ付き 32bit カラーフォーマットは D_D3DFMT_A8R8G8B8 です 573:描画用ABGR浮動小数点16ビット型カラーフォーマットは D_D3DFMT_A16B16G16R16F です 573:描画用ABGR浮動小数点32ビット型カラーフォーマットは D_D3DFMT_A32B32G32R32F です 573:描画用1チャンネル整数16ビット型カラーフォーマットは D_D3DFMT_G16R16 です 574:描画用1チャンネル不動少数点16ビット型カラーフォーマットは D_D3DFMT_G16R16F です 574:描画用1チャンネル不動少数点32ビット型カラーフォーマットは D_D3DFMT_R32F です 574:最大テクスチャサイズ 幅:4096 高さ:4096 574:テクスチャステージテンポラリレジスタ:使用可 575:減算合成のハードウェア対応:ネイティブ 575:頂点シェーダーバージョンコード:300 575:ピクセルシェーダーバージョンコード:300 819:バックバッファロック転送の時間:78601nsec 一時的な描画可能バッファを使用した転送の時間:2262nsec 819:バックバッファロックを使用しません 819:Zバッファを作成します.... 成功 840:プログラマブルシェーダーを使用します 984:フォントの初期化を行います 989:フォントの初期化は正常に終了しました 992:文字コードバッファの初期化を行います... 完了しました 3489:NotActive 3690:Active 4685:Active 6642:NotActive 6807:Active 8187:Active 11540:NotActive 13118:Active 15224:ウインドウを閉じようとしています 15228:ウインドウが破棄されようとしています 15229:ソフトを終了する準備が整いました 15231:NotActive 15233:フォントの初期化を行います 15234:フォントの初期化は正常に終了しました 15244:Direct3DDevice9 の解放 3 15252:Direct3D9 DLL の解放 4 15253:DirectInput 関連の終了処理... 完了 15257:DirectSound の終了処理は正常に終了しました 15321: 15321:Alloc memory dump 15321: Total size:0(0.000kb) Alloc num:0 15322:
Re: SetAlwaysRunFlagについて ( No.9 )
名前:タカトゥ 日時:2012/03/05 22:10

私の環境でも確認しました。 win7 64bit VC++2010 最小化をともなう非アクティブ(タスクバーのアイコンをクリック、ウィンドウの最小化ボタンをクリック) からタスクバーのアイコンをクリックしウィンドウの表示を行う時にのみ発生します。
Re: SetAlwaysRunFlagについて ( No.10 )
名前:いっち 日時:2012/03/06 21:09

タカトゥさん> ご報告ありがとうございます。 お手数ですが、宜しければその際のログをご提供頂けますか? (Active、NotActiveの部分の抜粋だけで良いと思います) 管理人さん> 以下のようなコードでウィンドウメッセージと状態の遷移を検証してみました。 //- 以下、テストコード -// #include <fstream> #include "DxLib.h" LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); const char *szClassName = "WM_ACTIVATE TEST"; int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow ) { { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH ); wc.lpszMenuName = NULL; wc.lpszClassName = szClassName; if ( !RegisterClass( &wc ) ) return FALSE; } HWND hWnd; hWnd = CreateWindow( szClassName, szClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); ShowWindow( hWnd, nCmdShow ); UpdateWindow( hWnd ); MSG msg; while ( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return 0; } LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { static std::ofstream logtext( "log.txt" ); switch ( message ) { case WM_ACTIVATEAPP: logtext << GetTickCount() << ":" << "WM_ACTIVATEAPP" << ":" << wParam << ":" << lParam << std::endl; break; case WM_ACTIVATE: logtext << GetTickCount() << ":" << "WM_ACTIVATE" << ":" << LOWORD(wParam) << ":" << HIWORD(wParam) << ":" << lParam << std::endl; break; case WM_NCACTIVATE: logtext << GetTickCount() << ":" << "WM_NCACTIVATE" << ":" << wParam << ":" << lParam << std::endl; break; case WM_DESTROY: PostQuitMessage( 0 ); return 0; default: break; } return DefWindowProc( hWnd, message, wParam, lParam ); } //- ここまで、テストコード -// 以下はその際の取得したログです。矢印以降は私のコメントで、見やすいように改行を入れています。 //- 以下、ログ -// 1396265:WM_ACTIVATEAPP:1:1632 <- 起動(アクティブに) 1396265:WM_NCACTIVATE:1:0 1396265:WM_ACTIVATE:1:0:0 1401968:WM_NCACTIVATE:0:0 <- 自タスクボタンクリック(非アクティブに...ならずにアクティブかつ非表示に) 1401968:WM_ACTIVATE:0:0:0 <- (1) ここでいったん非アクティブになったはずだが・・・ 1401968:WM_ACTIVATEAPP:0:708 1402125:WM_ACTIVATEAPP:1:0 <- 余談:LPARAM には本来スレッドIDがはいるはずだがなぜか 0 になる 1402125:WM_NCACTIVATE:2097152:0 <- 余談:WPARAM は 0x200000。本来は BOOL のはず 1402125:WM_ACTIVATE:1:32:0 <- (2) アクティブかつ非表示になってしまう 1406453:WM_NCACTIVATE:1:0 <- 自タスクボタンクリック(アクティブに) 1406484:WM_ACTIVATE:1:0:0 <- (3) 1411140:WM_NCACTIVATE:0:0 <- 最小化ボタンクリック(非アクティブに) 1411156:WM_ACTIVATE:0:32:0 <- (4) 1411156:WM_ACTIVATEAPP:0:2712 1415750:WM_ACTIVATEAPP:1:708 <- 自タスクボタンクリック(アクティブに) 1415750:WM_NCACTIVATE:2097153:0 <- 余談:WPARAM は 0x200001。実質 LOWORD と HIWORD にわかれているっぽい 1415750:WM_ACTIVATE:1:32:0 <- (5) 1415765:WM_ACTIVATE:1:0:0 <- (6) 余談:WM_NCACTIVATE が1つ足りなくて、WM_ACTIVATE との対応が崩れている・・・ 1419875:WM_NCACTIVATE:0:0 <- 他ウィンドウクリック(非アクティブに) 1419875:WM_ACTIVATE:0:0:0 1419875:WM_ACTIVATEAPP:0:2712 1422953:WM_ACTIVATEAPP:1:0 <- 自ウィンドウクリック(アクティブに) 1422953:WM_NCACTIVATE:1:0 1422953:WM_ACTIVATE:2:0:0 1427953:WM_NCACTIVATE:0:0 <- デスクトップクリック(非アクティブに) 1427953:WM_ACTIVATE:0:0:0 1427953:WM_ACTIVATEAPP:0:1632 1430531:WM_ACTIVATEAPP:1:0 <- 自ウィンドウクリック(アクティブに) 1430531:WM_NCACTIVATE:1:0 1430531:WM_ACTIVATE:2:0:0 1433765:WM_NCACTIVATE:0:0 <- 終了(非アクティブに) 1433765:WM_ACTIVATE:0:0:0 1433781:WM_ACTIVATEAPP:0:2712 //- ここまで、ログ -// (1)〜(6)の部分に注目して頂きたいのですが、おそらくこのメッセージのタイミングで SetActiveStateChangeCallBackFunction のコールバックが呼ばれているものと思われます。 特に問題となるのが(2)の部分で、(1)で非アクティブとなった直後にアクティブとしてコールバックが呼ばれます。 対策として、現在、コールバックの第一引数(ActiveState)は BOOL でアクティブ or 非アクティブの判定しかないようですが、 この値にウィンドウが非表示かどうかを判断できるようなフラグを含めて頂くことは出来ないでしょうか? ご検討の程よろしくお願いします。
Re: SetAlwaysRunFlagについて ( No.11 )
名前:管理人 日時:2012/03/11 02:56

すみません、「タスクバーを利用してウインドウの表示・非表示を切り替える」というのを タスクバーの何も無い領域のクリックと自ウインドウのボタンをクリックを行って アクティブ・非アクティブを切り替えることだと思ってしまっていました 載せて頂いた過去ログにある「ウインドウが最小化状態での WM_ACTIVATE のアクティブ化情報を無視する」を グラフィックシステムの復帰以外にも適用することで「アクティブになった」という情報が2回連続で コールバック関数に渡されないようにしました よろしければお試しになってみてください m(_ _;m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_DevCppTest.exe // Dev-C++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_MinGWTest.exe // MinGW 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』を、 Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい)
Re: SetAlwaysRunFlagについて ( No.12 )
名前:いっち 日時:2012/03/11 11:23

対応ありがとうございます。 変更確認しました。

Page: 1 |