お世話になります、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.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.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.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で質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) エクセルのマクロについて教えてください。 2 2023/07/06 17:46
- Windows 10 MSアカウントの「個人設定をクラウドから削除します」は機能していないのでしょうか? 1 2022/11/20 17:01
- その他(Microsoft Office) Office(Windows版,Word/Excel/PowerPoint等)にログインできません 4 2022/07/24 15:18
- その他(プログラミング・Web制作) pythonでアプリが終了されたときに特定の処理を実行したい 2 2023/01/19 17:13
- Visual Basic(VBA) エクセルのマクロについて教えてください。 7 2023/07/04 09:18
- Visual Basic(VBA) Application.Dialogs(xlDialogFileDelete).Showの件 1 2023/02/22 10:02
- その他(ソフトウェア) UnityのPublishing SettingsでCreate Keyを押しても反応しない 1 2023/06/27 01:03
- Visual Basic(VBA) 動かなくなってしまった古いVBAを動くようにしたい 8 2022/09/20 13:57
- YouTube Win10 Youtubeの動画を開くと、必ず右下に設定ダイアログ?が表示されます 2 2023/03/26 11:35
- Visual Basic(VBA) VBAでファイルを開くプログラムがエラーです 2 2023/02/21 16:56
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
メモリデバイスコンテキスト&...
-
些細な質問ですが、よろしくお...
-
Active Basic 再描写処理
-
PlgBltでの透過
-
メモリデバイスコンテキストを...
-
画面がチカチカする
-
エクセルで作った新しいウイン...
-
グラフの交点の求め方(Excel)
-
「アイテムは収集されました」...
-
フォントの大きさ
-
コンボボックス内の文字サイズ変更
-
検索の画面がでなくなってしま...
-
VBAのフォント変更(エクセルか...
-
vbaから他のアプリを終了
-
3次元空間上の2つの座標から...
-
マインクラフト(pc版)で座標...
-
コントロールの書式設定で、“コ...
-
作成したウインドウのサイズを...
-
エクセルのコントロールツール...
-
アクティブウインドウのIME...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
コンテキスト依存とは?
-
画像処理 ビットマップ ダブ...
-
画面がチカチカする
-
BeginPaintの使い方
-
VC++のTextOutの再描画の仕方
-
BitBlt関数について教えてください
-
GetDC()とCreateCompatibleDC()
-
VBでFD、USBの有効・無効...
-
領域を塗りつぶしたい
-
ダブルバッファの作り方
-
ダイアログにビットマップを貼...
-
Rectangleで、リソースが解放さ...
-
GetPixelに使うHDCの作り方
-
デバイスコンテキストに関して2...
-
メモリデバイスコンテキストを...
-
画面のちらつきについて
-
WinAPIでスクリーン画像を映し...
-
VC++でBitmapとText文字を表示...
-
SetWindowRgn()関数について。
-
丸いボタンの表示でCPU100%
おすすめ情報