MFCのダブルバッファリングを用いた画面切り替えプログラムの修正方法

このQ&Aのポイント
  • MFCのダブルバッファリングを用いて画面を切り替えるプログラムを作成したが、画面がちらつく問題が発生している。修正方法を教えてください。
  • CgraphViewのOnDraw関数において、ダブルバッファリングを行っているが、画面がちらついてしまう。どう修正すればよいか教えてください。
  • 画面のちらつきを解消するためには、CgraphViewのOnDraw関数でのダブルバッファリングを改善する必要がある。具体的な修正方法を教えてください。
回答を見る
  • ベストアンサー

MFCプログラミング

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); }

  • tnk48
  • お礼率9% (7/76)

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

  • ベストアンサー
回答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)に反してます。 あちこちから何も考えずにサンプルコードをコピーしてくるのは止めて下さい。

tnk48
質問者

補足

細かく説明していただきありがとうございます ちゃんとちらつかずに画面を表示させることができました。

その他の回答 (10)

回答No.10

説明が正しいか判別不能なのでOnDrawは全て掲載して下さい。 ちなみに(1)を排除するという言い方はマズかったですね。 形を変えて何処かで行わないと行けません。 それはどの様な形でしょうか?

tnk48
質問者

補足

ソースコードをもう一度掲載します (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)は裏画面を表画面に送る処理を全ての描画が終わってからのところに持っていったのですが余計にちらついてしまいました 元から最後の処理にあるようですが? 最新のコードを掲載して下さい。

tnk48
質問者

補足

(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.8

では、(1)と(2)は何処を直すべきでしょう? 問題点は理解できたんですよね。

tnk48
質問者

補足

(1)はわかりませんが、(2)は裏画面を表画面に送る処理を全ての描画が終わってからのところに持っていったのですが余計にちらついてしまいました

回答No.7

そこ以前の問題です。No.2の内容に(1)(2)と番号を振ったので質問全部に回答して下さい。 (1)そこで塗ったらCgraphView::OnEraseBkgnd()で背景塗らずに返した意味がありませんか? 塗りつぶした瞬間、画面がチラつきませんか?? 質問:(1)が問題としているのは何処で何故でしょうか? (2) ダブルバッファリングしているのであれば、 「裏画面の方を塗りつぶして、裏画面の描画全部終わってから表画面に転送する」 というのが狙っている動作ではありませんか? 質問:(2)の代案はなぜ検討されていないのでしょうか? ># この場合クライアント領域全部の転送が必要ではありますが。 現状転送されてると思います。 >まぁ、ついでに言うなら裏画面用のデバイスコンテキストやビットマップの作成は先にやっておいて、WM_PAINTのたびに生成/破棄のコストを払うのも…>というのはありますが。 ># WM_SIZEなどいくつかのメッセージに対応してデバイスコンテキストの再作>成などが必要になったりはしますけど。 これは難易度が高いので、それ以前の事ができてからです。 ちなみにOnDrawはWM_PAINTメッセージの結果呼び出されるのでOnDrawと言い換えて良いでしょう。

tnk48
質問者

補足

(1)が問題にしているのは背景を塗らずに返しているのに 再度塗り変えているため (2)に関しては読み間違えていて、今理解できました

回答No.6

No.2の何処の部分が分からないんでしょう? そしてNo.2の回答が良く分からないにもかかわらず分からない点を何故質問しなかったのでしょうか? >ダイアログで背景を変える設定をなくしても画面がちらつくのですが >それはどうしてでしょうか No.2の自分なりの理解として、この質問になったということですか? それとも分らないことは無視したのでしょうか? どのぐらい理解しているか知りたいのでNo.2の内容を解説してみて下さい。

tnk48
質問者

補足

No.2の ># この場合クライアント領域全部の転送が必要ではありますが。 >まぁ、ついでに言うなら裏画面用のデバイスコンテキストやビットマップの作成は先にやっておいて、WM_PAINTのたびに生成/破棄のコストを払うのも…>というのはありますが。 ># WM_SIZEなどいくつかのメッセージに対応してデバイスコンテキストの再作>成などが必要になったりはしますけど。 の部分が理解できていません。ダブルバッファリングは仮想的なデバイスコンテキストに一度描画処理を行い、一通り描画が終わった段階で実際のデバイスコンテキストに描画結果を転送していることは理解しています

回答No.5

>ちらつかないようにするにはどうしたら良いでしょうかね 既にNo.2で答えが書かれています。今までの回答を全部見なおして良く考えて質問して下さい。 Wr5さんなんか同じ答えを繰り返し書いているわけですから疲れ果てていると思います。こんな事を繰り返していると回答者が誰もいなくなりますよ。

tnk48
質問者

補足

見てもよく分からないので質問させてもらっているのですが OnPaintの中に書けばいいのですか

回答No.4

>そのときとはどの時のことを言っているんでしょうか >draw_stateは最初の画面では0、Startというテキストをクリックしたとき1になるようになっています 文脈的に「ダイアログで背景を変える設定をなくしても画面がちらつくのですが」がその時としか受け取れないですよ。 つまりdraw_stateが1ならチラついて当たり前です。なぜなら、そうプログラムを組んでいるのですから。

tnk48
質問者

補足

ちらつかないようにするにはどうしたら良いでしょうかね

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.3

>ダイアログで背景を変える設定をなくしても画面がちらつくのですが そのときのdraw_stateの値はいくつですか? 1だったらpDCに対して塗りつぶししているんですからチラつくと思いますが。 # 「どこで?」なんて言わないですよね?

tnk48
質問者

補足

そのときとはどの時のことを言っているんでしょうか draw_stateは最初の画面では0、Startというテキストをクリックしたとき1になるようになっています

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.2

>上の部分はダイアログで背景を変える設定です そこで塗ったらCgraphView::OnEraseBkgnd()で背景塗らずに返した意味がありませんか? 塗りつぶした瞬間、画面がチラつきませんか?? ダブルバッファリングしているのであれば、 「裏画面の方を塗りつぶして、裏画面の描画全部終わってから表画面に転送する」 というのが狙っている動作ではありませんか? # この場合クライアント領域全部の転送が必要ではありますが。 まぁ、ついでに言うなら裏画面用のデバイスコンテキストやビットマップの作成は先にやっておいて、WM_PAINTのたびに生成/破棄のコストを払うのも…というのはありますが。 # WM_SIZEなどいくつかのメッセージに対応してデバイスコンテキストの再作成などが必要になったりはしますけど。

tnk48
質問者

補足

ダイアログで背景を変える設定をなくしても画面がちらつくのですが それはどうしてでしょうか

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

>BOOL CgraphView::OnEraseBkgnd(CDC* pDC) >{ >return TRUE; >} は正しいとして…… >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.FillSolidRect(rc, RGB(255, 255, 255)); >pDC->FillSolidRect(myRect, RGB(255, 255, 255)); >pDC->BitBlt(0, 0, rc.right, rc.bottom, &bkDC, 0, 0, SRCCOPY); のそれぞれがどういう結果をもたらすのか理解できますか?

tnk48
質問者

補足

>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)); 上の部分はダイアログで背景を変える設定です

関連するQ&A

  • ダブルバッファについて

    スタート画面にBitmapを用いたアニメーションを用いて、次の場面に移動したいのですが 実行すると画面がちかちかしてしまいます。どう直せばよいか教えてもらえると助かります プログラムはVisualStudio2008のMFCでやっています #include "stdafx.h" #include "graph.h" #include "graphDoc.h" #include "graphView.h" #ifdef _DEBUG #define new DEBUG_NEW #endif //全域変数 CDC bkDC; CBitmap bkBMP; #define ID_REDRAW 30 #define TIMER_MS_FPS 1000/30 #define ID_BITMAP 60 #define TIMER_MS_BITMAP 300 #include <math.h> int draw_state = 0; float mouse_x = -1.0, mouse_y = -1.0; // CgraphView IMPLEMENT_DYNCREATE(CgraphView, CView) BEGIN_MESSAGE_MAP(CgraphView, CView) // 標準印刷コマンド ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview) ON_COMMAND(ID_BK_WHITE, &CgraphView::OnBkWhite) ON_COMMAND(ID_BK_BLUE, &CgraphView::OnBkBlue) ON_COMMAND(ID_BK_PINK, &CgraphView::OnBkPink) ON_WM_TIMER() ON_WM_DESTROY() ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() // CgraphView コンストラクション/デストラクション CgraphView::CgraphView() : background_color(0) , draw_state(0) , Bmp_ID(0) { // TODO: 構築コードをここに追加します。 background_color = 0; int draw_state = 0; } CgraphView::~CgraphView() { } BOOL CgraphView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: この位置で CREATESTRUCT cs を修正して Window クラスまたはスタイルを // 修正してください。 return CView::PreCreateWindow(cs); } // CgraphView 描画 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); bkDC.SelectObject(&bkBMP); //描画は、裏画面bkDCにおいて行う bkDC.FillSolidRect(rc, RGB(153, 204, 255)); int x, y, sx, sy; if(draw_state == 0) { bkDC.SetTextColor(RGB(255, 255, 255)); bkDC.TextOut(480, 580, _T("Start")); sx = 128; sy = 128; y = 340; x = 200; draw_school(x, y, sx, sy);//定義は省略 x = 400; draw_health(x, y, sx, sy);//定義は省略 x = 600; draw_environment(x, y, sx, sy);//定義は省略 } else if(draw_state == 1) { CRect myRect; GetClientRect(myRect); pDC->FillSolidRect(myRect, RGB(0, 0, 0)); } //裏画面を表画面に送る //pDC->BitBlt(0, 0, rc.right, rc.bottom, &bkDC, 0, 0, SRCCOPY); //裏画面を消去 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); //タイマーをスタート 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 > 420 && mouse_y > 500) { draw_state = 1; } } CView::OnLButtonDown(nFlags, point); } //以下は関数の定義なので省略

  • if文の判定について

    <環境> WIN98 VC++6.0 MFC  ダイアログベースにて 以下コードにて、タイマーによる変数nの変化に伴い絵1と絵2が切り替わっています。 int n; void CxxxDlg::OnPaint() { 略 m_p9[0].LoadBitmap(IDB_BITMAP1); m_p9[1].LoadBitmap(IDB_BITMAP2); tempDC9.SelectObject(&m_p9[n]); 略 } void CxxxDlg::OnTimer(UINT nIDEvent) { n=n+1; if(n>=2){ n=0; } Invalidate();   CDialog::OnTimer(nIDEvent); } ところがコードの一部を以下のように変更すると、 if文で正しく判定できなくなります。 どうしてなのでしょうか? if (n=0){ m_p9[0].LoadBitmap(IDB_BITMAP1); } m_p9[1].LoadBitmap(IDB_BITMAP2);

  • 画像の印刷について

    環境はWIN98 VC++6.0 MFCです。 初めて印刷に挑戦します。 TextOut()で書いた文字は印刷プレビューでちゃんと表示されましたが、以下のようにして取りこんだ画像を印刷プレビューで見ても何も表示されません。 どうしたら印刷できるようになりますか? void CXxxView::OnDraw(CDC* pDC) { CXxxDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: この場所にネイティブ データ用の描画コードを追加します。 CDC myDC; CBitmap myBMP; myBMP.LoadBitmap(IDB_BITMAP3); myDC.CreateCompatibleDC(pDC); CBitmap* oldBMP=myDC.SelectObject(&myBMP); pDC->BitBlt(10,10,60,100,&myDC,0,0,SRCCOPY); myDC.SelectObject(oldBMP); }

  • ローカル関数についてお願いします

    VC++プログラムです ボタン1,2は正常に動いたので割愛させていただきます この文をビルドしたらエラーがでました void CparaparaDlg::OnBnClickedButton3(){ { CPaintDC dc (this); CRect sikaku; GetClientRect (sikaku); int n; CBitmap gazou[2]; int CparaparaDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) { gazou[0].LoadBitmap(IDB_BITMAP1); gazou[1].LoadBitmap(IDB_BITMAP2); n = 1; SetTimer(1, 200, NULL); return 0; } void CparaparaDlg::OnTimer(UINT nIDEvent) { n = n + 1; if(n >= 3){ n = 1; } Invalidate(); if(n == 1){ OnBnClickedButton1(); } else if (n == 2){ OnBnClickedButton2(); } } } error C2601: 'CWnd::OnCreate' : ローカル関数の定義が正しくありません。 c:\Documents and Settings\mizuno\My Documents\Visual Studio error C2601: 'CWnd::OnTimer' : ローカル関数の定義が正しくありません。 というエラーが出ました・・・ どこをどう手直しすればよいのか教えていただける方、お願いします 関数についても教えていただけると幸いです

  • VC++のOnDraw()関数で、ボールを動かす

    下記のように、VC++のOnDraw()関数において、ウィンドウ上でボールを上下に 動かせたいのですが、動きません。VC++のバージョンは9.0です。(Visual Studio 2008) どういうふうに書けば動きますか? ------------------------------------------------------------------------- void CControllGameView::OnDraw(CDC* pDC) { Bitmap2.LoadBitmap(IDB_BITMAP2); // ボール pOldBitmap = MemDC.SelectObject(&Bitmap2); // 転送前のビットマップ領域を退避 GetClientRect(&rect); // ウィンドウのサイズをrectに記憶 pDC->BitBlt((rect.right-42)/2, rect.top+50, 42, 41, &MemDC, 0, 0, SRCCOPY); // ビット単位でビットマップ画像を転送 int z = rect.bottom + 50; // ボールのy座標の初期値 while(z < rect.top){ pDC->MoveTo((rect.right-42)/2, z+=1); } MemDC.SelectObject(pOldBitmap); // 元に戻す ReleaseDC(pDC); }

  • MFCのタイマーのつかい方を教えてください

    タイマーのつかい方が今ひとつ分かりません。 MFCでタイピングのゲームを作成しているのですが、 25問を解き、正解だった場合もしくは制限時間を超えてしまった場合、次の問題を表示したいと思っております。 下記がプログラム内容です。 void CProgramView::Loop1(CDC* pDC) { CProgramDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if((m_nRight<26)|(0<m_nRight)) { m_nRight=0; //正解数 m_nQuestion=1; //問題数 } Haikei(pDC); //問題表示領域の枠表示 Tokei(pDC); //時計の秒針が表示される枠表示 Moji(pDC); //問題文表示 OnChar(ch, count,flags); //入力 if(m_fTimer==FALSE) { SetTimer(123,250,NULL); //タイマーをセット if(m_nQuestion<26) //25問以上問題を解いていないケース { m_fTimer = FALSE; } else m_fTimer = TRUE; //全問解いた場合 } Loop0(pDC); //秒針の描画クラス if(m_nx==715) //タイムアウトだった場合 { KillTimer(123); NGPaper(pDC); m_nQuestion++; //問題をカウント m_sAnser.Empty(); //回答文字列をクリア pDoc->GetNextSet(); //次の問題を取得する InvalidateRect(NULL); } if(m_nQuestion<m_nCount) //正解だった場合 { KillTimer(123); //タイマーを切る Tokei(pDC); //秒針の画像を消すために時計の画面を再描画 Right(pDC); //正解した場合の画像を描画 Haikei(pDC); //問題文・回答を消すために問題表示領域の枠を再描画 PartsPaper1(pDC); //正解した場合の壁紙を表示 m_nQuestion++; //問題数をカウント m_sAnser.Empty(); //回答文字列をクリアする pDoc->GetNextSet(); //次の問題を取得する InvalidateRect(NULL); } } そして、この動作を25問、解くまでループさせる関数として以下の関数を作成しました。 void CProgramView::Loop2(CDC* pDC) { if(m_fTimer==FALSE) { Loop1(pDC); } } //タイマーの内容 void CProgramView::OnTimer(UINT nIDEvent) { // TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォルトの処理を呼び出してください if(nIDEvent == 123) { InvalidateRect(NULL); } CView::OnTimer(nIDEvent); } しかし、実際にこのプログラムを実行すると入力し、正解する間は次の問題が表示されるのですが、タイマーが切れません。 そして、制限時間になるとそこまで解いていた問題から凄い勢いで描画が始まり、止まりません。 おそらくタイマーが正常に使えていないという可能性が考えられるのですが・・・。 希望としては、25問を順次解き、解き終わった後は画像を描画し、次の問題を表示したいのですが、どうしたら良いか教えてください。

  • Visual Studioのタイマ処理を使って描画を行うプログラムを

    Visual Studioのタイマ処理を使って描画を行うプログラムを 作成したのですがうまくいきません. プログラムの開発環境はWindows XP SP2でVC++6.0 外部に接続したセンサからのデータを50Hzで サンプリングして そのデータを元に描画を行う予定なのですが計測時間が100秒を超えると 異常終了してしまいます. 原因がよく分かりません. どうしたらよいのでしょうか? void CMyDlg::OnSamplingStart() { i=0; // サンプリング用タイマ開始 //なぜか12にするとちょうど50Hzでサンプリングする SetTimer(1,12,NULL); // 0.02秒毎タイマ割り込み,50Hz } void CMyDlg::OnTimer(UINT nIDEvent) { /* ここで,センサからのデータをサンプリングし,いろいろな計算をする. */ CDC* pDC=m_pict.GetDC(); CRect myRECT; m_pict.GetClientRect(myRECT); pDC->FillSolidRect(myRECT, RGB(255,255,255)); CPen BlueBoldPen,*OldBlueBoldPen; BlueBoldPen.CreatePen(PS_SOLID,5,RGB(0,0,255)); OldBlueBoldPen=pDC->SelectObject(&BlueBoldPen); pDC->MoveTo((int)(X0/10),(int)(Y0/10)); pDC->LineTo((int)(L3_x[i]/10),(int)(L3_y[i]/10)); pDC->LineTo((int)(C7_x[i]/10),(int)(C7_y[i]/10)); // ペンを元に戻す pDC->SelectObject(OldBlueBoldPen); BlueBoldPen.DeleteObject(); m_time=(double)i/50; UpdateData(FALSE); i=i+1; CDialog::OnTimer(nIDEvent); } 計測終了はボタンを押して終了します. どうが具体的な解決策を教えてください.

  • Basicのプログラミングについて… (game)

    箱の上から自然に落ちるようにするにはどうすればよいのでしょうか? SET bitmap SIZE 500,500 SET WINDOW 0,10000,10000,0 LET x=5000 LET y=5000 LET jsw=0 DO UNTIL getkeystate(13)<0 PLOT LINES:0,5000+110;10000,5000+110 PLOT LINES:6000,4000;7000,4000 PLOT LINES:6000,4000;6000,5000+110 PLOT LINES:7000,4000;7000,5000+110 SET AREA COLOR "white" DRAW disk WITH SCALE(100)*SHIFT(x,y) IF getkeystate(37)<0 THEN LET x=x-50 IF getkeystate(39)<0 THEN LET x=x+50 IF x<0 THEN LET x=0 IF x>10000 THEN LET x=10000 IF getkeystate(38)<0 AND jsw=0 THEN LET jsw=1 LET i=-SQR(2500) END IF IF jsw=1 THEN LET y=i^2+2500 LET i=i+1 IF i>SQR(2500) THEN LET jsw=0 end if if i>0 then if 6000<x and x<7000 then if 4000-140<=y THEN LET jsw=0 end if end if end if if i>0 then if 6000>x then LET y=i^2+2400 IF i>SQR(2500) THEN LET jsw=0 end if end if SET AREA COLOR "black" DRAW disk WITH SCALE(100)*SHIFT(x,y) WAIT DELAY 0.01 LOOP END

  • ダイアログにビットマップを貼り付けた時にフリーズしてしまう

    お世話になります、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); } としています。 初めにこのダイアログを表示時は、ちゃんとビットマップが表示されるのですが、他のダイアログでこのダイアログを表示させた時にビットマップが上半分まで表示されて、動作がフリーズしてしまう現状です。 なにかよい打開策がありましたら、教えていただけたらと思っています。宜しくお願いいたします。

  • ビューにビットマップファイルを描画する方法

    MFCのプログラムで(マルチウィンドウ)ビュー上に指定したビットマップファイルをオープンして描画したいと思ってます。 Bitmapリソースを指定して描画する方法はわかりましたが、ビットマップファイル名を指定して、そのファイルをオープンしてビュー上に描画する方法はどのようすればよいのでしょうか? 今は以下のようにOnDraw()内で以下のように実装しています。 -------------------------------------------------------- CBitmap kaitaGazou; kaitaGazou.LoadBitmap(IDB_BITMAP1); CDC MemDC; MemDC.CreateCompatibleDC(pDC); CBitmap *pTmpBitmap; pTmpBitmap = MemDC.GetCurrentBitmap(); MemDC.SelectObject(&kaitaGazou); pDC->BitBlt(0, 0, 100, 100, &MemDC, 10, 10, SRCCOPY); MemDC.SelectObject(pTmpBitmap); kaitaGazou.DeleteObject(); --------------------------------------------------------

専門家に質問してみよう