[MFC] CScrollView - Flicker free drawing using memory DC 사용하기.
MFC&ActiveX 2007. 12. 20. 10:51 |하지만 지금 테스트해본 결과가 맞는 정답은 아니겠지만 많은 부분 개선되는 것을 확인했습니다.
스크롤 사이즈를 10240000 까지 늘려서 테스트를 진행했습니다.
SetScrollSizes(MM_TEXT, sizeTotal);
미리 선과제로 OnEraseBkgnd()는 return false로 변경을 하고 시작했습니다.
{
return false;
}
하나더 해줘야 할게 CScrollView의 스크롤이 16bit로 되는 현상을 32bit로 전환처리. (이건 제 블로그나 기타 다른 곳에도 기술되어 있습니다.)
{
// 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는 아래 코드가 있습니다.
스크롤 테스트한 총 예제는 아래 코드..