• 締切済み

MFC FormViewの背景色

MFCで開発してます。 CFormViewのクライアント領域を4分割して、右上だけ背景色を他の領域とは違う色にしたいのですが、 InvalidateRect(NULL, TRUE)の後のOnEraseBkgnd()とOnDraw()で、FillSolidRect()で右上だけ塗りつぶしても色が変わりません。 何が原因と考えられるでしょうか? よろしくお願いします。

みんなの回答

回答No.2

 こんばんは。  一つのCFormViewの中の右上と言う事でしょうか。  恐らく、OnEraseBkgnd()辺りが悪さをしているのではないでしょうか。  その他、座標計算が間違っている事も考えられます。  取り敢えずは、OnEraseBkgnd()を削って見ては如何でしょう。  以下はOnDraw()のみオーバーライドして確認しています。参考になれば。 void CMyFormView::OnDraw(CDC* pDC) { // TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。 RECT rc = {0}; //クライアント領域を取る this->GetClientRect(&rc); //座標を右上に設定 rc.left = rc.right / 2; rc.bottom/= 2; //緑色で塗ってみる pDC->FillSolidRect(&rc, 0xff00); }

real_neo
質問者

お礼

ありがとうございます。 最初はOnDraw()の中で塗りつぶしてたんですけど、うまくいかないので、 OnEraseBkgnd()をオーバーライドしてみました。 4分割でうまくいかないので、2分割でやってみると、これはうまくいきました。 FillSolidRect()に渡すパラメータがおかしいのかなぁ。 何度も見直したんですけど。。。 ちなみに塗りつぶす順番は、左上→右上→左下→右下です。 もう少し調べてみます。

  • chie65535
  • ベストアンサー率43% (8526/19383)
回答No.1

>InvalidateRect(NULL, TRUE)の後のOnEraseBkgnd()とOnDraw()で、 >FillSolidRect()で右上だけ塗りつぶしても色が変わりません。 InvalidateRect()で無効化したウィンドウはOnPaint()で描画します。(言い換えれば、InvalidateRect()するとOnPaint()が発生し、OnPaint()の処理を書き換えずにデフォルトの処理のままにすると、デフォルトの背景しか描画されず、OnPaint()以外で行った描画はすべて「無かった事」になります) また、OnEraseBkgnd()は、ウィンドウをリサイズした際にしか呼ばれません。 さらに http://www.bnote.net/sdk_mfc/mfc1.shtml には 「SDIやMDIアプリケーションの描画処理は OnDraw() で行い(印刷や印刷プレビューも)。 ダイアログベースでは OnPaint()で描画処理を行うようです。 」 と書いてあります。

real_neo
質問者

お礼

ありがとうございます。 参考にさせていただきます。

関連するQ&A

  • クライアント領域を再描画させない方法

    クライアント領域で左クリックを押したままマウスを移動させた時の処理 (WM_MOUSMOVE)として、マウスの位置情報を、 InvalidateRect(hWnd, NULL, FALSE); でWM_PAINTに送り、WM_PAINTで描画処理をさせます。 右クリックでの処理として、 case WM_RBUTTONDOWN:    InvalidateRect(NULL, NULL, TRUE);    return 0; とした時、WM_PAINTでは 右クリックによるWM_PAINTでは、クライアント領域を 再描画させない様にしたいのですが、 どのようにしたら良いのでしょうか? クライアント領域に描画されたのを再描画させないことで、 消したいのです。 MS VC++ & Win98 の環境で作成しています。

  • MFCダイアログベースでのボタン背景透過方法

    VC++初心者です。 MFCダイアログベースでボタンを描画したいのですが、 そのボタンの背景を透過(透明)にしたいのです。 環境はWinXP、VSC++2010です。 OnCtrlColor()関数でSetBkMode(TRANSPARENT)や brash.CreateStockObject(NULL_BRUSH)などを実装していますが、 背景は変わりません。 ちなみに、ダイアログにはbitmap画像を貼りつけています。 ボタンはCMFCButtonを使用しているので、 CMFCButtonの変数m_mfcBtnのメンバ(プロパティ?)の m_bTransparentをTrueにしてもダメでした。 なぜ背景が透過できないのかわかりません。 ご教授宜しくお願いします。

  • ウィンドウのフレームの色変更

    <環境> Win98 VC++6.0 MFC よろしくお願いします。 ダイアログのボタン押し下げにて、新規にウィンドウを作成しています。 新規に作成したウィンドウのクライアント領域の色は、 CPaintDC dc(this); // 描画用のデバイス コンテキスト CRect cr; GetClientRect( &cr); dc.FillSolidRect( cr, RGB( 250, 250, 0)); dc.DrawText( moji,cr, DT_SINGLELINE | DT_VCENTER | DT_CENTER); にて変更することが出来ました。 クライアント領域の外側にあるフレームの色も変更したいのですが、 どのようにすれば実現可能でしょうか? ご存知の方、教えてください。お願いします。

  • MFCでウィンドウ枠をアニメーションさせたい

    こんにちは、VC++初心者です。 今MFCでデスクトップマスコットを作りたいと思っています。 MFCのSDIアプリでとりあえず作成している最中で、 BMP画像の表示はC***ViewクラスのOnDraw関数で表示させています。 問題はウィンドウ枠です。 スタイル指定をWS_POPUPにして、クライアント領域にのみ表示させていますが、 リージョンを使って、BMP画像を切り取った形のウィンドウにするのにてこずっています。 ちうか、そもそもOnDraw関数内でBMP表示とともに行っている、 SetWindowRgn関数がうまく動いてくれていない状態です(泣)。 ソースの一部をのせておきますで、どうかご判断ください。 宜しくお願いします。 CTestView::CTestView() { //コンストラクタでビットマップの読み込みとリージョンの設定 gazou.LoadBitmap( IDB_GAZOU); //CBitmapのメンバ変数 m_rgn[0].CreateEllipticRgn(0, 0, 48,48); //CRgnのメンバ変数1 m_rgn[1].CreateRectRgn(0, 0, 48,48); //CRgnのメンバ変数1 } void CTestView::OnDraw(CDC* pDC) { //画像表示及びリージョンの切り替え 中略... static int anim = 0; CDC dc; dc.CreateCompatibleDC( pDC); dc.SelectObject( gazou); pDC->BitBlt(0,0,48,48,&dc,0,0,SRCAND); //48*48ドットのBMP HRGN hrgn =(HRGN)m_rgn[anim].Detach(); SetWindowRgn( hrgn, true); dc.DeleteDC(); anim ^= 1; 中略... }

  • 背景色がちゃんとでません

    スタイルシートで設定した背景色が特定のクライアントPC(WinNt IE4.0)で反映されません。WinNt IE4.0全てでダメなのかは分からないのですが、Win95、98のIE4,0、5は大丈夫なんですけど。おかしいクライアントPCの設定の問題かなと思ってIEのインタネットオプションの設定→全般→色 と ユーザ補助 のところは間違いなさそうなんですが、他になんでもいいので何か思い当たる原因があればぜひ教えてください。よろしくお願いします.

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

  • MFC ビットマップ描画で残像が残る

    MFCです。 ワーカースレッドで取得したDIBを定期的に描画するプログラムを作っています。 ダブルバッファリングで実現しているのですが、画面リサイズを繰り返すと、再描画の後に、拡大して発生した新しいクライアント領域に古い画像が残ってしまいます。 SelectObject()で選択したコンパチDCのビットマップを選択前のものに戻してなかったのですが、これが原因なんでしょうか?

  • OnDrawが呼び出されません

    一つの画面をコントロール部と描画部にわけたものを作ろうとしています. (VC++6.0 MFC使用) ・CMyViewクラス(CFormViewクラス派生・コントロール部) ・CTest1Viewクラス(CViewクラス派生・描画部)(CTest1Docに関連付け) ・CTest1Docクラス MyViewのボタン入力でTest1Viewの画面を再描画させたいのですが,MyView内から以下のようにしてもTest1ViewのOnDrawが呼び出されません. (OnUpdateは呼び出されるようです) CTest1Doc *pDoc=(CTest1Doc *)GetDocument(); pDoc->UpdateAllViews(NULL, 1, NULL); 再描画させるにはどうすればよいのでしょうか.

  • 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問を順次解き、解き終わった後は画像を描画し、次の問題を表示したいのですが、どうしたら良いか教えてください。

  • 壁紙(CDジャケットの背景にする)を探しています(条件アリ)

    音楽CDのジャケット用にweb検索してみたのですが、風景や写真はいっぱいあるのですが、 ”無機質な画像”がなかなか見つかりません。 (音楽CDのジャケットですが、背景には音楽と無縁のものを貼りたいのです) こんなイメージで考えています。 1.12x12cmの画面を正方形で4分割する。 2.画像は基本的に茶色のレンガ塀のイメージ(全面) 3.右上および左下は濃い茶色、左上及び右下は淡い茶色  (濃い、といっても、この上に曲目を印刷するので、あまり濃いと文字が見えなくなって不都合) [補足] CDラベルを作ってしまったので、それに合わせたはジャケット背景を、と思って、 こんな細かい注文になってしまいました。 因みに、CDラベル作製ソフトには、ラベルとペアになったジャケット用の背景がありません。 CDラベルの背景は正確にはレンガではないのですが、レンガなら何とか繋がりそうだと思っています。 よろしくお願いいたします。