トップページ > 過去ログ > 記事閲覧
タスク切換時の画像復帰
名前:SweetBlack 日時: 2007/01/17 17:44

いつもお世話になります。 順調にゲーム製作を続けていたのですが、 ふと「ALT+TAB」によるタスク切換を試していなかった事を思い出し、試してみたところ、妙な現象がおきました。 一度ALT+TABで処理を切り換え、復帰させてみたところ 一部のキャラクタが表示されなくなってしまったのです。 全てではなく、一部のキャラのみでしたので、 色々と調べていたところ、どうやら CreateGraphFromMem で作成したグラフィックデータを DerivationGraph で切り出して作成したキャラが 表示されなくなっている事に気づきました。 普通にLoadGraphで作成し、DerivationGraphで切り出した場合は 正常に表示される事を確認しましたので、 問題はCreateGraphFromMemの方ではないかと結論づけました。 この現象を回避する方法はありますでしょうか?

Page: 1 | 2 |

追記 ( No.1 )
名前:SweetBlack 日時:2007/01/17 17:52

追記です。 MakeGraphとGetDrawScreenGraphで作成した画像も 復帰されていないような気がします。 これについては詳しく調べておりませんが、一応。
Re: タスク切換時の画像復帰 ( No.2 )
名前:管理人 日時:2007/01/19 13:28

 SweetBlackさんどうも、DXライブラリの管理人です。  フルスクリーンモードで起動している際に「ALT+TAB」で デスクトップ画面に戻る等の画面モード変更が発生した場合 MakeGraph や CreateGraphFromMem で作成した画像の内容が 無くなるのは仕様です。  LoadGraph で読み込んだ画像は再度フルスクリーンになった 際に自動的に読み直されるので何もしなくてもそのまま使い 続けることが出来ますが、MakeGraph や CreateGraphFromMem 等で作成した画像は SetRestoreShredPoint 関数で登録できる、 画像復元用のコールバック関数で読み込み直す必要があります。 // グラフィック復元関数の登録 int SetRestoreShredPoint( void (*ShredPoint)( void ) ) ; (関数名がヘンですが気にしないで下さい・・・)  この関数で登録できるコールバック関数は、フルスクリーンに 再び画面モードが変更された際に呼ばれますので、この関数の中で、 作成された全ての画像のデータを ReLoadGraph や ReCreateGraphFromMem や GetDrawScreenGraph 等を使用して 再度画像を読み込み直すということをします。 (デフォルトでは LoadGraph や LoadDivGraph で作成された 画像のみファイルから読み込み直すということをしています (CreateGraphFromMem や GetDrawScreenGraph で読み込まれた 画像は、既にメモリ上や画面上から無くなっている可能性が 高いので自動で再読み込み処理を行うことが出来ないのです)) サンプル:  画像復元用関数の LoadImage 関数を SetRestoreShredPoint 関数 で登録して、フルスクリーンに戻って来たときに呼ばれるように しています。 #include "DxLib.h" #include <stdio.h> int GraphHandle; // 画像読み込み関数 void LoadImage( void ) { void *Buffer; int BufferSize; FILE *fp; // 画像ハンドルを全て削除する InitGraph(); // 画像ファイルをメモリに読み込む fp = fopen( "test1.bmp", "rb" ); fseek( fp, 0L, SEEK_END ); BufferSize = ftell( fp ); fseek( fp, 0L, SEEK_SET ); Buffer = malloc( BufferSize ); fread( Buffer, BufferSize, 1, fp ); fclose( fp ); // メモリに読み込んだ画像データでハンドルを作成する GraphHandle = CreateGraphFromMem( Buffer, BufferSize ); // メモリに読み込んだ画像データを解放する free( Buffer ); } // WinMain 関数 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // DXライブラリの初期化 if( DxLib_Init() < 0 ) return -1; // 画像の復帰関数を登録する SetRestoreShredPoint( LoadImage ); // 画像を読み込む LoadImage(); // 描画先を裏画面にする SetDrawScreen( DX_SCREEN_BACK ); // メインループ(ESCキーが押されたらループを抜ける) while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { // 画面のクリア ClearDrawScreen(); // 画像の描画 DrawGraph( 0, 0, GraphHandle, TRUE ); // 裏画面の内容を表画面に反映 ScreenFlip(); } // DXライブラリの後始末 DxLib_End(); // ソフトの終了 return 0; }  上記の例では最初の画像の読み込み関数と、復帰用の関数を同じ 関数で行えるように、関数の最初で InitGraph で全ての画像ハンドルを 削除しています。
Re: タスク切換時の画像復帰 ( No.3 )
名前:SweetBlack 日時:2007/01/19 22:55

管理人様、お返事ありがとうございます。 つまり、今現在どの画像が読み込まれているかを 管理しておいて、読み直すという事ですね。 アドバイスありがとうございます。 現在の私のやり方でGetDrawScreenGraphの画像を 復元させるのはかなりホネ(というか不可能)ですが ちょっと考えてみます。
Re: タスク切換時の画像復帰 ( No.4 )
名前:SweetBlack 日時:2007/01/20 21:59

教えていただいた方法だと 今までは自動的に復元されていた画像まで すべて手動で復元しなくてはならないので、 全てのシーンで「現在利用している画像」を チェックしておき、それを復元しなくては ならないようで、変更量が凄くて挫折しそうです……。 すみません、愚痴です。
Re: タスク切換時の画像復帰 ( No.5 )
名前:管理人 日時:2007/01/21 04:31

すみません、この仕様はリファレンスに載せておくべきでした。
Re: タスク切換時の画像復帰 ( No.6 )
名前:SweetBlack 日時:2007/01/22 14:43

たびたびすみません。 また質問させてください。 「ALT+TAB」でタスク切り替えする時、 小さなウィンドウが出てきて、処理を選びますよね? この時に、実行中のプログラム以外に処理を移してから 再度、「ALT+TAB」で処理を戻した場合は問題ないのですが、 「ALT」を押しっぱなしにしたまま、「TAB」をトントンと 押していき、ぐるっと一周させてから、 「実行中のプログラム」に戻して処理を続けさせた場合、 画面に何も表示されなくなってしまいます。 グラフィックデータが消えたとかじゃないようです。 文字すら表示されません。 (再度、別のアプリケーションに処理を移してから  戻すと、ちゃんと表示されるようになる) 管理人さまが提示してくださったサンプルで試しても 同様の現象が起きました。 これは環境のせいでしょうか? 私の環境を次の通りです。 Windows2000 AMD Athlon 64 Processor 3000+ 1.8GHz DirectX 9.0c NVIDIA GeForce 6600 GT
Re: タスク切換時の画像復帰 ( No.7 )
名前:SweetBlack 日時:2007/01/22 14:46

書き忘れましたが、使用ソフトはBCCです。
Re: タスク切換時の画像復帰 ( No.8 )
名前:管理人 日時:2007/01/23 11:50

 SweetBlackさんどうも、DXライブラリの管理人です。  不具合のご報告有難うございます、ライブラリの問題です。  ALT+TABのタスク選択で再び元々実行しているタスクを選択する というのは試していませんでした。  修正したバージョンをアップしましたので、宜しければ お使い下さい。m(_ _)m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe //VC用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe //BCC用 (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』、VCをお使いの場合は『リビルド』をして下さい)
Re: タスク切換時の画像復帰 ( No.9 )
名前:SweetBlack 日時:2007/01/24 23:30

管理人様。 早速の対応ありがとうございます。 ちゃんと動作する事を確認いたしました。 大元の変更の方もなんとか目処が立ちました。 まだいくつか問題が残ってますが (この仕様だとGetDrawScreenGraphの使い道が無いのではないか? とか、  タスク切り替えの際に、タイミング次第では強制終了してしまう?  WaitVSync等を上手く配置すると落ちる確率が減る? 等) 一応は先に進めそうです。 ありがとうございました。
Re: タスク切換時の画像復帰 ( No.10 )
名前:niwa 日時:2007/01/26 22:27

横からですが、報告です。 >タスク切り替えの際に、タイミング次第では強制終了してしまう? こちらでは、'06夏頃のは大丈夫で2.22dから落ちます。 logを見ると復帰後に画像データを読み込んだあと、 また同じデータを読み込んで落ちているようです。
Re: タスク切換時の画像復帰 ( No.11 )
名前:管理人 日時:2007/01/29 13:12

 SweetBlackさん、niwaさんどうも、DXライブラリの管理人です。  不具合のご報告有難うございます。  タスク切り替え時に強制終了してしまう現象ですが、私の環境で 簡易的なテストプログラムを実行した限りでは発生しませんでした。  何か条件があると思うのですが、とりあえず niwaさんのお書き込みにある > logを見ると復帰後に画像データを読み込んだあと、 > また同じデータを読み込んで落ちているようです。  という部分が気になりましたので、同じデータを読み込んで しまっている箇所を修正してみました。  これで正常に動作するかどうかは分かりませんが、宜しければ お試しになってみてください。m(_ _)m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe //VC用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe //BCC用 (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』、VCをお使いの場合は『リビルド』をして下さい)
Re: タスク切換時の画像復帰 ( No.12 )
名前:SweetBlack 日時:2007/01/29 15:02

管理人様、niwa様、色々とありがとうございます。 さて、強制終了の件ですが、新たに頂いた分でも やはり発生しました。 ※これがniwa様のおっしゃる現象と同じものか  どうかは、解りません。念の為。 私は上のほうで 「WaitVSync等を上手く配置すると落ちる確率が減る?」 と書きましたように、特定の条件下では発生しやすい ような気がしましたので、わざとそういうサンプルを 作ってみました。 上のほうの記事(bQ)で管理人様が提示してくださったサンプルに手を加えたものです。 //--------------------------------ここから #include "DxLib.h" #include <stdio.h> int GraphHandle; // 画像読み込み関数 void LoadImage( void ) { void *Buffer; int BufferSize; FILE *fp; // 画像ハンドルを全て削除する InitGraph(); // 画像ファイルをメモリに読み込む fp = fopen( "test1.bmp", "rb" ); fseek( fp, 0L, SEEK_END ); BufferSize = ftell( fp ); fseek( fp, 0L, SEEK_SET ); Buffer = malloc( BufferSize ); fread( Buffer, BufferSize, 1, fp ); fclose( fp ); // メモリに読み込んだ画像データでハンドルを作成する GraphHandle = CreateGraphFromMem( Buffer, BufferSize ); // メモリに読み込んだ画像データを解放する free( Buffer ); } // WinMain 関数 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // DXライブラリの初期化 if( DxLib_Init() < 0 ) return -1; // 画像の復帰関数を登録する SetRestoreShredPoint( LoadImage ); // 画像を読み込む LoadImage(); // 描画先を裏画面にする SetDrawScreen( DX_SCREEN_BACK ); // 画面のクリア ClearDrawScreen(); // 画像の描画 DrawGraph( 0, 0, GraphHandle, TRUE ); // 裏画面の内容を表画面に反映 ScreenFlip(); // メインループ(ESCキーが押されたらループを抜ける) while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { } // DXライブラリの後始末 DxLib_End(); // ソフトの終了 return 0; } //--------------------------------ここまで これだと当然画面の復帰は行われませんが、実験はできました。 タスクを別の処理に切り替え、再び戻す、を何度か繰り返すと落ちます。 私の環境ではほぼ2回目までには落ちました。 念の為に以下にログも記しておきます。 //---------------------------ここから 15:システムの情報を出力します 15: DXライブラリ Ver2.22e 15: OS Windows2000 ( Build 2195 Service Pack 4 ) 115: CPU動作速度:大体1.46GHz 116: MMX命令を使用します 117: CPUベンダ:AuthenticAMD 121: CPU名:AMD Athlon(tm) 64 Processor 3000+ 122:COMの初期化... 成功しました 125:メモリ総量:2047.23MB 空きメモリ領域:1705.73MB 126:タイマーの精度を検査します 127:精度結果 更新回数 マルチメディアタイマー:0 パフォーマンスカウンター:60 128:パフォーマンスカウンターを使用します タイマー分解能 : 3579.545000 KHz 128:ソフトの二重起動検査... 二重起動はされていませんでした 130:ウインドウクラスを登録します... 登録に成功しました 132:フルスクリーンモード用のウインドウを作成します 145:カーソルを不可視にしました 146:IMEを無効にしました 347:DirectInput関係初期化処理 348: DirectInput7 の取得中... 成功 360: 引き続き初期化処理... 初期化成功 362: ジョイパッドの初期化... 369: 入力装置を見つけました 372: デバイスの登録名:Rumble Pad 373: デバイスの製品登録名:Rumble Pad 374: 周期的エフェクトの作成に失敗しました。 375: ジョイパッドの追加は正常に終了しました 376: ジョイパッドの初期化は正常に終了しました 377: マウスデバイスの初期化... 初期化成功 379: キーボードデバイスの初期化... 初期化成功 382:DirectInput 関連の初期化は正常に終了しました 383:DirectSound の初期化を行います 384:DirectSound インターフェースの取得を行います.... 成功 387:引き続きインターフェースの初期化処理... 成功 461: DirectSound デバイスを列挙します 463: モジュール名: ドライバ記述:プライマリ サウンド ドライバ 464: モジュール名: ctaud2k.sys ドライバ記述:SB Live! オーディオ [A000] 465: 最大サンプリングレート:192.00KHz 最小サンプリングレート:4.00KHz 466: 総サウンドメモリ領域:0.00KB 空きサウンドメモリ領域:0.00KB 468: 利用可能サンプリング精度 469: プライマリ 16bit = OK 8bit = OK 470: セカンダリ 16bit = OK 8bit = OK 471: 利用可能チャンネル 472: プライマリ MONO = OK STEREO = OK 473: セカンダリ MONO = OK STEREO = OK 475:DirectSound の初期化は正常に終了しました 476:DirectDraw 関連の初期化を行います 477: DirectDraw オブジェクトの取得を行います.... 成功 481: 引き続き初期化処理... 初期化に成功しました 485: ビデオカードの情報 486: 画面モード変更処理を開始します 547: ウインドウスタイルをフルスクリーンモード用に変更します... 完了 552: 画面モードの変更処理を開始します 640 x 480 16 bit 553: 画面解像度を変更します... 成功しました 692: 画面モードの変更は正常に終了しました 699: カラー情報 703: A:00000000 B:0000f800 G:000007e0 B:0000001f 718: 出力画面用の DirectDrawSurface を作成します 913: 各スクリーンメモリの配置位置 918: PrimaryBuffer : VIDEOMEMORY 924: BaskBuffer : VIDEOMEMORY 927: 出力画面用の DirectDrawSurface の作成は正常に終了しました 937: Direct3D 関連の初期化を行います 949: Direct3Dオブジェクトを取得します 1240: Direct3Dオブジェクトを取得しました 1242: 3Dデバイスを作成します... 3Dデバイスの作成に成功しました 1247: テクスチャ最大幅:4096 最小幅:1 1249: 描画制限: D_D3DPTEXTURECAPS_POW2 = 0 D_D3DPTEXTURECAPS_SQUAREONLY = 0 1250: テクスチャピクセルフォーマット 1250: 通常グラフィック用 1252: BIT:16 RED:5 GREEN:6 BLUE:5 1253: RED:00f800 GREEN:0007e0 BLUE:00001f 1254: BIT:32 RED:8 GREEN:8 BLUE:8 1255: RED:ff0000 GREEN:00ff00 BLUE:0000ff 1257: アルファチャンネル付きグラフィック用 1258: BIT:16 ALPHA:4 RED:4 GREEN:4 BLUE:4 1259: ALPHA:0000f000 RED:00000f00 GREEN:000000f0 BLUE:0000000f 1261: BIT:32 ALPHA:8 RED:8 GREEN:8 BLUE:8 1262: ALPHA:ff000000 RED:00ff0000 GREEN:0000ff00 BLUE:000000ff 1263: Direct3D 関連の初期化は正常に終了しました 1265: グラフィック管理系の初期化を行います 1267: 3Dグラフィック描画機能を使用します 1268: フォントの初期化を行います 1272: フォントの初期化は正常に終了しました 1274: グラフィック管理系の初期化は正常に終了しました 1333: サーフェス間転送には BltFast を使用します 1334: BitBlt:29696μs BltFast:25088μs 1335: スキャンラインの数:480 1465: 1フレーム当たりの時間は 17 msecです 1466: Tri00:17 msec 1468: Tri01:16 msec 1469: Tri02:17 msec 1471: Tri03:16 msec 1473: 画面モード変更処理は正常に終了しました 1482: オーバーレイサーフェスを使用します    UYVY 1483: DirectDraw 関連の初期化は正常に終了しました 1498: 文字コードバッファの初期化を行います... 完了しました 7349: Direct3Dデバイスを削除しました 7351: Direct3Dオブジェクトを解放します 7352: Direct3Dオブジェクトを解放しました 7354: メインサーフェスを破棄をします... 完了しました 7355: DirectInput 関連の終了処理... 完了 7357: DirectDrawオブジェクトを解放します 7361: DirectDrawオブジェクトを解放しました 7363: DirectDraw オブジェクトの取得を行います.... 成功 7366: 引き続き初期化処理... 初期化に成功しました 7370: ビデオカードの情報 7371: 画面モードの変更処理を開始します 640 x 480 16 bit 7373: 画面解像度を変更します... 成功しました 7513: 画面モードの変更は正常に終了しました 7519: 画面モードの変更処理を開始します 640 x 480 16 bit 7526: 画面解像度を変更します... 成功しました 7618: 画面モードの変更は正常に終了しました 7619: 出力画面用の DirectDrawSurface を作成します 7668: 各スクリーンメモリの配置位置 7676: PrimaryBuffer : VIDEOMEMORY 7682: BaskBuffer : VIDEOMEMORY 7698: 出力画面用の DirectDrawSurface の作成は正常に終了しました 7746: Direct3Dオブジェクトを取得します 7747: Direct3Dオブジェクトは正常に取得されました 7749: 3Dデバイスを作成します... 3Dデバイスの作成に成功しました 7763: DirectInput関係初期化処理 7764: DirectInput7 の取得中... 成功 7767: 引き続き初期化処理... 初期化成功 8029: ジョイパッドの初期化... 8036: 入力装置を見つけました 8039: デバイスの登録名:Rumble Pad 8041: デバイスの製品登録名:Rumble Pad 8041: 周期的エフェクトの作成に失敗しました。 8043: ジョイパッドの追加は正常に終了しました 8045: ジョイパッドの初期化は正常に終了しました 8046: マウスデバイスの初期化... 初期化成功 8050: キーボードデバイスの初期化... 初期化成功 8053: DirectInput 関連の初期化は正常に終了しました 14916: Direct3Dデバイスを削除しました 14917: Direct3Dオブジェクトを解放します 14919: Direct3Dオブジェクトを解放しました 14921: メインサーフェスを破棄をします... 完了しました 14922: DirectInput 関連の終了処理... 完了 14924: DirectDrawオブジェクトを解放します 14928: DirectDrawオブジェクトを解放しました 14930: DirectDraw オブジェクトの取得を行います.... 成功 14933: 引き続き初期化処理... 初期化に成功しました 14936: ビデオカードの情報 14938: 画面モードの変更処理を開始します 640 x 480 16 bit 14939: 画面解像度を変更します... 成功しました 15080: 画面モードの変更は正常に終了しました 15085: 画面モードの変更処理を開始します 640 x 480 16 bit 15090: 画面解像度を変更します... 成功しました 15183: 画面モードの変更は正常に終了しました 15184: 出力画面用の DirectDrawSurface を作成します 15224: 各スクリーンメモリの配置位置 15235: PrimaryBuffer : VIDEOMEMORY 15239: BaskBuffer : VIDEOMEMORY 15253: 出力画面用の DirectDrawSurface の作成は正常に終了しました 15301: Direct3Dオブジェクトを取得します 15307: Direct3Dオブジェクトは正常に取得されました 15309: 3Dデバイスを作成します... 3Dデバイスの作成に成功しました
Re: タスク切換時の画像復帰 ( No.13 )
名前:niwa 日時:2007/01/29 23:59

動作報告です。 >logを見ると復帰後に画像データを読み込んだあと、 >また同じデータを読み込んで落ちているようです。 何回か試しましたが、今の所落ちる事はありません。 SweetBlack様のテストプログラムでも落ちません。 (Ver2.22fでは落ちました) ただVC上から実行した時はタスクを切り替えても 画面が戻らない為リセットする必要があります。 あとログのVerを見ると2.22eになっています。 こちらでは2.23なので旨くlibが更新出来ていないのでは?
Re: タスク切換時の画像復帰 ( No.14 )
名前:SweetBlack 日時:2007/01/30 00:34

>あとログのVerを見ると2.22eになっています。 ご指摘ありがとうございます。 テストプログラムの方の更新を忘れていました。 ただし、やはり2.23に更新しても落ちました。 となると私の環境のせいなのでしょうか……?
Re: タスク切換時の画像復帰 ( No.15 )
名前:管理人 日時:2007/01/30 13:16

 SweetBlackさん、niwaさんどうも、DXライブラリの管理人です。 動作テストをして頂き有難うございます。  その後 SweetBlackさんがご掲載して下さったテストプログラムを 実行したところ、私の環境でも同様の強制終了現象が発生しました。  ソフトが非アクティブになった時にはDXライブラリ中の様々な 箇所に仕掛けてある非アクティブチェックプログラムでプログラムが 一時停止するようになっているのですが、丁度 CheckHitKey 関数の中に 仕掛けてあるチェックプログラムで一時停止した場合のみ復帰時に 不正なメモリアクセスが発生するようになっていました。  修正したバージョンをアップしましたので、何度も申し訳ありませんが 宜しければお試しになってみてください。m(_ _)m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe //VC用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe //BCC用 (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』、VCをお使いの場合は『リビルド』をして下さい)

Page: 1 | 2 |