CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Apr 2005
    Posts
    73

    Screen flicker problem? InvalidateRect()

    I have some problem with screen flicker, I copy one image from hard disk to view, and draw one circle on the screen, when I move the circle using direction arrow of keyboard, there is flicker problem because redrawing the whole screen. So I called the function InvalidateRect() to redraw specific rectangular, but it seems no action. the following is my code, can you please give some suggestion?

    Thanks in advance!

    void MyView::OnDraw(CDC* pDC)
    {
    CString szFilename("c:\\image.bmp");
    HBITMAP hBmp = (HBITMAP)::LoadImage(NULL,szFilename,
    IMAGE_BITMAP,0,0,
    LR_LOADFROMFILE|LR_CREATEDIBSECTION);

    CBitmap bmp;
    bmp.Attach(hBmp);

    CClientDC dc(this);
    CDC bmDC;
    bmDC.CreateCompatibleDC(&dc);
    CBitmap *pOldbmp = bmDC.SelectObject(&bmp);

    BITMAP bi;
    bmp.GetBitmap(&bi);

    dc.BitBlt(0,0,bi.bmWidth,bi.bmHeight,&bmDC,0,0,SRCCOPY);
    dc.SelectObject(pOldbmp);

    DrawCircle(pDC);
    }

    void MyView:rawCircle(CDC *pDC)
    {
    CPen *penold, pennew;
    pennew.CreatePen(PS_DOT,1,RGB(255,255,255));
    penold=pDC->SelectObject(&pennew);

    CBrush *pBrhold, Brhnew;
    Brhnew.CreateStockObject(NULL_BRUSH);
    pBrhold=pDC->SelectObject(&Brhnew);

    m_tracker.AdjustRect(false,&m_tracker.m_rect);
    m_tracker.m_rect.bottom=m_tracker.m_rect.top+m_tracker.m_rect.right -m_tracker.m_rect.left;
    m_tracker.AdjustRect(true,&m_tracker.m_rect);

    pDC->Ellipse(m_tracker.m_rect);

    pDC->SelectObject(penold);
    pDC->SelectObject(pBrhold);
    pennew.DeleteObject();
    }

    void MyDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
    {
    // TODO: Add your message handler code here and/or call default

    CRect rcClient;
    p_view->GetClientRect(&rcClient);
    rcClient.top=rcClient.top/2;

    if(nChar==VK_LEFT)
    {
    p_view->m_tracker.m_rect.left-=1;
    p_view->m_tracker.m_rect.right-=1;

    InvalidateRect(rcClient);
    //Invalidate();
    }
    }

  2. #2
    Join Date
    Sep 2002
    Location
    14° 39'19.65"N / 121° 1'44.34"E
    Posts
    9,815

    Re: Screen flicker problem? InvalidateRect()

    Quote Originally Posted by berrywong
    I have some problem with screen flicker, I copy one image from hard disk to view, and draw one circle on the screen, when I move the circle using direction arrow of keyboard, there is flicker problem because redrawing the whole screen. So I called the function InvalidateRect() to redraw specific rectangular, but it seems no action. the following is my code, can you please give some suggestion?
    A few things:
    • Calling InvalidateRect() instead of Invalidate() makes no difference if you pass the entire client rect - actually, that's exactly what Invalidate does (calling InvalidateRect with the entire client rect). It only makes sense if you call it for a smaller rectangle (e.g. your circle's bounds, but note that you would have to call that twice: Before the move, and after the move).
    • Why are you creating a CClientDC in OnDraw()? You should use the readily prepared CPaintDC you are getting as the pDC parameter.
    • To completely avoid flickering, I would suggest to handle WM_ERASEBKGND, and return TRUE. You could also pass FALSE as the second parameter to InvalidateRect(), preventing the background from being drawn.

  3. #3
    Join Date
    Nov 1999
    Location
    Los Angeles, USA
    Posts
    253

    Re: Screen flicker problem? InvalidateRect()

    Hi,

    Quote Originally Posted by berrywong
    void MyDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
    {
    // TODO: Add your message handler code here and/or call default

    CRect rcClient;
    p_view->GetClientRect(&rcClient);
    rcClient.top=rcClient.top/2;

    if(nChar==VK_LEFT)
    {
    p_view->m_tracker.m_rect.left-=1;
    p_view->m_tracker.m_rect.right-=1;

    InvalidateRect(rcClient);
    //Invalidate();
    }
    }
    rcClient.top = rcClient.top / 2 could be a problem. The top of the client is 0.
    Another thing is that InvalidateRect() is being called for the dialog and not the view.

    Jay

  4. #4
    Join Date
    Apr 2005
    Posts
    73

    Re: Screen flicker problem? InvalidateRect()

    Thank you so much for your suggestions, gstercken! I have changed code as below, but flicker in specific rectangular area (rcClient) is still visible . Is there effective method to eliminate flicker completely?

    void MyDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
    {
    CRect rcClient(0,250,600,350);

    if(nChar==VK_LEFT)
    {
    p_view->m_tracker.m_rect.left-=1;
    p_view->m_tracker.m_rect.right-=1;

    InvalidateRect(rcClient, false);
    //Invalidate();
    }
    }

  5. #5
    Join Date
    Apr 2005
    Posts
    73

    Re: Screen flicker problem? InvalidateRect()

    yes, it should be corrected as rcClient.top=rcClient.right/2!

  6. #6
    Join Date
    Apr 2005
    Posts
    73

    Re: Screen flicker problem? InvalidateRect()

    I inserted the following, it still flicker!

    BOOL BIPTTestView::OnEraseBkgnd(CDC* pDC)
    {
    // TODO: Add your message handler code here and/or call default

    return true;//CView::OnEraseBkgnd(pDC);
    }

    BOOL BIPTTestView::PreCreateWindow(CREATESTRUCT& cs)
    {
    // TODO: Add your specialized code here and/or call the base class
    cs.lpszClass = AfxRegisterWndClass(0);
    return CView::PreCreateWindow(cs);
    }

  7. #7
    Join Date
    May 2004
    Posts
    75

    Re: Screen flicker problem? InvalidateRect()

    Handle WM_ERASEBKGND as gstercken suggested.

    Consider to use "double buffering". Should be easy in your case:
    Code:
    CClientDC dc(this);
    CDC bmDC;
    bmDC.CreateCompatibleDC(&dc);
    CBitmap *pOldbmp = bmDC.SelectObject(&bmp);
    
    // Draw the circle on the bitmap.
    DrawCircle(&bmDC);
    
    BITMAP bi;
    bmp.GetBitmap(&bi);
    
    // Blt the whole bitmap including circle to the output dc.
    dc.BitBlt(0,0,bi.bmWidth,bi.bmHeight,&bmDC,0,0,SRCCOPY);
    dc.SelectObject(pOldbmp);
    Also, consider to buffer the image to avoid reading it on every paint.
    Last edited by Oliver M.; April 25th, 2005 at 01:25 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured