GSI

기존 CScrollView를 사용하면서 mfc의 DC 드로잉 부분에서 부족했던 저로서는 번쩍 거리는 화면이 너무 안좋게 보였습니다.
하지만 지금 테스트해본 결과가 맞는 정답은 아니겠지만 많은 부분 개선되는 것을 확인했습니다.

스크롤 사이즈를 10240000 까지 늘려서 테스트를 진행했습니다.
sizeTotal.cx = sizeTotal.cy = 10240000;
SetScrollSizes(MM_TEXT, sizeTotal);

미리 선과제로 OnEraseBkgnd()는 return false로 변경을 하고 시작했습니다.

BOOL CScrollViewTestView::OnEraseBkgnd(CDC* pDC)
{
     return false;
}

하나더 해줘야 할게 CScrollView의 스크롤이 16bit로 되는 현상을 32bit로 전환처리. (이건 제 블로그나 기타 다른 곳에도 기술되어 있습니다.)

BOOL CScrollViewTestView::OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll)
{
 // When you drag the scroll box, the nPos value send from WM_HSCROLL/WM_VSCROLL is 16bit value.
 // Therefore retrieve the 32bit scroll box position value.
 if(SB_THUMBTRACK == LOBYTE(nScrollCode)) // WM_HSCROLL
 {
  SCROLLINFO info;
  if(GetScrollInfo(SB_HORZ, &info, SIF_TRACKPOS))
  {
   nPos = info.nTrackPos; // 32bit position value.
  }
 }
 else if(SB_THUMBTRACK == HIBYTE(nScrollCode)) // WM_VSCROLL
 {
  SCROLLINFO info;
  if(GetScrollInfo(SB_VERT, &info, SIF_TRACKPOS))
  {
   nPos = info.nTrackPos; // 32bit position value.
  }
 }

 return CScrollView::OnScroll(nScrollCode, nPos, bDoScroll);
}

이후에 OnDraw(CDC* pDC) 에서 테스트를 했습니다.

스크롤 내부의 총 사이즈를 사용해서 드로잉을 해봤습니다.

CSize size = GetTotalSize()
... 중략...
 for(int x = 0; x < size.cx; x += 10) {
  pDC->MoveTo(x, 0);
  pDC->LineTo(x, size.cy);
 }

 for(int y = 0; y < size.cy; y += 10) {
  pDC->MoveTo(0, y);
  pDC->LineTo(size.cx, y);
 }

이렇게 테스트를 하니까. tick를 찍어 봤을때 2250 이 나오네요. -.-;

그래서 우선  Flicker Free Drawing 를 사용해서 해봤습니다.

 CRect rcBounds = CRect(0, 0, size.cx, size.cy);
 CMemDC pDCEx(pDC);
 pDCEx->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));

 for(int x = 0; x < size.cx; x += 10) {
  pDCEx->MoveTo(x, 0);
  pDCEx->LineTo(x, size.cy);
 }

 for(int y = 0; y < size.cy; y += 10) {
  pDCEx->MoveTo(0, y);
  pDCEx->LineTo(size.cx, y);
 }

하지만 tick는 2500 으로 더 많게 되네요. 왜냐하면. 메모리 DC를 만들고 하다 보니 그런거 같아요.

그래서 스크롤은 안보이는 부분을 드로잉하지 않는 처리를 해야 하는거 같아서
아래와 같이 값을 구한다음에 처리를 해봤습니다.

 CSize size = GetTotalSize();  // 페이지의 총 사이즈(안보이는 부분까지 싹다)
 CRect clientRect;
 GetClientRect(&clientRect);    // 현재 화면에 보이는 클라이언트 정보

 CPoint scrollpos = GetScrollPosition();  // 스크롤 된 위치 좌측 상단
 CPoint devicescrollpos = GetDeviceScrollPosition();  // 디바이스별... 이건 위와 같네요(현재 상태에서는)

// 드로잉 간격을 10씩 했기 때문에 시작 지점을 보정해 줬습니다.
 CPoint startpos = CPoint(scrollpos.x%10, scrollpos.y%10);
 startpos.x = scrollpos.x - startpos.x;
 startpos.y = scrollpos.y - startpos.y;

// 시작지점과 클라이언트 영역을 사용해서 끝 점을 구했습니다.
 CPoint endpos = CPoint(scrollpos.x + clientRect.Width(), scrollpos.y + clientRect.Height());

드로잉은 아래와 같이 테스트...

 CRect rcBounds = CRect(0, 0, size.cx, size.cy);
 CMemDC pDCEx(pDC);
 pDCEx->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));

 for(int x = startpos.x; x < endpos.x; x += 10) {
  pDCEx->MoveTo(x, 0);
  pDCEx->LineTo(x, size.cy);
 }

 for(int y = startpos.y; y < endpos.y; y += 10) {
  pDCEx->MoveTo(0, y);
  pDCEx->LineTo(size.cx, y);
 }

이렇게 작업을 해서 안보이는 부분을 처리 했습니다.
처음 시작할때는 조금 딜레이가 있지만. 번쩍 거리는 현상의 거의 없어 지네요.
앞으로 복잡한 부분이 아닌 적당한 드로잉 방법에는 Flicker Free Drawing를 사용해야 겠습니다. ^^..


여기서 사용한 CMemDC는 아래 코드가 있습니다.




스크롤 테스트한 총 예제는 아래 코드..

Posted by gsi
: