お世話になります、fujicafeです。
現在、MFCにてダイアログベースのアプリケーションを作成中なのですが、ダイアログにビットマップを貼り付けてOnPaint()で表示するようにプログラムを作成したのですが、何度かダイアログの表示を繰り返すとOnPaintでのビットマップの読み込みが途中まででフリーズしてしまう現象が起きてしまいました。
プログラムは以下のように作成しています
void C****Dlg::OnPaint()
{
CDC* pDC = this->GetDC();
CDC myDC;
CBitmap newbitmap;
CBitmap* oldbitmap;
CRect rc;
GetClientRect(rc);
newbitmap.LoadBitmap(IDB_BITMAP);
myDC.CreateCompatibleDC( pDC );
oldbitmap=myDC.SelectObject( &newbitmap );
pDC->BitBlt( 0, 0, rc.Width(), rc.Height(), &myDC, 0, 0, SRCCOPY );
myDC.SelectObject(oldbitmap);
}
としています。
初めにこのダイアログを表示時は、ちゃんとビットマップが表示されるのですが、他のダイアログでこのダイアログを表示させた時にビットマップが上半分まで表示されて、動作がフリーズしてしまう現状です。
なにかよい打開策がありましたら、教えていただけたらと思っています。宜しくお願いいたします。
No.5
- 回答日時:
>何度かダイアログの表示を繰り返すとOnPaintでのビットマップの読み込みが途中まででフリーズしてしまう現象が起きてしまいました。
デバイスコンテキストを「使いっぱなし」にしてはいけません。使った物はちゃんと片付けましょう。
GetDCした場合、そのデバイスコンテキストを使い終わったらReleaseDCしなければなりません。
ReleaseDCをせずにGetDCを何度も繰り返すと、デバイスコンテキストのロックリソースが尽き、デバイスコンテキストへのアクセスが出来なくなったり(つまり、画面の描画が出来なくなったり)、スレッドが応答しなくなったりします。
また、CreateCompatibleDCで作成したデバイスコンテキストも、使い終わったらDeleteObjectで削除しなければなりません。
DeleteObjectをせずにCreateCompatibleDCを何度も繰り返すと、デバイスコンテキストのリソースが尽き、デバイスコンテキストへのアクセスが出来なくなったり(つまり、画面の描画が出来なくなったり)、スレッドが応答しなくなったりします。
以下の2点にご注意下さい。
・GetDCでデバイスコンテキストを占有した場合は、必ずReleaseDCで不要になったデバイスコンテキストのロックを解除して開放すること。
・CreateCompatibleDCでデバイスコンテキストを作成した場合は、必ずDeleteObjectで不要になったデバイスコンテキストを削除すること。
因みに、デバイスコンテキストは「各スレッドで同時に使えるのは16個くらい」なので、ダイアログの表示を5~8回も行えば、デバイスコンテキストのリソースが尽き、プロセスがフリーズするでしょう。
なお、あくまでも「同時に使えるのは」です。
なので「占有→使用→開放を16回以上」はOKです。これは「同時に使っているのは1個だけ」なので、何の問題もありません。
ですが「占有→使用→放置を16回以上」はNGです。これは「同時に使っているのは16個以上」なので、リソース不足でダウンします(質問者さんのプログラムが、この状態になっている)
ご回答ありがとうございます。
早速、CreateCompatibleDCを仕様したデバイスコンテキストをDeleteObjectしてみたのですが、やはりフリーズします。
そこで、CpaintDCを使用してBitBltしている箇所をあえて、
CDC* pDC = this->GetDC();
でデバイスコンテキストを取得し、最後にReleaseDCで解除するように変更したのですが、やはりフリーズしてしまいました。
呼び出す側のピクチャーコントロールへのビットマップの貼り付けをはずすか、呼ばれるダイアログの背景のビットマップの貼り付けをはずすとフリーズせずに動作するようなのですが、これは使用しているマシンの性能の問題なのでしょうか?
開発で使用しているマシンがPCではなく、組み込みのマシンのためそういう問題もあるのかなと思っています。
No.4ベストアンサー
- 回答日時:
こんにちは。
補足頂きました。よく考えたら、CBitmapのデストラクタでビットマップが消去されているので、リークではなかったかもしれません。
http://msdn.microsoft.com/ja-jp/library/wc99t364 …
・なにかまだ考えられることがありましたら宜しくお願い致します。
取りあえず、当方もフリーズの経験があるのですが、確りとCPaintDCの方を使用していますでしょうか。
OnPaint()(WM_PAINTメッセージ相当)の中では、GetDC()/ReleaseDC()を使用して描いてはならず、BeginPaint()/EndPaint()相当(CPaintDC)に描かせます。
http://msdn.microsoft.com/ja-jp/library/a48eab8d …
http://orangeknowledge.jpn.org/report060325.html
後、提示したコードが良くなかったかもしれません。以下の様にして見て下さい。
void C****Dlg::OnPaint()
{
CPaintDC paintDC(this);//此れじゃないと問題を起こす事がある
CDC myDC;
CBitmap* oldbitmap;
CRect rc;
GetClientRect(rc);
myDC.CreateCompatibleDC(&paintDC);
oldbitmap=myDC.SelectObject( &m_newbitmap );
paintDC.BitBlt( 0, 0, rc.Width(), rc.Height(), &myDC, 0, 0, SRCCOPY );
myDC.SelectObject(oldbitmap);
//不安なら以下をコメントアウト
//myDC.DeleteDC();
}
詳細な情報ありがとうございます。
早速、ご提示頂いたコードで動作させてみました。
結果としては
前回と同様にフリーズしてしまいました。
コードを提示して頂いて、ただ出来ない出来ないと文句を言っているようで本当に大変申し訳ございません。
私なりにもしらべて見たのですが、4つの各ダイアログを呼び出すメインダイアログ1,2にはピクチャーコントロールがあり、それぞれがビットマップを表示するようにしています。このピクチャーコントロールへのビットマップの貼り付け方法なのですが、ピクチャーコントロールのプロパティでイメージにビットマップのIDを選択させてビットマップを表示させるようにしているのですが、この方法ですと何か問題はありますでしょうか?
背景のビットマップと同様に、各ピクチャーコントロールに対するビットマップもOnInitialDialog()内で貼り付けて、OnPaintでBitBltで表示するようにしたらよいのでしょうか。
質問するくらいなら実際にやればいいのでしょうが、なぜかうまくその方法ですとピクチャーコントロールに画像が描画されないため悩んでいるところです。
たびたびの質問で申し訳ございません。
No.3
- 回答日時:
CBitmap が、どう振舞うのか?
メモリデバイスコンテキストはどう使うのか?
このあたりの基本を勉強したほうがいいです。
newbitmap もメンバにしないといけないはずです。
ご指示ありがとうございます。
確かに、本やネットをみて、このコードでならビットマップ
が貼り付けれるとしか考えていなかったです。
しっかりとメモリデバイスコンテキストの振る舞いやCBitmap
について勉強し直さなければならないみたいです。
CBitmapをメンバ変数にしてみましたが、結果は変わらずでした。
もしかしたら
ダイアログ内のピクチャーボックスにビットマップを貼り付けている
のですが、その貼り付け方法がプロパティのイメージでビットマップの
IDを選択している
ということも影響の要因なのかなと思っています。
これも関係ありますでしょうか?
No.1
- 回答日時:
こんばんは。
OnPaint()が呼ばれる度に、ビットマップをリソースからロードしているので、リークを起こしているのではないでしょうか。
newbitmapをメンバ変数にして、OnInitDialog()で作成して置くのが無難です。
後、OnPaint()でダイアログに描写する際は、CDCではなくて、PaintDCの方ではないでしょうか。
以下では駄目でしょうか。
class C****Dlg
{
private:
CBitmap m_newbitmap;//ヘッダに移動
};
BOOL C****Dlg::OnInitDialog()
{
// TODO: 特別な初期化を行う時はこの場所に追加してください。
//此処で作成しておく
m_newbitmap.LoadBitmap(IDB_BITMAP);
return TRUE; // TRUE を返すとコントロールに設定したフォーカスは失われません。
}
void C****Dlg::OnPaint()
{
//再描画で使用するDC
CPaintDC paintDC(this);
CDC myDC;
CBitmap* oldbitmap;
CRect rc;
GetClientRect(rc);
//互換メモリデバイスコンテキストの作成
CDC* pDC = this->GetDC();
myDC.CreateCompatibleDC(pDC);
ReleaseDC(pDC);
//選択して書く
oldbitmap=myDC.SelectObject( &m_newbitmap );
paintDC.BitBlt( 0, 0, rc.Width(), rc.Height(), &myDC, 0, 0, SRCCOPY );
myDC.SelectObject(oldbitmap);
}
この回答への補足
もう一つ付け加えなのですが、メインダイアログ1で4つのダイアログ
を各コントロールから呼び出す際には今回のような症状が出ていません。
メインダイアログ1からメインダイアログ2を呼び出して、さらにそこから4つのダイアログを呼び出していった時の4番目のダイアログの呼び出し時に必ずこの現象が生じるようです。
丁寧な説明ありがとうございます。
早速、教えて頂いた通りにビットマップの呼び出しをOnInitDialog()
に移動させ、OnPaint()内ではBitBltのみを処理するようにして観ました。
結果としては、以前と同様にビットマップの呼び出しで動作がフリーズしてしまいます。でも、確かにメモリリークを起こしているような気がします。
現在のプログラムの詳細な状況を説明させていただきますと、
メインのダイアログが2つありまして、それをメインダイアログ1,メインダイアログ2とします。
メインダイアログ1からメインダイアログ2を呼び出すにはF1キーで呼び出します。メインダイアログ1,メインダイアログ2にはそれぞれ同じボタンが4つありまして、4つのボタンで4つのダイアログを表示させます。ダイアログは全て背景をビットマップとしています。
現在の症状としては、フリーズするときにはダイアログ上の背景ビットマップが約上半分表示され、ダイアログ上のコントロールは全て空白となり、呼び出したメインダイアログの背景が透けて見えるといった状況です。
開発環境がWindows CE6.0でVisualStudio2005なのが不安ではあるのですが、なにかまだ考えられることがありましたら宜しくお願い致します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
準・究極の選択
「年収1000万円で一生カレーライス」か 「年収180万円で毎日何でも食べ放題」 あなたはどちらを選びますか?
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
StretchBlt関数について
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
3×3のラテン方陣をつくるプログ...
-
10進数からN進数に変換するプロ...
-
大量のデータを読み込んで表示...
-
C#,vb.netで業務用アプリ開発と...
-
プログラマーです。このDB設計...
-
0 == False はいいけど
-
インクリメント演算子のみを用...
-
ArduinoでMouse関数を使用して...
-
C言語 列挙型(enum型)変数について
-
VisualStudio2022でC言語プログ...
-
パイソン。If elseの挙動につい...
-
擬似コード 長さがmの配列でな...
-
UART通信の取説で,left floati...
-
あんまり考えたくないけど
-
CPUが16bitでも32bitOSでコンパ...
-
double型が正常に認識されてい...
-
c言語でイベントフラグを使った...
-
【C言語】全角文字の配列を、全...
-
C言語について。
-
C言語について。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
コンテキスト依存とは?
-
画面がチカチカする
-
VC++のTextOutの再描画の仕方
-
コントロール内の文字の背景色
-
ビットマップ(表示速度とサイズ)
-
VBでFD、USBの有効・無効...
-
Rectangleで、リソースが解放さ...
-
WinAPIでスクリーン画像を映し...
-
メモリデバイスコンテキストを...
-
クライアント領域をCBitmapに取...
-
ダブルバッファの作り方
-
VC++でopenGLを利用したい...。
-
C 多角形を半透明に塗る方法
-
Win32APIにて、アイコンの情報...
-
ExtTextOut
-
TextOutについて
-
ハードコピーをプログラムから...
-
Windowsプログラミング 画面描...
-
BeginPaintの使い方
-
デバイスコンテキストの宣言に...
おすすめ情報