トップページ > 過去ログ > 記事閲覧
画面モード変更時
名前:だみあん 日時: 2010/01/18 08:01

管理人さんのお体の調子がよろしくないというのに またまた要望でもうしわけないのですが 画面モードをフルスクリーンに切り替える、またその逆のときに 画像ハンドルをすべて取得し直さなければならない仕様についての要望です。 C言語ベースでなら、それほど困らないのかもしれないのですが c++で組んでいますと、クラスのコンストラクタで画像をロードし、デストラクタで開放。 なんてことをすることは良くあると思います。 そこで、オブジェクト指向の隠蔽や独立性を持たせる場合 画面モードが切り替わったときに画像を保持しているクラスすべてに Reloadメソッドをもたせて実行させる・・・というのは 使い捨ての一時的なオブジェクトなどにも必要だったり なんだか面倒&記述し忘れなどによるバグの温床にもなってしまいます。 全部の基底クラスをつくって、そこで一括してオーバーライドで実行させる。 フレンドで画像を管理するクラスを作って、画像はすべてそこでロードする。 など、解決方法はいくつか思いつくのですが DXライブラリの内部では、 ユニークなint型の値とセットで画像メモリのポインタを保持していると想像するのですけども そこに、ロードに使用したファイル名も一緒に記録させれば、ReloadGraphというような関数で 全ての画像ハンドルの再取得がライブラリ側で可能になるのでは? とおもうのですが いかがでしょうか。 もしくは、ChangeWindowMode_Setの中で暗黙で呼ばれると 画像ハンドルの再取得自体を気にしないで済むので嬉しいのですが。 自前でDXライブラリ自体を弄らない方法で実現しようと思うと 画像管理用のフレンドクラスをつくり そのメンバ関数にLoadGraphなどの画像読み込み系の関数のラッパーを作成し Std::mapで static map<int , string> PIC_FILE_LIST; 画像ハンドルは重複しないユニークな数字がはいるということで 画像ハンドルをキーとして、画像ファイルとセットでファイル名を登録して DeleteGraphのラッパーで該当のキーのリストを削除する。 そして、ReloadGraph()というような関数で 一括リロード。 なんてのが出来そうなのですが。 しかし、LoadDivGraphやMakeGraphといった亜流のものまでラッパーを作成しなくてはならなかったり (キーが配列になるので、厄介そう・・・w) 画像ハンドルを受け取る関数が必要だったり、あまり現実的ではないようなきもします。 できれば、ライブラリ側で隠蔽していただけるとありがたいのですが、いかがでしょうか。 なお、これも特に急ぎというわけでもありせんので お体の調子を見つつ、余裕の足るときにでも前向きに検討していただけると幸いです。

Page: 1 |

Re: 画面モード変更時 ( No.1 )
名前:いっち 日時:2010/01/18 13:02

LoadDivGraphやMakeGraph、CreateGraphFromMem、CreateGraphFromSoftImage あたりのグラフィックハンドルが復元されないのは良いと思いますが、 SetUseASyncChangeWindowModeFunctionで登録したコールバック関数の中でも ReloadFileGraphAllを使えるようにすることは無理なのでしょうか? (以前のバージョンとの互換性を言えば当然無理だとは思いますが・・・)
Re: 画面モード変更時 ( No.2 )
名前:sy(サイ) 日時:2010/01/18 17:12

c++で制作してますが、僕の場合、クラスに必要なロードを関数化して画面モード変更の時に再実行してます。 また、設定などもゲーム側で保管しておいて再設定してます。 隠ぺいされると便利そうですね。
Re: 画面モード変更時 ( No.3 )
名前:いっち 日時:2010/01/18 18:36

急いで書いたために書き忘れてしまいましたが、上記(No.1)は管理人さんへの質問です。 だみあんさんのスレに便乗させて頂きました。 それと、ReloadFileGraphAll関数はLoadDivGraph関数で作ったハンドルも復元してくれるのですね。 勘違いしていました。すみません。 個人的に「なんでReloadFileGraphAll関数が使えないんだろう?」と、 思っていただけなので要望と言う程ではなく、「できたら便利かな?」ぐらいの気持ちです。
Re: 画面モード変更時 ( No.4 )
名前:管理人 日時:2010/01/28 01:50

いっちさんも仰られていますが、MakeGraph や GetDrawScreenGraph、CreateGraphFromMem 等で 作成した画像の復元ができないので、中途半端な機能なら作らない方が良いと思っていたのですが・・・ うーん、ちょっと考えてみます > いっちさん 試してみたことはありませんがコールバック関数の中で ReloadFileGraphAll を使用することは可能だと思います
Re: 画面モード変更時 ( No.5 )
名前:いっち 日時:2010/01/28 13:01

> 試してみたことはありませんがコールバック関数の中で ReloadFileGraphAll を使用することは可能だと思います ちょっとやってみましたが、使えないようです。 おそらくChangeCallbackを呼ぶ前にグラフィックハンドルを全削除しているのでは無いかと思います。 (使い方まちがっていたらすみません) -- 以下 テストソース (Tex1.bmp、Tex2.bmp使用)-- #include "DxLib.h" int image[10]; const char* file[2] = { "Tex1.bmp", "Tex2.bmp" }; void ChangeCallback( void *Data ) { ReloadFileGraphAll( ); SetDrawScreen( DX_SCREEN_BACK ) ; } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { SetUseASyncChangeWindowModeFunction( TRUE, ChangeCallback, NULL ); SetOutApplicationLogValidFlag( FALSE ); if ( DxLib_Init( ) == -1 ) return -1; SetDrawScreen( DX_SCREEN_BACK ); SetDrawArea( 32, 32, 640, 128 ); for ( int i = 0; i < 10; i++ ) image[i] = LoadGraph( file[i % 2] ); int xmove = 0; while ( ProcessMessage( ) == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { ClearDrawScreen( ); for ( int i = 0; i < 10; i++ ) { DrawGraph( i * 64, 0, image[i], FALSE ); } ScreenFlip( ); } DxLib_End( ); return 0; }
Re: 画面モード変更時 ( No.6 )
名前:だみあん 日時:2010/01/29 00:08

>MakeGraph や GetDrawScreenGraph、CreateGraphFromMem 等で 作成した画像の復元ができないので そういった、動的に確保するタイプの物については newとdeleteのように、プログラマ側で責任を持って開放するもしくは復元するべき物だとおもいますが 通常の画像ハンドルに関しては一括で処理できる余地があるのであれば そうしてもらえると嬉しいなという、 言い方はわるいですが、手抜き出来るところは手抜きできればと。 オブジェクト指向的には 画像ハンドルをもったオブジェクトが開放や復元まで責任を持つのが筋なのでしょうけども 画像ハンドルの復元にかんしては ウィンドウモードの切り替え時のみ必要…という限定した場所でのみ必要なこともあり そのためだけに画像ハンドルを保持するクラスすべてに復元用のメソッドを用意して 全てを呼び出すというのは億劫だったりします。 ほかに手段がないならそうするしかないのですが 楽が出来るならそれにこしたことはない的な感じで…。 設計段階で工夫もいろいろと考えたのですが どうしても多様性や拡張性が犠牲になってしまうんですよね…。 ウィンドウモードの切り替えのためだけに…と思うと。
Re: 画面モード変更時 ( No.7 )
名前:いっち 日時:2010/01/29 01:16

>>MakeGraph や GetDrawScreenGraph、CreateGraphFromMem 等で >作成した画像の復元ができないので 私はDirectXに詳しくないので間違った認識をしているのかもしれませんが、 リファレンスなどを読んだ感じでは、おそらくDxLibはLoadGraph系関数で 作ったハンドルのPixelデータを内部で保持していないのではないかと思います。 あくまでDxLibはDirectXへのデータの受け渡しを行うだけで、内部的に保持しているのは ハンドルとファイル名やファイルタイプとの関連付けぐらいなのではないでしょうか。 だとすると、動的に生成された画像のハンドルをDxlibで復元するのは難しいですし、 メモリの効率や実行速度の悪化、ライブラリの複雑化を招きそうなので、 そこまでする必要は無いかなと感じています。(私が勝手に感じても仕様が無いですが) ただ、ReloadFileGraphAllが使えると 1) SoftImageで動的に画像を生成 2) SaveImageでテンポラリに画像を保存 3) LoadGraphでテンポラリから読み込み 4) ウィンドウモードの切り替え 5) ReloadFileGraphAll → 楽チン! なんて事が出来そうなので、良いかなと思っています。 ただ、現状でもコールバック関数内にグラフィック系の初期化処理を 詰め込んでしまえば、大抵の部分はなんとかなります。
Re: 画面モード変更時 ( No.8 )
名前:だみあん 日時:2010/01/29 13:17

・・・一度整理したいのですが ReloadFileGraphAllというのは主にSetRestoreGraphCallbackのなかで使う・・・と リファレンスに記載されていいますよね。 以前何処かでウィンドウモード切り替え時には使えない(そういう用途のものではない) というような事が書かれていた記憶があるのですが (過去ログをあさったのですがみつかりませんでしたので、思い違い? かもしれないですが DxLib.hでこの関数を見つけたときは、おお、こんな便利そうなのがあるじゃないか・・・と思ったものの、 期待していたものとは違った・・・とがっかりした記憶だけは鮮明に残っているので・・・w しかし、今回の要望的に、ReloadFileGraphAllがそのような用途で使える物であれば ReloadFileGraphAllを使ってください。と一言で済む話なので、やはり違うということでいいの・・・ですか?) SetRestoreGraphCallback自体は、ウィンドウモードの切り替え時ではなく フルスクリーンで起動中にalt+tabなどで、タスクを切り替えたときに ウィンドウモードに戻り、再びアプリケーションにタスクを戻してフルスクリーンに戻ったときに 一時的にウィンドウモードに切り替わって無効になった画像ハンドルを復元する関数を登録するという 用途につかわれるのであって ALT+ENTER、ChangeWindowModeで画面モードが変更された時には 関係ない・・・ということでよいのでしょうか。 さらに、リファレンスのSetRestoreGraphCallback項に >それは何故かといいますと、 DXライブラリが LoadGraph 関数 や LoadDivGraph 関数等の >画像ファイルから読み込まれて作成されたグラフィックハンドルの画像を、 >ひそかに再度画像ファイルから読み込んでいるからです。 という記載があるのですが これはすでにグラフィックハンドル自体からリロードの仕組みはすでに備わっているということなのでしょうか。 そうなると、何故、ChangeWindowModeのときにも同様の処理をしてもらえないのかなと・・・。 SetRestoreGraphCallbackのほうでは MakeGraph や GetDrawScreenGraph、CreateGraphFromMem 等の動的に作成する物に対しても フォローされているようですが ChangeWindowModeでの画面モード変更と alt+tabでの一時的なモードの変更では、内部的にはおおきな隔たりがあるのでしょうか・・・。 あと、 どうにも、いっちさんとは見ている方向が違うようで それが混ざってしまって混乱してしまっています。 ChangeWindowModeの際にも、コールバックを使って復元メソッドを実行させる方法を取れと仰っているようにもとれるのですが 動的に画像ハンドルを保持するオブジェクトを生成している場合には、(1画像1オブジェクトでぽこぽこつくってたりしてるので・・・) なんだか煩雑になりそうで、私の場合には適していない様に思えます。 (単純に基底クラスに復元メソッドを用意して仮想関数で実行するだけの方がクラス内に隠蔽されてよさげですし クラスのメンバ関数に、コールバック関数を登録する方法もあるのですが、staticにした上にthisポインタを渡してあげないと使えないとか もともとスマートなやり方ではないっぽいですし、動的に作成したオブジェクトはスマートポインタで扱っているので直で実体にアクセスさせたくない というのもあったりで、使わない方がよさそうかな、とかあるので・・・) 私的には、単純にChangeWindowModeの時にLoadGraph、LoadDivGraph系が暗黙のうちに復元されてくれたら 楽でいいなーというだけですので。 MakeGraph や GetDrawScreenGraph、CreateGraphFromMem 等はプログラマが責任をもって自前で 復元すべきだと思いますし。 一番最初の書き込みでMakeGraph や GetDrawScreenGraph、CreateGraphFromMem 等に触れたのが 面倒の元だったような気がしてます・・・。 あれは、LoadGraph、LoadDivGraph系も含めてすべて自前で処理した場合のことだったので。 LoadGraph、LoadDivGraph系が自動で復元されたなら あとはプログラマが自前で復元すべき動的な画像の復元処理だけを書けば済むから楽でいいな。 というつもりで書いたのです。 もともと開放の面倒を見なくてはならないので、使用箇所はプログラマ的には把握しているべき部分ですし。 あと、管理人さんのレスの >中途半端な機能なら作らない方が良いと思っていたのですが・・・ ですが 私的には、動的作成(MakeGraph等)と、ライブラリ内部で保持する作成系(LoadGraph系)とで 明確に区切りがついていると考えますので その性質的にも、LoadGraph系はライブラリ側で暗黙の内に復元できて 他は出来ない・・・というのは 中途半端という様には感じていないのですが・・・ その辺は私個人の見解なので、他の方はどう考えるのかわかりませんが。
Re: 画面モード変更時 ( No.9 )
名前:いっち 日時:2010/01/29 20:08

まず、誤解していたので訂正します。 私の( No.7 )のレスはだみあんさんの( No.6 )のレス内の > そういった、動的に確保するタイプの物については > newとdeleteのように、プログラマ側で責任を持って開放するもしくは復元するべき物だとおもいますが > 通常の画像ハンドルに関しては一括で処理できる余地があるのであれば > そうしてもらえると嬉しいなという、 > 言い方はわるいですが、手抜き出来るところは手抜きできればと。 上記の部分を読み、だみあんさんが動的に生成した画像の復元を要望されているように見えての レスでしたが、( No.8 )のレスにて誤解だとわかりました。余計な混乱を招き申し訳ありません。 > どうにも、いっちさんとは見ている方向が違うようで > それが混ざってしまって混乱してしまっています。 私は本件を「ウィンドウの状態が切り替わってグラフィックの情報が失われたときに 誰がどうやって復元するのが適切で効率的なのか?」という問題であって、 各個人の実装方法やオブジェクト指向とは関係ない話だと考えています。 ですので、オブジェクト指向としてスマートかどうかなどは気にしていないです。 そもそも、割り込ませて頂いたのは以下の2つの似たような機能(に見える)関数で登録される コールバック関数の挙動の違いに違和感を感じたので、その理由を管理人さんにお聞きしたかったのです。 ・SetRestoreGraphCallback (ウィンドウの状態が一時的に切り替わり元に戻ったら呼ばれる) → グラフィックハンドル復元用の情報を内部に保持 (ReloadFileGraphAll有効) ・SetUseASyncChangeWindowModeFunction (ウィンドウの状態が切り替わったら呼ばれる) → グラフィックハンドル復元用の情報を内部に持たない (ReloadFileGraphAll無効) で、考えてみたのですが、フルスクリーンと非フルスクリーンでは描画環境もだいぶ違いますし、 ウィンドウの状態によって画像を切り替えて使いたいと言う方もきっといらっしゃると思うので、 現状どおりウィンドウの状態が変わったらきれいさっぱりリセットというのも良いかなと考えています。 コロコロと意見が変わって申し訳ありません。つくづく主観でしか物が見えていないと反省しております。 だみあんさんに対しても、趣旨と違った内容を混ぜて混乱を招いてしまい申し訳ありませんでした。 ※上記の内容にDxLibの挙動を推測している部分がありますが、間違っていたらすみません。
Re: 画面モード変更時 ( No.10 )
名前:管理人 日時:2010/01/31 22:39

> いっちさん すいません、仰る通り SetUseASyncChangeWindowModeFunction で登録する関数では、関数が呼び出される前に 画像ハンドルが全て削除されているので ReloadFileGraphAll 関数は使えませんでした orz > だみあんさん、いっちさん 何で SetGraphMode や ChangeWindowMode では画像ハンドルや描画設定が自動復元しないのかを思い出しました なぜなら・・・DXライブラリの元となったライブラリの仕様がそうだったからです(汗 Alt+Tab の画面切り替えでファイルから読み込まれた画像が自動復元する機能は私が後付けしたもので 開発者が意図しないタイミングで画面切り替えが発生した場合も画像ハンドルが無効になるのは一般公開する ライブラリとしては有り得ないと考えたからです( 元となったライブラリは学習用途のライブラリで、学習時には 無くても良いような機能はありませんでした ) それ以外にも、かなり前のことなので当時の自分の考えを推測する感じになりますが、 全く同じ画面モードに戻ってくる Alt+Tab での画面切り替えと違って SetGpaphMode や ChangeWindowMode では カラービット深度が変化する可能性がありますので、いっちさんが仰られていますように変更後には変更前とは 違う形の画像ハンドル作成などを行う可能性があるんじゃないかとか考えていたような気がします ともあれ、以上のこととだみあんさんといっちさんのご意見を踏まえて考えてみますと・・・ 自動読み込みをするかどうかを設定する関数を用意することが一番妥当かなと思いました 挙動の仕様変更を行うわけにはいきません( 画像の自動復元を行うということは今まで自動的に全削除されていた 画像ハンドルが削除されずにそのまま残り続けるということになりますので、現在の仕様を踏まえて作成された プログラムを新仕様のライブラリで実行するとメモリリークの原因になってしまうから )が、確かに自動読み込みの 機能があった方が便利だとも私も思いますし・・・ というわけで、設定関数の追加をする方向で考えてみたいと思います m(_ _)m
Re: 画面モード変更時 ( No.11 )
名前:いっち 日時:2010/01/31 23:47

> なぜなら・・・DXライブラリの元となったライブラリの仕様がそうだったからです(汗 なるほど、2つのコールバックの挙動の違いは開発の経緯によるものだったのですね。 すっきりしました(現在の挙動も十分合理的だと思いますし)。 しかも、対応してくださると言うことで有難い限りです。 私としてはまったく急いでおりませんので、だみあんさんや他の方と 管理人さんのご都合に合わせて対応なさってください。よろしくお願いします。 > だみあんさん この度は横から失礼しました。 おかげさまで疑問が解決いたしました。ありがとうございます。
Re: 画面モード変更時 ( No.12 )
名前:だみあん 日時:2010/02/01 01:58

>というわけで、設定関数の追加をする方向で考えてみたいと思います ただ単に、自動復元をつけると、過去のものに影響が出るというところまで 考えが周りませんでしたw 設定関数追加という形であれ、 とりあえず機能追加の方向でご検討いただけると言うことで 期待しております。 ありがとうございます〜。
Re: 画面モード変更時 ( No.13 )
名前:管理人 日時:2010/02/22 01:14

遅くなってすいません 画面モードを変更した際に ALT+TAB とほぼ同様( 再読み込み関数はライブラリの デフォルト関数に固定 )の復帰処理が行われるようにするかどうかを設定する関数を 追加しましたので、よろしければお試し下さい m(_ _)m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用 (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』、VCをお使いの場合は『リビルド』をして下さい) 追加した関数 // 画面モード変更時( とウインドウモード変更時 )にグラフィックスシステムの設定や // グラフィックハンドルをリセットするかどうかを設定する( TRUE:リセットする( デフォルト ) FALSE:リセットしない ) int SetChangeScreenModeGraphicsSystemResetFlag( int Flag ) ; 使い方ですが、デフォルトでは TRUE の状態になっているので、 DxLib_Init の後にでも一回だけ SetChangeScreenModeGraphicsSystemResetFlag( FALSE ) ; と実行してください、以降 ChangeWindowMode や SetGraphMode が呼ばれても グラフィックハンドルは削除されず、SetDrawArea や SetDrawBlendMode などの 画面設定もリセットされなくなります
Re: 画面モード変更時 ( No.14 )
名前:だみあん 日時:2010/02/22 23:49

早速導入させていただきました。 今のところ問題無く期待どおりに機能しているようです。 これで、煩雑な画像ハンドル関係の復旧処理を考えなくて済むようになったので 嬉しい限りですw 機能追加、ありがとうございました(ぺこり

Page: 1 |