스크롤바를 사용하다 보면 32767 unsigned short의 양의값을 넘어가는 경우가
간혹 발생할 수 있다.

그래픽 디자인 프로그램과 같은 것들을 설계할 때야 줌 팩터등을 이용하여 따로 처리하니
별 문제가 없겠지만 간단한 먼가를 만들 때 100000의 값을 써야한다면 먼가 설계를 해야하나?

그렇다면 우선 MSDN을 살펴보자.

CScrollBar::SetScrollRange
Set nMinPos and nMaxPos to 0 to hide standard scroll bars.
Do not call this function to hide a scroll bar while processing a scroll-bar notification message.

If a call to SetScrollRange immediately follows a call to the SetScrollPos member function, set bRedraw in SetScrollPos to 0 to prevent the scroll bar from being redrawn twice.

The difference between the values specified by nMinPos and nMaxPos

must not be greater
than 32,767

. The default range for a scroll-bar control is empty

일단 스크롤바의 SetScrollRange의 인자는 int 값인데, 어쩌구 저쩌구한 이유로 32767이 최대
라고 한다. 인자가 int라면 그렇다면 먼가를 처리하면 최대 양수 20억까지 쓸수 있다는 야근데..



SetScrollRange Function Win32API

 

However, because the SetScrollInfo, SetScrollPos, SetScrollRange, GetScrollInfo,
GetScrollPos, and GetScrollRange

functions support 32-bit scroll bar position data,

there is a way to circumvent the 16-bit barrier of the WM_HSCROLL and WM_VSCROLL


messages. See GetScrollInfo for a description of the technique.

MSDN에서 API의 도움말을 살펴보았다. Remark를 자세히 보다보니 32비트를 쓸 수 있는데
16비트 베리어에 쌓여 있단다.. 그렇다면 위의 두 메시지에서 오는 UINT nPos 가 정수
범위임에도 불구하고 쇼트크기를 가진다면 저걸 않쓰면 가능하지 않을까...


(16비트 베리어라는 의미는 내부적으로 먼가를 처리할 때 아무생각 없이 16비트를 썼다는
내용을 아주 점잔하게 표시한 것으로 추측된다.. 즉, 16비트 머신의 잔제가 남았다는 거겠죠.)

--------------------------------------------------------------------------------------

일단 여기까지 살펴보면 32비트를 쓸 수 있는데도 불구하고, 메시지 WM_VSCROLL과
WM_HSCROLL의 UINT nPOS는 16비트 최대값을 가진다고 결론을 내릴 수있다.
즉, 저걸 않쓰면 된다는 이야기겠고..

그럼 저걸 않쓰고 프로그램을 구성하면 되겠죠..
이전 장에 있던 샘플은 0 부터 100까지 크기를 가지는 샘플이었습니다.
이걸 그럼 위의 지식을 기반으로 0부터 1000000 크기를 가지는 샘플로 바꿔보죠.

#define SCROLL_MIN   0
#define SCROLL_MAX 

1000000


마이스크롤.SetScrollRange(SCROLL_MIN, SCROLL_MAX);
마이스크롤.SetScrollPos(50);
마이스크롤.EnableScrollBar(ESB_ENABLE_BOTH);

요렇게 설정을 해놓고 WM_VSCROLL 핸들러를 다음과 같이 수정해봅니다.
어짜피 이전 샘플에서도 nPos를 쓰는데는 스크롤바를 트래킹할 때만 썻으므로
이 샘플에서도 바뀌는 부분은 거기 밖에는 없습니다.

void CSampleDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    UINT nCurPos;
    if(pScrollBar->GetDlgCtrlID() == IDC_SCROLLBAR5)
    {
        nCurPos = pScrollBar->GetScrollPos();
        switch(nSBCode)
        {
       

// 중간 생략.. 원본과 다른바 없음.

       case SB_THUMBPOSITION:
       {
          SCROLLINFO si = {0};
          si.cbSize = sizeof(SCROLLINFO);
          si.fMask = SIF_TRACKPOS;
          ::GetScrollInfo(pScrollBar->m_hWnd, SB_CTL, &si);

          // 메시지의 nPos 대신에 그냥 트랙포스를 가져다 쓴다.


          pScrollBar->SetScrollPos(si.nTrackPos);
       }
       break;

       case SB_THUMBTRACK:
       {
          SCROLLINFO si = {0};
          si.cbSize = sizeof(SCROLLINFO);
          si.fMask = SIF_TRACKPOS;
          ::GetScrollInfo(pScrollBar->m_hWnd, SB_CTL, &si);

          // 메시지의 nPos 대신에 그냥 트랙포스를 가져다 쓴다.


          pScrollBar->SetScrollPos(si.nTrackPos);
       }
       break;
      // 아래도 생략.. 원본과 같음
    }
 
    CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

헉.. 그냥 않쓰면 되네.. ㅜㅜ;;;
그럼 수고하세요..

scroll02.zip
0.03MB

 

 

+ Recent posts