GSI

CScrollView 클래스는 스크롤바 관련 메시지 처리를 구현하고 있다. CSrollView::OnHScroll(), CScrollView::ONVScroll() 루틴이 그것인데, 이 두 루틴은 CScrollView::OnScroll()를 호출하도록 구현하고 있다.

그런데 스크롤 메시지(WM_HSCROLL/WM_VSCROLL)의 스크롤 코드가 SB_THUMBTRACK일때, wParam의 상위 워드(16bit)로 전달되는 스크롤 박스의 현재 위치 값이 CScrollView::OnScroll()의 nPos 파라미터로 전달되어 그대로 사용된다. SB_THUMBTRACK이 아닌 다른 스크롤 코드에 대해서는 CScrollView::OnScroll() 루틴이 직접 GetScrollPos() 함수를 호출함으로 스크롤 박스의 현재 위치 값이 32bit값으로 사용된다.

CScrollView::SetScrollSizes()를 사용하여 스크롤 뷰의 크기를 일반적으로 크게 설정할 때, (맵핑모드에 따라 차이는 있겠지만) 결과적으로 다바이스 단위로 변환된 스크롤 뷰의 크기가 16bit int(0 ~ 32767)의 범위를 넘어가면 문제가 발생한다. 스크롤바의 스크롤 박스를 마우스로 드래그할 때 (즉, SB_THUMBTRACK 코드가 발생될 때) 드래그 위치가 16bit int 값으로 짤려서 전달되기 때문에 음수로 해석이 되어 스크롤 박스위치가 0으로 리셋되는 (튕겨지는) 현상이 발생한다.

이 문제를 해결하려면 아래의 예와 같이 CScrollView::OnScroll()를 오버라이드 해야 한다. 다행이 CScrollView::OnScroll()은 버추얼 함수로 되어 있다.

BOOL CPixelMapView::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 CZoomView::OnScroll(nScrollCode, nPos, bDoScroll);
}

발췌 : http://blog.naver.com/lonekid?Redirect=Log&logNo=60045291285
감사 ^^.

Posted by gsi
: