GDIリソースの減少を防ぐには?

解決


しろうと  2005-11-13 20:08:30  No: 127641

環境  VB6(SP6)Windows98_SE、Visual Studio TM6.0(SP6)

素人ですが良ければご指導お願いします。
白黒2値画像を元に指定範囲のフォアカラーの変更を連続して繰返す処理で
GDIリソースが減り続けます。終了すると元に戻ります。

上記の処理をベースにしたシュミレーションプログラムなので、実行中に
GDIリソースが回復出来ないと、最終的にはアウトになってしまいます。

この処理には以下のAPI(GDI32)を駆使したフリーのソースを使用させて頂いています。
GetDIBits Lib "GDI32"
SetDIBits Lib "GDI32"
GetObject Lib "GDI32" Alias "GetObjectA"
CreateDIBitmap Lib "GDI32"
SelectObject Lib "GDI32"
DeleteObject Lib "GDI32"

Webで検索したところ以下の情報が見つかったのですが、
ビットマップのカラー変更の場合でも、仕方ないのでしょうか?
.Netの場合はDispose()で開放するとの情報が有ったのですが
VB6ではどうすれば良いのでしょうか?

基本的な知識の無いど素人ですが宜しくお願いします。

-------------------------------------------------------------------------------------
CreteObjectで作ったオブジェクトのリソースは、実はDeleteObjectでは解放されないのです。
(これは"CreateFontIndirect"特有の現象だと思うのですが)
-------------------------------------------------------------------------------------
http://66.102.7.104/search?q=cache:Ndo4sjBX7aIJ:www.surveytec.com/prog/vb/kouza/chap6.html+VB%E3%80%80GDI%E3%80%80%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9&hl=ja&lr=lang_ja


通ってみた  2005-11-13 21:45:56  No: 127642

案として

アプリケーションをふたつに分ける
1:メインプログラム
2:GDI処理のみのプログラム

1から2をShell起動させ、処理をさせて、Unloadすればリソースが回復すると思うので、繰り返しても大丈夫なのではないかと

実際自分はメモリクリーニングのアプリは待機アプリと掃除アプリを別にしています
そうしないとリソースが減りつづけるので


しろうと  2005-11-13 22:21:51  No: 127643

通ってみたさんご指導有難うございます。

DeleteObjectの他にAPI等でリソースを開放する手段が有るのかな?と思って
質問させて頂いたのですが、仕方なさそうですね。

ご指導頂いた方法など思いつく余裕も知識も経験も無く、ほぼ完成して
テスト段階で不具合に気づき落胆してました。

ご掲示のGDI処理部分を別のプログラムにしてメインから必要の都度起動する
を試して見たいと思います。

有難うございます。


しろうと  2005-11-14 01:47:14  No: 127644

すみません!もうひとつご指導お願いします。

GDI処理側でメインプログラムのフォーム上のPictureBoxと指定色(文字列)が必要で
これをCommand関数の引数に指定して処理出来るかと試したのですが、引数の型が違う!
と怒られてしまします。

文字列以外の引数の受け渡し方が解りません。
基本的なことと思いますが、ご指導お願いします。


しろうと  2005-11-14 23:38:10  No: 127645

無理な様なので解決にさせて頂きます。


しろうと  2005-11-14 23:42:23  No: 127646

解決チェック忘れました。
失礼しました。


通ってみた  2005-11-15 03:33:10  No: 127647

解決になってますが・・・

文字列を数値に変換すればいいだけでは?
「Asc」とか「Val」とかを調べてみてください


gdi  2005-11-16 22:54:13  No: 127648

単に、GDIオブジェクトの後始末の問題だと思いますが・・・
SelectObjectで新しいオブジェクトに置き換えた場合、
使い終えたら必ず、SelectObjectで元のオブジェクトに置き換えてから
DeleteObjectするのが作法だと思いますが?


しろうと  2005-11-17 00:01:34  No: 127649

gdiさんレス有難うございます。
現在は以下のご指導で「クラス化して・・・」を参考にしてクラスモジュールに
していますが、gdiさんご指摘の件を試しましたが変わりませんでした。
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200511/05110074.txt
1.GetBitmapDataEs()プロシージャ側で
    ・・・・・
    ・・・・・
    TempBmp = CreateDIBitmap(moPicBox.hdc, BmpInfo.bmiHeader, 0, 0, BmpInfo, 0)
    OldBmp = SelectObject(moPicBox.hdc, TempBmp)
    ReDim bp(BmpData.bmWidth * BmpData.bmHeight)
    ret = GetDIBits(moPicBox.hdc, OldBmp, 0, BmpData.bmHeight, bp(0), BmpInfo, 0)

    TempBmp = SelectObject(moPicBox.hdc, OldBmp)
    Call DeleteObject(TempBmp)
    
    OldBmp = SelectObject(moPicBox.hdc, TempBmp)
    Call DeleteObject(OldBmp)

2.SetBitmapDataEs()側で
    ・・・・・・・・    
    ・・・・・・・・  
    TempBmp = CreateDIBitmap(moPicBox.hdc, BmpInfo.bmiHeader, 0, 0, BmpInfo, 0)
    OldBmp = SelectObject(moPicBox.hdc, TempBmp)
    ret = SetDIBits(moPicBox.hdc, OldBmp, 0, BmpData.bmHeight, bp(0), BmpInfo, 0)

    TempBmp = SelectObject(moPicBox.hdc, OldBmp)
    Call DeleteObject(TempBmp)
    moPicBox.Refresh
    
    OldBmp = SelectObject(moPicBox.hdc, TempBmp)
    Call DeleteObject(OldBmp)

ど素人でやり方が可笑しいのだと思いますが
宜しくお願いします。


あん  2005-11-17 13:31:21  No: 127650

再利用できるのは次のものだと思います。
TempBmp 
OldBmp 
いちいち作成しなくてもいいです
クラスを新規に作成するとき
TempBmp 
OldBmp 
を作成しておいて
複数処理のとこで
GetBitmapDataEs
SetBitmapDataEs
(TempBmp OldBmp を再利用)  
をコールすればいいと思います。

Call DeleteObject(OldBmp)
これはいらないと思いますが・・

やっとソースがでてきた


しろうと  2005-11-17 19:38:12  No: 127651

あんさん回答有難うございます。
ソースコード(1、2)の最後の2行
   OldBmp = SelectObject(moPicBox.hdc, TempBmp)
   Call DeleteObject(OldBmp)
はgdiさんのレスから、良く理解せずに自分で追加したものです。(_ _)
クラスの記述の仕方自体は間違いでは無さそうなので、今回ご指導頂いたことを
参考にもう一度挑戦してみます。

質問の「タイトル」はこちらが適切なのですが「解決」にしてしまいましたので
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200511/05110074.txt
で続けさせて頂きます。
よろしくお願いします。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加