화요일, 3월 11, 2008

View class의 Flickering 방지

View class를 이용해 화면에 디스플레이할 때, 정해진 시간간격으로 데이터를 업데이트 할 경우

화면이 깜박거리는 현상을 볼 수 있다.


이러한 현상은 몇 가지 기능의 조합으로 해결 가능하다.

간단히 말하면, 배경 지우기 방지 + 메모리에 그리고 한꺼번에 현재의 화면과 교환 이다.


  1. View에 Wnd object가 존재 할 경우 View class의 생성시에 속성에 WS_CLIPSIBLING과 WS_CLIPCHILDREN을 추가해 준다.

    이것은 화면 업데이트 시에 Wnd object의 영역은 제외하고 업데이트 하여 이 object가 깜박거리는 것을 방지하기 위함이다.


    BOOL CPlanView::PreCreateWindow(CREATESTRUCT& cs)

    {

    cs.style|=WS_CLIPSIBLINGS|WS_CLIPCHILDREN;

    return CView::PreCreateWindow(cs);

    }


  2. View에 OnErawseBkgnd 함수를 추가하고 아래와 같이 변경해 준다.

    화면을 업데이트 할 때 배경을 지우라는 명령에서 이 메소드가 실행되는데 이 때, 배경을 지우지 않고

    배경을 지웠다고 알려주는 것으로 변경하는 것이다.


    BOOL CPlanView::OnEraseBkgnd(CDC* pDC)

    {

    return TRUE;

    }


  3. OnDraw 함수에서 메모리에 dc를 생성하고 이 메모리 dc에 원하는 출력을 한 후에 현재의 dc와 swap하는 방식의 코드를 만든다.


    void CPlanView::OnDraw(CDC* pDC)

    {

    CPOMDPDoc* pDoc = GetDocument();


    CDC dc;

    CDC* pMemDC = pDC;


    CBitmap *pOldBitmap;

    CBitmap bitmap;


    CRect rect;

    GetClientRect(&rect);


    if (!pDC->IsPrinting())

    {

    if (dc.CreateCompatibleDC(pDC))

    {

    if (bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()))

    {

    OnPrepareDC(&dc, NULL);

    pMemDC = &dc;

    pOldBitmap=dc.SelectObject(&bitmap);

    }

    }

    }


    CBrush brush;

    if (!brush.CreateSolidBrush(0x00ffffff)) return;

    brush.UnrealizeObject();

    pMemDC->PatBlt(rect.left,rect.top,rect.Width(),rect.Height(),PATCOPY); // 배경을 그린다.


DrawPlan(pMemDC);

원하는 draw 내용을 구현


if (pMemDC != pDC)

{

GetClientRect(&rect);

pDC->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),&dc, 0 , 0, SRCCOPY);

dc.SelectObject(pOldBitmap);

}


brush.DeleteObject();

bitmap.DeleteObject();

dc.DeleteDC();

}


댓글 없음:

댓글 쓰기