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
対応ありがとうございます。
変更確認しました。
|