MFCのダブルバッファリングを用いて画面を切り替えるプログラムを作ったのですが
画面がちらついてしまいます、どう修正すればよいか教えてください
// CgraphView 描画
void CgraphView::OnDraw(CDC* pDC)
{
CgraphDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: この場所にネイティブ データ用の描画コードを追加します。
CRect myRect;
GetClientRect(myRect);
if(background_color == 0)
pDC->FillSolidRect(myRect, RGB(255, 255, 255));
else if(background_color == 1)
pDC->FillSolidRect(myRect, RGB(153, 204, 255));
else
pDC->FillSolidRect(myRect, RGB(255, 153, 204));
//ダブルバッファに関するコード
CRect rc;
GetClientRect(&rc);
bkDC.CreateCompatibleDC(pDC);
bkBMP.CreateCompatibleBitmap(pDC, rc.right, rc.bottom);
CBitmap Bitmap, *pOldBitmap;
pOldBitmap = bkDC.SelectObject(&bkBMP);
//これから、すべての描画は、裏画面bkDCにおいて行う
bkDC.FillSolidRect(rc, RGB(255, 255, 255));
int x, y, sx, sy;
if(draw_state == 0)
{
bkDC.SetTextColor(RGB(0, 0, 0));
bkDC.TextOut(400, 500, _T("Start"));
sx = 128;//表示するビットマップの横の大きさ
sy = 128;//表示するビットマップの縦の大きさ
y = 300;//表示するビットマップの左上の頂点のy座標
x = 50;
draw_school(x, y, sx, sy);
x = 200;
draw_health(x, y, sx, sy);
x = 350;
draw_environment(x, y, sx, sy);
}
else if(draw_state == 1)
{
CRect myRect;
GetClientRect(myRect);
pDC->FillSolidRect(myRect, RGB(255, 255, 255));
}
//裏画面bkDCにおいて、すべての描画を行った後
//裏画面を表画面に送る
pDC->BitBlt(0, 0, rc.right, rc.bottom, &bkDC, 0, 0, SRCCOPY);
bkDC.SelectObject(pOldBitmap);
//裏画面を消去
bkBMP.DeleteObject();
bkDC.DeleteDC();
void CgraphView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。
bitmap[0].LoadBitmap(IDB_BITMAP1);
bitmap[1].LoadBitmap(IDB_BITMAP2);
bitmap[2].LoadBitmap(IDB_BITMAP3);
bitmap[3].LoadBitmap(IDB_BITMAP4);
bitmap[4].LoadBitmap(IDB_BITMAP5);
bitmap[5].LoadBitmap(IDB_BITMAP6);
Bmp_ID = 0;
//タイマーをスタート
SetTimer(ID_BITMAP, TIMER_MS_BITMAP, NULL);
//画面再描画のタイマーをスタートする
SetTimer(ID_REDRAW, TIMER_MS_FPS, NULL);
Bmp_ID = 0;
}
void CgraphView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。
if(nIDEvent == ID_BITMAP)
Bmp_ID = (Bmp_ID+1) % 2;
if(nIDEvent == ID_REDRAW)
InvalidateRect(NULL, FALSE);
CView::OnTimer(nIDEvent);
}
void CgraphView::OnDestroy()
{
CView::OnDestroy();
// TODO: ここにメッセージ ハンドラ コードを追加します。
KillTimer(ID_BITMAP);
KillTimer(ID_REDRAW);
}
void CgraphView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。
mouse_x = point.x;
mouse_y = point.y;
if(draw_state == 0)
{
if(mouse_x > 400 && mouse_y > 500)
{
draw_state = 1;
}
}
CView::OnLButtonDown(nFlags, point);
}
BOOL CgraphView::OnEraseBkgnd(CDC* pDC)
{
// TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。
return TRUE;
//return CView::OnEraseBkgnd(pDC);
}
No.11ベストアンサー
- 回答日時:
>ソースコードをもう一度掲載します
>(1)をどの場所で行うかは今の所わからない現状です。
まったくNo.2内容を読み取れてませんね。
(2)に答えが書いてあります。
(a)裏画面の方を塗りつぶして
(b)裏画面の描画全部終わってから
(c)表画面に転送する
この(a)(b)(c)をちゃんと実践してますか?
それぞれ実勢しているソースコードを書きだして下さい。
あと少なくとも(b)に反している部分があります。
else if( draw_state == 1 ) {
CRect myRect;
GetClientRect( myRect );
pDC->FillSolidRect( myRect, RGB( 255, 255, 255 ) );
}
この処理が必要な理由も私にはわかりませんが、pDCで無いことは確かです。
それとグラフを表画面に直接書くとチラつくと思います。
なぜ裏画面に書かないのでしょうか?
これも(b)に反してます。
あちこちから何も考えずにサンプルコードをコピーしてくるのは止めて下さい。
No.10
- 回答日時:
説明が正しいか判別不能なのでOnDrawは全て掲載して下さい。
ちなみに(1)を排除するという言い方はマズかったですね。
形を変えて何処かで行わないと行けません。
それはどの様な形でしょうか?
この回答への補足
ソースコードをもう一度掲載します
(1)をどの場所で行うかは今の所わからない現状です。
void CgraphView::OnDraw(CDC* pDC)
{
CgraphDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: この場所にネイティブ データ用の描画コードを追加します。
//ダブルバッファに関するコード
CRect rc;
GetClientRect(&rc);
bkDC.CreateCompatibleDC(pDC);
bkBMP.CreateCompatibleBitmap(pDC, rc.right, rc.bottom);
CBitmap Bitmap, *pOldBitmap;
pOldBitmap = bkDC.SelectObject(&bkBMP);
//これから、すべての描画は、裏画面bkDCにおいて行う
bkDC.FillSolidRect(rc, RGB(255, 255, 255));
int x, y, sx, sy;
if(draw_state == 0)
{
bkDC.SetTextColor(RGB(0, 0, 0));
bkDC.TextOut(400, 500, _T("Start"));
sx = 128;//表示するビットマップの横の大きさ
sy = 128;//表示するビットマップの縦の大きさ
y = 300;//表示するビットマップの左上の頂点のy座標
x = 50;
draw_school(x, y, sx, sy);
x = 200;
draw_health(x, y, sx, sy);
x = 350;
draw_environment(x, y, sx, sy);
}
else if(draw_state == 1)
{
CRect myRect;
GetClientRect(myRect);
pDC->FillSolidRect(myRect, RGB(255, 255, 255));
}
//裏画面bkDCにおいて、すべての描画を行った後
//裏画面を表画面に送る
pDC->BitBlt(0, 0, rc.right, rc.bottom, &bkDC, 0, 0, SRCCOPY);
bkDC.SelectObject(pOldBitmap);
//裏画面を消去
bkBMP.DeleteObject();
bkDC.DeleteDC();
int x0=50, y0=450, xsp=700, ysp=400, xp, yp ;
// float xmax, ymax;
int DataN=pDoc->DN, i;
//pDC->SetTextColor(RGB(0,0,255));
//pDC->TextOut(0,0,"Title");//グラフタイトル
CPen Pen1(PS_SOLID,1,RGB(0,0,0)); //ペンの初期化
CPen Pen2(PS_SOLID,2,RGB(0,0,0));
CPen* OldPen=pDC->SelectObject(&Pen1); //ペンの変更
if(DataN!=0){
pDC->SelectObject(Pen2);
pDC->MoveTo(x0,y0);
pDC->LineTo(x0+xsp,y0);
pDC->MoveTo(x0,y0);
pDC->LineTo(x0 ,y0-ysp);
for(i=0;i<=DataN;i++){
xp=(int)(x0+pDoc->Dx[i]/100.0*xsp);
yp=(int)(y0-pDoc->Dy[i]/100.0*ysp);
if(i==0) pDC->MoveTo(xp,yp);
else pDC->LineTo(xp,yp);
}
}
pDC->SelectObject(OldPen);
}
No.9
- 回答日時:
>(1)はわかりませんが、
直し方がわからないのは問題点が分からないからです。
(1)と(2)はセットで語られているのは分かりますか?
(1)の問題点を排除し、(2)の方法で修正するのです。
さて、何処を排除しますか?
>(2)は裏画面を表画面に送る処理を全ての描画が終わってからのところに持っていったのですが余計にちらついてしまいました
元から最後の処理にあるようですが?
最新のコードを掲載して下さい。
この回答への補足
(1)では
CRect myRect;
GetClientRect(myRect);
if(background_color == 0)
pDC->FillSolidRect(myRect, RGB(255, 255, 255));
else if(background_color == 1)
pDC->FillSolidRect(myRect, RGB(153, 204, 255));
else
pDC->FillSolidRect(myRect, RGB(255, 153, 204));
の部分を排除しました
//裏画面bkDCにおいて、すべての描画を行った後
//裏画面を表画面に送る
pDC->BitBlt(0, 0, rc.right, rc.bottom, &bkDC, 0, 0, SRCCOPY);
bkDC.SelectObject(pOldBitmap);
//裏画面を消去
bkBMP.DeleteObject();
bkDC.DeleteDC();
の後にグラフを描画するコードが書かれていて
その後ろに持っていったということです
No.7
- 回答日時:
そこ以前の問題です。
No.2の内容に(1)(2)と番号を振ったので質問全部に回答して下さい。(1)そこで塗ったらCgraphView::OnEraseBkgnd()で背景塗らずに返した意味がありませんか? 塗りつぶした瞬間、画面がチラつきませんか??
質問:(1)が問題としているのは何処で何故でしょうか?
(2)
ダブルバッファリングしているのであれば、
「裏画面の方を塗りつぶして、裏画面の描画全部終わってから表画面に転送する」
というのが狙っている動作ではありませんか?
質問:(2)の代案はなぜ検討されていないのでしょうか?
># この場合クライアント領域全部の転送が必要ではありますが。
現状転送されてると思います。
>まぁ、ついでに言うなら裏画面用のデバイスコンテキストやビットマップの作成は先にやっておいて、WM_PAINTのたびに生成/破棄のコストを払うのも…>というのはありますが。
># WM_SIZEなどいくつかのメッセージに対応してデバイスコンテキストの再作>成などが必要になったりはしますけど。
これは難易度が高いので、それ以前の事ができてからです。
ちなみにOnDrawはWM_PAINTメッセージの結果呼び出されるのでOnDrawと言い換えて良いでしょう。
この回答への補足
(1)が問題にしているのは背景を塗らずに返しているのに
再度塗り変えているため
(2)に関しては読み間違えていて、今理解できました
No.6
- 回答日時:
No.2の何処の部分が分からないんでしょう?
そしてNo.2の回答が良く分からないにもかかわらず分からない点を何故質問しなかったのでしょうか?
>ダイアログで背景を変える設定をなくしても画面がちらつくのですが
>それはどうしてでしょうか
No.2の自分なりの理解として、この質問になったということですか?
それとも分らないことは無視したのでしょうか?
どのぐらい理解しているか知りたいのでNo.2の内容を解説してみて下さい。
この回答への補足
No.2の
># この場合クライアント領域全部の転送が必要ではありますが。
>まぁ、ついでに言うなら裏画面用のデバイスコンテキストやビットマップの作成は先にやっておいて、WM_PAINTのたびに生成/破棄のコストを払うのも…>というのはありますが。
># WM_SIZEなどいくつかのメッセージに対応してデバイスコンテキストの再作>成などが必要になったりはしますけど。
の部分が理解できていません。ダブルバッファリングは仮想的なデバイスコンテキストに一度描画処理を行い、一通り描画が終わった段階で実際のデバイスコンテキストに描画結果を転送していることは理解しています
No.2
- 回答日時:
>上の部分はダイアログで背景を変える設定です
そこで塗ったらCgraphView::OnEraseBkgnd()で背景塗らずに返した意味がありませんか?
塗りつぶした瞬間、画面がチラつきませんか??
ダブルバッファリングしているのであれば、
「裏画面の方を塗りつぶして、裏画面の描画全部終わってから表画面に転送する」
というのが狙っている動作ではありませんか?
# この場合クライアント領域全部の転送が必要ではありますが。
まぁ、ついでに言うなら裏画面用のデバイスコンテキストやビットマップの作成は先にやっておいて、WM_PAINTのたびに生成/破棄のコストを払うのも…というのはありますが。
# WM_SIZEなどいくつかのメッセージに対応してデバイスコンテキストの再作成などが必要になったりはしますけど。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- JavaScript 入力フォームの javascript で メールアドレスの正規チェックをを行い、ボタンをクリックして 2 2022/04/27 16:06
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- FX・外国為替取引 mql4のコンパイルエラー箇所の修正お願いします。 1 2023/03/15 16:14
- JavaScript フォームが空欄の時にフォームの外をクリックすると、エラーが出るコードを調べています。 1 2023/06/25 11:51
- Visual Basic(VBA) VBAの繰り返し処理について教えてください。 3 2022/08/02 13:21
- HTML・CSS ボタンをクリックした時に、入力フォームのすぐ下部に、「入力欄が空白です」というテキストメッセージが表 1 2022/04/27 16:25
- JavaScript ①入力フォーム→②確認表示画面→③送信完了画面のコードを書いているのです、 入力フォームから受け取っ 2 2022/05/10 16:45
- JavaScript 画像の表示位置 3 2022/12/23 08:25
- JavaScript sessionStorageを調べています。 1 2023/06/20 12:41
- Java java 引数 戻り値のあるメソッド 3 2023/02/12 06:23
このQ&Aを見た人はこんなQ&Aも見ています
-
とっておきの「夜食」教えて下さい
真夜中に小腹がすいたときにこっそり作るメニュー、こっそり家を抜け出して食べに行くお店… 人には言えない、けど自慢したい、そんなあなたの「とっておきの夜食」を教えて下さい。
-
人生最悪の忘れ物
今までの人生での「最悪の忘れ物」を教えてください。 私の「最悪の忘れ物」は「財布」です。
-
遅刻の「言い訳」選手権
よく遅刻してしまうんです…… 「電車が遅延してしまい遅れました」 「歯医者さんが長引いて、、、」 「病院が混んでいて」 などなどみなさんがこれまで使ってきた遅刻の言い訳がたくさんあるのではないでしょうか?
-
この人頭いいなと思ったエピソード
一緒にいたときに「この人頭いいな」と思ったエピソードを教えてください
-
【大喜利】【投稿~12/6】 西暦2100年、小学生のなりたい職業ランキング
【お題】 ・西暦2100年の「小学生のなりたい職業ランキング」で1位になった職業は何か教えてください
-
画面を強制的に再描画させる方法
C言語・C++・C#
-
MFCでOnPaintのタイミング
C言語・C++・C#
-
UpdateData( FALSE); による文字列データの表示更新(VC++6.0)
C言語・C++・C#
-
-
4
リストビューのスクロールバーを非表示にしたい
C言語・C++・C#
-
5
MFCで画像を表示させているのですが、透過表示する方法がわかりません。
C言語・C++・C#
-
6
MFCのコントロールにUTF-8の文字を表示したい
C言語・C++・C#
-
7
MFCのCListCtrlでスクロールを検出
C言語・C++・C#
-
8
CString から LPCTSTRの型に変換
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・「みんな教えて! 選手権!!」開催のお知らせ
- ・漫画をレンタルでお得に読める!
- ・【選手権お題その1】これってもしかして自分だけかもしれないな…と思うあるあるを教えてください
- ・【穴埋めお題】恐竜の新説
- ・我がまちの「給食」自慢を聞かせてっ!
- ・冬の健康法を教えて!
- ・一番好きな「クリスマスソング」は?
- ・集合写真、どこに映る?
- ・自分の通っていた小学校のあるある
- ・フォントについて教えてください!
- ・【大喜利】【投稿~12/6】 西暦2100年、小学生のなりたい職業ランキング
- ・これが怖いの自分だけ?というものありますか?
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・遅刻の「言い訳」選手権
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・10代と話して驚いたこと
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
三菱GOTの画面切り替えについて
-
C言語で今まで表示していた画面...
-
遷移元を判定したい!
-
アドレスバーに引数を表示させ...
-
モーダル画面の親をクリック時...
-
Strutsのデータ受け渡しについて
-
Javascriptのhistory.back()が...
-
前画面の値を引き継ぎたい。
-
ポップアップでウィンドウを表...
-
Java-jspの画面入力値保持について
-
strutsで、JSP→アクションクラ...
-
テキストボックスから勝手に画...
-
ASP.NET 画面遷移前の状態を保...
-
Struts1.3.10でAjax連携
-
非アクティブな画面を操作する...
-
親ウィンドウの画面遷移
-
FormのsubmitでFormの内容がnull
-
スマホ向けに「お気に入り登録...
-
Strutsの情報保持の仕方について
-
このサービスの仕組みが知りた...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
三菱GOTの画面切り替えについて
-
C言語で今まで表示していた画面...
-
Java-jspの画面入力値保持について
-
Javaプログラミングの質問にな...
-
画面を隠す・消す方法を教えて...
-
遷移元を判定したい!
-
ASP.NET 画面遷移前の状態を保...
-
ServletからServletへの値渡し
-
C# ログイン画面からメイン画面...
-
javaのstrutsを使った画面遷移...
-
セッション切れでのリクエスト...
-
Javascriptのhistory.back()が...
-
ruby on railsでの画面間 パラ...
-
"+"文字が" (スペース)"に文字...
-
サブミット後、自動的に画面を...
-
非アクティブな画面を操作する...
-
FormのsubmitでFormの内容がnull
-
location.hrefでページ切替時の...
-
ブラウザアドレスバーからのURL...
-
画像の縦横比固定の計算方法。
おすすめ情報