MFCがウィンドウの点滅を避ける方法(OnEraseBkgnd).

5873 ワード

グラフィック画像処理のプログラミング過程において,二重バッファリングは基本的な技術である.フォームがWMに応答している場合PAINTメッセージの場合、複雑なグラフィック処理を行うと、フォームは再描画時にオーバークロックのリフレッシュによって点滅します.この問題を解決する有効な方法はデュアルバッファ技術である.
フォームがリフレッシュされると、元の画像を消去するプロセスOnEraseBkgndが常に必要になるため、背景色を利用してフォームの描画領域を塗りつぶし、新しい描画コードを呼び出して再描画することで、消去すると画像の色のギャップが発生します.WM_PAINTの応答が頻繁な場合、このギャップもますます顕著になります.そこで私たちは点滅現象を見た.
背景色の塗りつぶしを避けるのが最も直接的な方法だと自然に考えられます.でもそうすると、フォームがめちゃくちゃになります.画像を描くたびに元の画像をクリアしないため、画像が残り、フォームが再描画されると画面がめちゃくちゃになることが多い.だから単純に背景の再描画を禁止するだけでは足りない.再描画を行う必要があるが,速度が速いことが要求され,BitBlt関数の使用を考えた.グラフィックブロックのコピーをサポートし、高速です.メモリに図を作成してから、この関数を使用して作成した図をフロントにコピーし、バックグラウンドのリフレッシュを禁止することで、点滅を排除できます.以上がダブルバッファ描画の基本的な考え方である.
まず普通の図面の方法でプログラミングを行います.つまり、ビュークラスのOnDraw関数に描画コードを追加します.ここでは、いくつかの同心円を描きます.コードは次のとおりです.
[cpp]
view plain
copy
print
?
CBCDoc* pDoc = GetDocument();  
  • ASSERT_VALID(pDoc);  
  • CPoint ptCenter;  
  • CRect rect,ellipseRect;  
  • GetClientRect(&rect);  
  • ptCenter = rect.CenterPoint();  
  • for(int i=20;i>0;i--)  
  • {  
  •   ellipseRect.SetRect(ptCenter,ptCenter);  
  •   ellipseRect.InflateRect(i*10,i*10);  
  •   pDC->Ellipse(ellipseRect);  
  • }  
  • CBCDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    CPoint ptCenter;
    CRect rect,ellipseRect;
    GetClientRect(&rect);
    ptCenter = rect.CenterPoint();
    for(int i=20;i>0;i--)
    {
      ellipseRect.SetRect(ptCenter,ptCenter);
      ellipseRect.InflateRect(i*10,i*10);
      pDC->Ellipse(ellipseRect);
    }
    

    実行プログラムをコンパイルし、ウィンドウのサイズを変更しようとすると、点滅現象が検出されます.デュアルバッファ法では,まずマスクバックグラウンドのリフレッシュを行う.バックグラウンドリフレッシュは実はWM_に応答していますERASEBKGNDニュース.このメッセージに対する応答をクラスに追加すると、デフォルトのコードは次のように表示されます.
    [cpp]
    view plain
    copy
    print
    ?
    BOOL CMYView::OnEraseBkgnd(CDC* pDC)   
  • {  
  •      return CView::OnEraseBkgnd(pDC);  
  • }  
  • BOOL CMYView::OnEraseBkgnd(CDC* pDC) 
    {
         return CView::OnEraseBkgnd(pDC);
    }

    親クラスを呼び出すOnEraseBkgnd関数であり、この呼び出しをマスクするには、直接return TRUEを必要とします.できます.次に、メモリバッファ作図の手順を示す.
    [cpp]
    view plain
    copy
    print
    ?
    CBitmap bit;  
  • bit.LoadBitmapA(IDB_BITMAP1);  
  • BITMAP bm;  
  • bit.GetBitmap(&bm);  
  • CDC memDc;  
  • memDc.CreateCompatibleDC(pDC);  
  • CBitmap* pOldBitmap = memDc.SelectObject(&bit);  
  • CRect rect;  
  • GetClientRect(&rect);  
  • pDC->SetStretchBltMode(COLORONCOLOR);//このモードを設定しないと画像がひどく歪みます  
  • pDC->StretchBlt(0,0,rect.Width() ,rect.Height(),  
  • &memDc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);  
  • memDc.SelectObject(pOldBitmap);  
  • memDc.DeleteDC();                                      //DCの削除  
  • bm.DeleteObject();                                       //ビットマップの削除  
    CBitmap bit;
    bit.LoadBitmapA(IDB_BITMAP1);
    BITMAP bm;
    bit.GetBitmap(&bm);
    CDC memDc;
    memDc.CreateCompatibleDC(pDC);
    CBitmap* pOldBitmap = memDc.SelectObject(&bit);
    CRect rect;
    GetClientRect(&rect);
    pDC->SetStretchBltMode(COLORONCOLOR);//                  
    pDC->StretchBlt(0,0,rect.Width() ,rect.Height(),
    &memDc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
    memDc.SelectObject(pOldBitmap);
    memDc.DeleteDC();                                      //  DC
    bm.DeleteObject();                                       //    
    

    複雑なグラフィック操作がバックグラウンドに移行するため,我々が見たのは速度の速い複製操作であり,自然に点滅現象も解消される.Q:OnEraseBkgnd関数でTRUEまたはFALSEを返す違いは何ですか?A:  WM_ERASEBKGNDReturn ValuesAn application should return nonzero if it erases the background; otherwise,it should return zero.A:trueは処理済みバックグラウンドリフレッシュを表し、falseはOnPaintで処理する必要があることを示していますQ:OnEraseBkgndでダイアログボックスを描くバックグラウンドピクチャとOnPaintでダイアログボックスを描くバックグラウンドピクチャの違いは何ですか.またOnEraseBkgndとCtlColorの違いは何ですか.A:  OnEraseBkgndは、ウィンドウのサイズが変更された場合などに発生し、ウィンドウの背景を描画します.一方、OnCtlColorは、ウィンドウのコントロールを描画する必要がある場合に発生し、ウィンドウのコントロールを描画します. A:OnEraseBkgnd:ウィンドウの背景を再描画する必要がある場合に呼び出す.OnPaint:OnEraseBkgndが呼び出されたので、この応答関数内でバックグラウンドを操作すると、OnEraseBkgndで行った操作が上書きされます.OnCtlColor:ウィンドウが(最初に)描画されるときに応答する場合、サブウィンドウはWM_をオフにすることができます.CTLCOLORは親ウィンドウにHRUSHを要求した.