如何消除MFC中带有擦除背景的闪烁

时间:2019-01-17 12:03:53

标签: visual-c++ timer mfc onpaint

我正在与SDI应用程序一起使用视图文件中的计时器重绘图形并更新数据。即使我使用ON_WM_ERASEBKGND消除了闪烁,但仍然会发生。下面是我尝试实现的代码。任何人都有消除闪烁的想法吗?

这是我的MSG_MAP

        ON_WM_PAINT()
    ON_WM_ERASEBKGND()
    ON_WM_TIMER()

        BOOL CVCDSOView::OnEraseBkgnd(CDC* pDC) 
        {
         // TODO: Add your message handler code here and/or call default
         return TRUE;
         return CView::OnEraseBkgnd(pDC);   
        }

        void CVCDSOView::OnInitialUpdate() 
        {
         CView::OnInitialUpdate();
         CRect Rect;
         GetClientRect(&Rect);
         CRect m_rcDraw = Rect;

             // set timer with 200ms
             SetTimer(ID_LABEL_COMPANY,200,NULL);

             labelCompany.Create(_T("Company"), WS_CHILD | WS_VISIBLE, 
        CRect(LEFT_SIDE, TOP_SIDE, RIGHT_SIDE+50, BOTTOM_SIDE), this, ID_LABEL_COMPANY);

         textboxCompany.Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_NOHIDESEL, 
        CRect(LEFT_SIDE, TOP_SIDE+VERTICAL_OFFSET, RIGHT_SIDE+50, BOTTOM_SIDE+VERTICAL_OFFSET), this, ID_EDITTEXT_COMPANY);
        }
// CVCDSOView message handlers

        void CVCDSOView::OnPaint() 
        {
         CPaintDC dc(this); // device context for painting

         // TODO: Add your message handler code here
         CRect Rect;
         GetClientRect(&Rect);

         CDC dcMem;
         CBitmap bmpMem;
         dcMem.CreateCompatibleDC(&dc);
         bmpMem.CreateCompatibleBitmap(&dc,Rect.Width()- GRID_LEFT,Rect.Height()-35);
         dcMem.SelectObject(&bmpMem);
         dcMem.FillSolidRect(Rect, RGB(255,255,255));
         CRect m_rcDraw = Rect;
         m_rcDraw.DeflateRect(GRID_LEFT,GRID_TOP,GRID_RIGHT,GRID_BOTTOM);

             DrawGrid(&dcMem,m_rcDraw);

         dc.BitBlt(0,0,Rect.Width(),Rect.Height(),&dcMem,0,0,SRCCOPY);
         dcMem.DeleteDC();
         DeleteObject(bmpMem);
         // Do not call CView::OnPaint() for painting messages
        }

        void CVCDSOView::OnTimer(UINT nIDEvent) 
        {
         // TODO: Add your message handler code here and/or call default
         //
         if(nIDEvent==ID_LABEL_COMPANY)
         {
          CollectData();    
          Invalidate();
          CView::OnTimer(nIDEvent);
         }

        }

任何想法都将不胜感激。

2 个答案:

答案 0 :(得分:4)

您有一些子控件,当绘制其背景时可能会引起闪烁。您想通过向视图类中添加WS_CLIPCHILDREN标志来从绘制区域中排除子控件:

BOOL CVCDSOView::PreCreateWindow(CREATESTRUCT& cs)
{
    cs.style |= WS_CLIPCHILDREN;
    return CView::PreCreateWindow(cs);
}

与闪烁问题无关:

不要为主矩形减去任何东西。您应该将位图更改为

bmpMem.CreateCompatibleBitmap(&dc, Rect.Width(), Rect.Height());

您不需要dcMem.DeleteDC()DeleteObject(bmpMem) MFC会自动删除这些对象。

请注意,MFC不会自动取消选择对象。这通常无关紧要,因为Windows会进行必要的清理,如本例所示。但是为了完整起见,请添加以下内容:

CBitmap* oldbitmap = (CBitmap*)dcMem.SelectObject(&bmpMem);
...
dc.BitBlt(0,0,Rect.Width(),Rect.Height(),&dcMem,0,0,SRCCOPY);
dcMem.SelectObject(oldbitmap);

答案 1 :(得分:0)

  1. OnEraseBkgnd中,您应该返回FALSE
  2. OnPaint中的所有绘图都最好使用CMemDC类,因为直接在屏幕上绘图也很可能导致闪烁:

    CMemDC memDC(*pDC, this);
    CDC& rDC = memDC.GetDC();
    rDC.ActualDrawing`...