こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

Rectangleで、リソースが解放されない

只今 Borland C コンパイラ 5.5.1 においてプログラムを書いているのですが、(C言語)
仕様なのかどうなのか、ある処理でウィンドウのサイズを
ぐりぐり動かしつづけるとリソースが減っていって
フリーズしていしまいます。使用しているWindowsは98SEです。

そのプログラムは、ウィンドウプロシージャにおいて、

case WM_PAINT:
 hdc = BeginPaint(hWnd,&ps);
 
 hPen = CreatePen(PS_SOLID, 0, RGB(255,0,0));
 hOldPen = (HPEN)SelectObject(hdc, hPen);
 hBrush = CreateSolidBrush(RGB(0,255,0));
 Rectangle(hdc, 10,10,100,100);
 DeleteObject(hPen);
 SelectObject(hdc, hOldPen);
 DeleteObject(hBrush);
 DeleteObject(hOldPen);
 
 EndPaint(hWnd,&ps);
 break;

という風に、Rectangle関数で画面に四角形を描画しているのですが、どうも上記の処理を何度も行うことにより
リソースが解放されずに大量に消費されてしまいます。
C言語においてはまだ少しわかるほどのレベルで、
殆どの関数の意味を今だに理解していなくプログラムの
文法になにかしらの間違いがあるかもしれませんが、
ご指摘いただければ幸いです。

投稿日時 - 2005-08-03 15:40:27

QNo.1557058

困ってます

質問者が選んだベストアンサー

原因が分かりました、というわけではないのですが、気になるところを2点。

(1) hPenがまだselectされている状態でDeleteObjectしています。hPenのselectを解除してから(hOldPenをselectしてから)DeleteObjectしましょう。もしかしたらselectされている状態でDeleteObjectできず、そのせいでリソースが消費されているのかもしれません。

(2) hBrushがどこにも使われていません。SelectObjectし忘れでしょうか。(使用しないことによる問題はありません。)

投稿日時 - 2005-08-03 15:58:31

お礼

すいません、
すぐに回答いただいてそのあとすぐにお礼を言おうとしたのですが、どうやらエラーが起きたようで
ちゃんと投稿されなかったようです。

hPenがselectされている状態ではDeleteOBjectにて削除することはできなかったんですね。
言われたとおりhPenをhOldPenに変えてから削除したところ
リソースは消費されることはなくなりました。
それと、hBrushは確かにいらなかったですね^^;
どうもありがとう御座いました。

投稿日時 - 2005-08-04 00:40:57

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.5

case WM_CREATE:
 hPen = CreatePen(PS_SOLID, 0, RGB(255,0,0));
 hBrush = CreateSolidBrush(RGB(0,255,0));
 break;
case WM_PAINT:
 hdc = BeginPaint(hWnd,&ps);
 SelectObject(hdc, hPen);
 Rectangle(hdc, 10,10,100,100);
 EndPaint(hWnd,&ps);
 break;
case WM_DESTROY:
 DeleteObject(hBrush);
 DeleteObject(hPen);
 break;

といった感じでどうですか?

投稿日時 - 2005-08-04 15:24:10

お礼

この場合は hPenとhBrushの値が初期化されないように、
hPen と hBrush を staticで定義しておかないと
ダメみたいですが、その手もありですね。
最初から最後までずっとhPenを登録してる方法なので、
少しだけでも動作は速くなると思うので、
やってみます。^^
回答有難う御座いました。

投稿日時 - 2005-08-04 16:01:46

ANo.4

1の方のいうとおりDCに選択された状態でDeleteObjectするとリソースリークします。

それと、描画系の処理をするときはSaveDC, RestoreDCを使用されることをオススメします。
現在の設定を保存して、あとで復元することができますので、いちいち以前設定されていたPenやBrushなどを覚えて復元する必要がなくなりミスが減ります。

上記コードですとこんな感じで使用します
int nSaveDC;

case WM_PAINT:
 hdc = BeginPaint(hWnd,&ps);
 
nSaveDC = SaveDC(hdc); /* <-- 設定を保存 */

 hPen = CreatePen(PS_SOLID, 0, RGB(255,0,0));
 SelectObject(hdc, hPen);
 hBrush = CreateSolidBrush(RGB(0,255,0));
 Rectangle(hdc, 10,10,100,100);

RestoreDC( hdc, nSaveDC ); /* 復元 */

/* DCに選択されていない状態で削除*/
 DeleteObject(hPen);
 DeleteObject(hBrush);
 
 EndPaint(hWnd,&ps);
 break;

投稿日時 - 2005-08-04 00:23:49

お礼

以前から参考書などにもsaveDCとRestoreDCとい関数
の説明が載っていましたが全くどう働くのかわからず
スルーしていたことがありましたが、こういうことだったんですね。
しかもいちいちもとのhdcの状態を保持し、
それを一括してもとにもどしてくれる関数があったとは、ほんとに脱帽物です。
回答ありがとうございました。

投稿日時 - 2005-08-04 01:06:42

ANo.3

DeleteObject(hOldPen); ←これが余計な処理では?
これをコメントアウトして試してください。
システムのリソースをDeleteObjectしている気がします。


#2さんへ
「Borland C コンパイラ 5.5.1」 でVCL
は使えないんじゃ?

投稿日時 - 2005-08-03 16:58:05

お礼

>>DeleteObject(hOldPen); ←これが余計な処理では?

確かに余計でした(汗)
SelectObjectによるハンドルとは明記されていたのですが、
これもリソースを消費するのでは?というような
妙な考えを持ってしまいつけていたようでした。
外して試したところリソースは消費されていなかったので、
外して処理致しました。
本当に取っていいのだろうかと心配してたので、
大丈夫だなんだとわかり有難うござした^^

投稿日時 - 2005-08-04 00:55:58

ANo.2

質問とは直接関係ありませんが、お許し下さい。

このプログラムは演習用でしょうか?

デバイスコンテキスト関連のAPI関数を呼ばなくても
void __fastcall TForm1::FormPaint(TObject *Sender)
{
  Form1->Canvas->Pen->Style = psSolid;
  Form1->Canvas->Pen->Color = (TColor)RGB(255,0,0);
  Form1->Canvas->Brush->Style = bsSolid;
  Form1->Canvas->Brush->Color = (TColor)RGB(0,255,0);
  Form1->Canvas->Rectangle(10,10,100,100);
}
で済んでしまうのですが…。
(使う場所によっては、Form1->CanvasのPenとBrushを保存しておいて元に戻す必要がありますが)

このようにしない理由があるのでしょうか?

投稿日時 - 2005-08-03 16:27:12

お礼

すいません、C言語によるプログラムから始めたばかりで、
まだまだ分からない所も山ほどあるので、そういった方法は全く無知でした。
APIから少しでもソフトを作れるようになって、いろいろと
スキル向上を目指したいと思います。
一応今開発しているツールの一部で、HSPのような
プログラムの描き方にはなるんですが、背景用として
Rectangleをこの場合は利用しています。
画面のちらつきを防ぐため、WM_ERASEBKGNDを処理しているので、その背景の変わりに利用してます。
回答ありがとうございました。^

投稿日時 - 2005-08-04 00:49:36

あなたにオススメの質問