描画が止まっている時は音を止めたい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ジンセイ

描画が止まっている時は音を止めたい

#1

投稿記事 by ジンセイ » 11年前

DXライブラリを使用してゲームを製作しているのですが、
表題の通り描画が止まっている時は音を止めたいと思っています。

現在は以下のようなウィンドウプロシージャを組んでおり、
ウィンドウがアクティブ、非アクティブの場合、描画と一緒に音も鳴ったり止まったりしているのですが、
ウィンドウをつまんだり、Altキーを押下した場合、描画は止まってしまいますが音が止まってくれません。

その場合どのようなメッセージが来るのか、その他にも描画が止まってしまうイベントがあるのかご教示お願い出来ますでしょうか?
Windows に関する知識がないため調べ方も判らず困っています。

コード:

LRESULT CALLBACK
CGameController::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg ) {
    case WM_ACTIVATE:
    {
        {
            CLock lock( _LockObj );
            if( _isLoad != true ) {
                break;
            }
        }

        switch( LOWORD( wParam ) ) {
        case WA_ACTIVE:
        case WA_CLICKACTIVE:
            CSoundController::instance()->restartSE();
            CSoundController::instance()->restartBGM();
            break;
        case WA_INACTIVE:
            CSoundController::instance()->stopSE();
            CSoundController::instance()->stopBGM();
            break;
        default:
            break;
        }
        break;
    }
    default:
        break;
    }

    return 0L;
}

アバター
Dixq (管理人)
管理人
記事: 1661
登録日時: 13年前
住所: 北海道札幌市
連絡を取る:

Re: 描画が止まっている時は音を止めたい

#2

投稿記事 by Dixq (管理人) » 11年前

DXライブラリは公開関数の他にに、DxLib.hの中に便利な非公開関数が沢山あるので、そちらをまずご覧になってはいかがでしょう。

特に、DxLib.hの
「// ウインドウ関係情報取得関数」
以下の関数群はウインドウ系の情報が取得できます。

この中の
GetWindowActiveFlag
はウィンドウがアクティブに動作しているかどうかを取得するもののようです。
使用したことはないですが、この辺を調べてみてはいかがでしょう。

ジンセイ

Re: 描画が止まっている時は音を止めたい

#3

投稿記事 by ジンセイ » 11年前

返信ありがとうございます!
メインループで GetWindowActiveFlag を見るようにしても結果は変わりませんでした。

毎フレーム、コンソールに文字を出力しているのですが、
その動きを見る限り、どうやらウィンドウをつまんでいるときや Alt キーを押下した時は、
プログラムが止まっているように見えます。
# ウィンドウをつまみながらウィンドウを動かすと
# 画面が真っ暗になるのはプログラムが止まっているから?

ジンセイ

Re: 描画が止まっている時は音を止めたい

#4

投稿記事 by ジンセイ » 11年前

Alt キーが押された時、タイトルバーをクリックされた時に
ウィンドウプロシージャにメッセージが飛んでくれば解決なのですが、
ウィンドウメッセージ一覧を他のサイトで見た限り
それらのイベントを見つけることが出来ませんでした。

そもそもそれらのイベントを捕捉することが Windows 的に可能なのか
ご存知の方がいらっしゃいましたらご教示頂ければ幸いです。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 描画が止まっている時は音を止めたい

#5

投稿記事 by ISLe » 11年前

ウィンドウの移動やサイズ変更がはじまるときにWM_ENTERSIZEMOVE、おわったときにWM_EXITSIZEMOVE
Altキーが押された(メインメニューに制御が移った)ときWM_ENTERMENULOOP、もどるときWM_EXITMENULOOP
です。

ホヅミ
記事: 110
登録日時: 13年前

Re: 描画が止まっている時は音を止めたい

#6

投稿記事 by ホヅミ » 11年前

力技ですが
Altキーの時
int CheckHitKey( int KeyCode ) ;
KEY_INPUT_LALT // 左ALTキー
KEY_INPUT_RALT // 右ALTキー

ウィンドウをつまんだとき
マウス座標がウィンドウの外へ出た時に処理

とかはできませんでしたっけ?
自分自身で試していないのでわからないですが。

ジンセイ

Re: 描画が止まっている時は音を止めたい

#7

投稿記事 by ジンセイ » 11年前

みなさん返信ありがとうございます。

やり方はいまいちな気がしますが一応目的が果たせました。
タイトルバーでマウスの左ボタンを離した時のイベント WM_NCLBUTTONUP が上がらず苦労しました。
調べたところ WM_NCLBUTTONUP はダブルクリックした時にしか上がらないようで、
無理やり?WM_NCLBUTTONUP を PostMessage することで対応しました。
一応ソースを添付しておきます。

コード:

LRESULT CALLBACK
CGameController::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    static bool min_size = false;
    static LPARAM save_pos;

    {
        CLock lock( _LockObj );
        if( _isLoad != true ) {
            return 0L;
        }
    }

    switch( msg ) {
    case WM_ACTIVATE:
    {
        switch( LOWORD( wParam ) ) {
        case WA_ACTIVE:
        case WA_CLICKACTIVE:
            if( min_size != true ) {
                CSoundController::instance()->restartSE();
                CSoundController::instance()->restartBGM();
            }
            break;
        case WA_INACTIVE:
            if( min_size != true ) {
                CSoundController::instance()->stopSE();
                CSoundController::instance()->stopBGM();
            }
            break;
        default:
            break;
        }
        break;
    }
    case WM_SYSCOMMAND:
    {
        switch( LOWORD( wParam ) ) {
        case SC_MINIMIZE:
            CSoundController::instance()->stopSE();
            CSoundController::instance()->stopBGM();
            min_size = true;
            break;
        case SC_RESTORE:
            CSoundController::instance()->restartSE();
            CSoundController::instance()->restartBGM();
            min_size = false;
            break;
        default:
            break;
        }
        break;
    }
    case WM_NCLBUTTONUP:
    case WM_NCLBUTTONDBLCLK:
    case WM_EXITMENULOOP:
    {
        CSoundController::instance()->restartSE();
        CSoundController::instance()->restartBGM();
        break;
    }
    case WM_NCLBUTTONDOWN:
    {
        if( wParam != 0x12 ) {
            CSoundController::instance()->stopSE();
            CSoundController::instance()->stopBGM();
        }
        break;
    }
    case WM_ENTERMENULOOP:
    {
        CSoundController::instance()->stopSE();
        CSoundController::instance()->stopBGM();
        break;
    }
    case WM_SETCURSOR:
    {
        if( (((save_pos >> 16) & 0xFFFF) == 0x201) &&
            (((lParam >> 16) & 0xFFFF) == 0x200) ) {
            PostMessage( hWnd, WM_NCLBUTTONUP, 0, 0 );
        }
        save_pos = lParam;
        break;
    }
    case WM_CAPTURECHANGED:
    {
        if( (save_pos & 0xff) == 0x8 ||
            (save_pos & 0xff) == 0x9 ||
            (save_pos & 0xff) == 0x14 ) {
            CSoundController::instance()->restartSE();
            CSoundController::instance()->restartBGM();
        }
        break;
    }
    default:
        break;
    }

    return 0L;
}

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 描画が止まっている時は音を止めたい

#8

投稿記事 by ISLe » 11年前

WM_SYSCOMMANDのSC_MINIMIZE/SC_RESTOREはシステムメニューが選択されたときのメッセージで、実際に最小化されるタイミングではないので注意が必要です。
実際に最小化されるタイミングで発行されるメッセージは別にあります。

そもそも最小化されれば非アクティブになるので必要ない気がします。
min_sizeの判定はそのせいでわざわざ入ってますよね?

もっとまとめられるはずですけど。

あと、カテゴリの違うウィンドウメッセージ間では到着順が予測できないので、まとめて排他制御するとデッドロック起こす可能性があります。

ジンセイ

Re: 描画が止まっている時は音を止めたい

#9

投稿記事 by ジンセイ » 11年前

返信ありがとうございます。

> WM_SYSCOMMANDのSC_MINIMIZE/SC_RESTOREはシステムメニューが選択されたときのメッセージで、実際に最小化されるタイミングではないので注意が必要です。
> 実際に最小化されるタイミングで発行されるメッセージは別にあります。

「ウィンドウ 最小化 メッセージ」等で検索をかけると
WM_SYSCOMMAND の SC_MINIMIZE/SC_RESTORE を使用している解説サイトを多く見かけますが、
よろしければそのメッセージを教えて頂けないでしょうか?

> そもそも最小化されれば非アクティブになるので必要ない気がします。
> min_sizeの判定はそのせいでわざわざ入ってますよね?
> もっとまとめられるはずですけど。

タスクバーを左クリックで最小化を行うとなぜか WA_ACTIVE が上がってくるので
仕方なく min_size の判定を入れています。
もっとスマートな方法があれば是非ご教授お願いします。

> あと、カテゴリの違うウィンドウメッセージ間では到着順が予測できないので、まとめて排他制御するとデッドロック起こす可能性があります。

排他をかけているのはフラグ参照のところだけなので
どういう呼ばれ方をしたとしてもデッドロックはしません。

アバター
へにっくす
記事: 634
登録日時: 11年前
住所: 東京都

Re: 描画が止まっている時は音を止めたい

#10

投稿記事 by へにっくす » 11年前

WM_SIZEでキーワード検索かけましょう
最小化ボタン押そうが、タスクバーで最小化を選択しようが、必ずこのメッセージが来ます。
最小化の判定はパラメータで出来ますよ。
以下、MSDNの説明(英語ですが)
WM_SIZE message
ジンセイ さんが書きました:タスクバーを左クリックで最小化を行うとなぜか WA_ACTIVE が上がってくるので
あたりまえ。クリックした時点でアクティブになるんですから。
written by へにっくす

ジンセイ

Re: 描画が止まっている時は音を止めたい

#11

投稿記事 by ジンセイ » 11年前

ありがとうございます。
WM_SIZE の SIZE_MINIMIZED で最小化の判定を行うのが一般的なんですね。
ちょっと試してみます。

> あたりまえ。クリックした時点でアクティブになるんですから。

タスクバーの左クリックで最小化するとそのウィンドウは非アクティブになるのに
WA_ACTIVE が上がってくるのがなぜ「あたりまえ」と言えるのでしょうか?

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 描画が止まっている時は音を止めたい

#12

投稿記事 by ISLe » 11年前

デッドロックは違いましたね。
言いたかったのは、処理すべきメッセージがスルーされて、再生すべきところで停止したり停止すべきところで再生したりする状況になってしまう可能性があるということです。

対応するのは、ウィンドウのアクティブ・非アクティブ以外に、前に回答した2組みのメッセージだけで良いはずですけど。

わたしは参照カウンタ用意して特定の値に変化したら再生開始、他の値に変化したら再生停止のようにしてます。
あと、一瞬鳴るのが気になるのであれば、1秒ほど待って再生するとか、音量を徐々に上げるとか、いきなり鳴らさなければ良いと思います。


タスクバーはアクティブなウィンドウ(というかアプリ)を切り替えるのが本来の役目なのですから、クリックしたら(最小化する前にいったん)アクティブになるのは当たり前だとわたしも思います。
あとWindows 7より前とWindows 7以降でタスクバーのアイコンをクリックしたときの動作は異なりますし、レジストリの設定をいじるとさらに細かく変化します。
なのでマウスクリックのメッセージを捕まえて細かく制御しようとすると、実行環境が変わったときにハマりますよ。

閉鎖

“C言語何でも質問掲示板” へ戻る