[MFC] CScrollView의 스크롤 메시지(SB_THUMBTRACK)에서 16bit 위치 값이 전달되는 문제.
MFC&ActiveX 2007. 12. 19. 01:08 |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
감사 ^^.