2010년 10월 22일 금요일

[스크롤바-기초02] 얏 움직여라~

스크롤바를 달아만 놨었다.. 요지부동.. ㅎㅎ

스크롤바 컨트롤을 상속받아서 내부에서 처리하지 않는이상... 다이알로그 등에 올려놓고 쓰려면
WM_VSCROLLWM_HSCROLL  메시지를 처리해서 하나 하나 직접 동작시켜 주어야 한다.

현재 길쭉한 나무 막대기 모양으로 만들었으니, WM_VSCROLL 메시지를 이용하여 스크롤바가
원하는 동작을 하도록 만들어 보자.


그림 처럼 클래스 위저드를 이용하여 메시지 핸들러를 추가한다.

그전에 알아두어야 할것이, winuser.h 에 디파인 되어있는 스크롤바의 동작에 관한 디파인이다.
우리가 사용할 WM_VSCROLL 메시지 핸들러의 정의부를 살펴보면 첫번째 인자에 전달되는
값이기도 하기 때문에 꼭 알고 있어야 한다.

afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);

아래에서 디파인이 같은 것들이 존재하는 이유는 결국 같은 동작이지만 수직 스크롤과 수평
스크롤을 구분해 보여주기 위하여 나누어 놓은것이다.
#define SB_LINEUP             0
#define SB_LINELEFT          0
#define SB_LINEDOWN         1
#define SB_LINERIGHT         1
#define SB_PAGEUP            2
#define SB_PAGELEFT         2
#define SB_PAGEDOWN        3
#define SB_PAGERIGHT        3
#define SB_THUMBPOSITION 4
#define SB_THUMBTRACK     5
#define SB_TOP                    6
#define SB_LEFT                  6
#define SB_BOTTOM             7
#define SB_RIGHT                 7
#define SB_ENDSCROLL        8

그러므로 수직 스크롤바에 대하여 설명하면 수평은 자동이해.. ^^;
#define SB_LINEUP              0 - 위의 버튼 누름
#define SB_LINEDOWN         1 - 아래 버튼 누름
#define SB_PAGEUP            2 - 버튼과 이동막대기(thumb)사이의 상단 공간 누름
#define SB_PAGEDOWN        3 - 버튼과 이동막대기(thumb)사이의 하단 공간 누름
#define SB_THUMBPOSITION 4 - 이동 막대기의 최종위치
#define SB_THUMBTRACK     5 - 이동 막대기가 계속 이동하고 있음
#define SB_TOP                    6 - 크기가 변하거나 업데이트 될 때.. min 설정
#define SB_BOTTOM             7 - 크기가 변하거나 업데이트 될 때.. max 설정
#define SB_ENDSCROLL        8 - 한단계의 스크롤 동작을 마침

아주 간단하게 동작에 대해 설명했는데.. 6,7,8번을 제외하고는 이해하는데 별 문제가 없다.
SB_TOP, SB_BOTTOM은 레인지를 다시 설정하거나 크기를 변경하거나 할 때 발생하는
것이라는데 거의 사용하지 않는다.

스크롤시에 버튼을 꾹 누르고 있거나 이동 막대기를 잡고 왔다 갔다 하다가 마지막에 마우스
버튼을 딱 띠는 순간 SB_ENDSCROLL가 발생한다. 마우스를 누르고 이리 저리 움직이면
내부 타이머에 의하여 연속적으로 이벤트가 발생하는데, 이 이벤트가 떨어지면 전체적인
하나의 동작으 완료되었음을 알 수 있게된다.

보통 잘 쓰이지는 않는데.. 연속적인 동작에는 관심없고 마지막 최종 동작에만 관심이 있을 경우
위 이벤트를 이용하여 최종 포지션을 읽어와서 먼가 작업을 한다던가 할 때 주고 쓰인다.


아래는 실제로 이벤트 핸들러 내부에 동작을 구현해본 코드이다.
1. 버튼을 누를 경우는 위 아래로 +-1 이동하고
2. 이동막대기를 움직일 때는 움직인 만큼
3. 페이지 영역을 누를 때는 +-5로 이동하도록 구현하였다.

void CSampleDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    if(!pScrollBar || !pScrollBar->m_hWnd)
        return;

    if(pScrollBar->GetDlgCtrlID() == IDC_SCROLLBAR5)
    {
        UINT nCurPos = pScrollBar->GetScrollPos();
        switch(nSBCode)
        {
        case SB_BOTTOM:
            pScrollBar->SetScrollPos(SCROLL_MAX);
            break;

        case SB_ENDSCROLL:
            break;

        case SB_LINEDOWN:
            nCurPos += 1;
            if(nCurPos > SCROLL_MAX)
                nCurPos = SCROLL_MAX;
            pScrollBar->SetScrollPos(nCurPos);
            break;

        case SB_LINEUP:
            nCurPos -= 1;
            if(nCurPos < SCROLL_MIN)
                nCurPos = SCROLL_MIN;
            pScrollBar->SetScrollPos(nCurPos);
            break;

        case SB_PAGEDOWN
            nCurPos += 5;
            if(nCurPos > SCROLL_MAX)
                nCurPos = SCROLL_MAX;
            pScrollBar->SetScrollPos(nCurPos);
            break;

        case SB_PAGEUP:
            nCurPos -= 5;
            if(nCurPos < SCROLL_MIN)
                nCurPos = SCROLL_MIN;
            pScrollBar->SetScrollPos(nCurPos);
            break;

        case SB_THUMBPOSITION:
             pScrollBar->SetScrollPos(nPos);
            break;

        case SB_THUMBTRACK:
            pScrollBar->SetScrollPos(nPos);
            break;

        case SB_TOP:
             pScrollBar->SetScrollPos(SCROLL_MIN);
            break;
        }
    }
 
    CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

댓글 없음:

댓글 쓰기