2011년9월26일_winAPI_스크롤 바(Scroll Bar)


스크롤 바는 지금까지 사용한 컨트롤들(버튼, 체크박스, 라디오버튼, 에디트등등)에 비해서는 비교적 복잡한 컨트롤이다.
윈도우의 스크롤 상태를 관리하기 위해 사용하기도 하며 일정 범위에 있는 값을 대충 선택할 때도 사용한다.

스크롤 바는 “scrollbar”윈도우 클래스로 CreateWindow( )를 사용하여 생성하며,
세 번째 인자 스타일에 수평 스크롤 바일 경우 SBS_HORZ스타일을,
                           수직 스크롤 바일 경우 SBS_VERT스타일을 지정한다.
스크롤 바는 범위와 현재 위치값을 가지는데 다음 두 함수로 이 값들을 지정한다.


BOOL SetScrollRange(HWND hWnd,        // 스크롤 바의 윈도우 핸들
                           int nBar,               // 메인 윈도우에 부착된 표준 스크롤바 또는 별도의 스크롤바(SB_CTL) 지정
                           int nMinPos,          // 최소값
                           int nMaxPos,          // 최대값
                           BOOL bRedraw);      // 스크롤바의 범위를 변경한 후 다시 그릴 것인지 여부

상기의 SetScrollRange( )는 함수이름에서 알 수 있듯이 스크롤바의 범위를 지정하는 함수이다.
첫 번째 인자인 hWnd는 스크롤 바의 윈도우 핸들로 CreateWindow( )의 리턴값인 윈도우 핸들을 넣으면 된다.
두 번째 인자인 nBar는 메인 윈도우의 스크롤바 또는 별도의 스크롤바를 지정하는 것이라는데,
                            SB_HORZ, SB_VERT는 표준 스크롤 바이고, SB_CTL은 별도의 스크롤바라고 한다. SB_BOTH도 표준인가?
세 번째 인자인 nMinPos는 스크롤바의 최소값이고,
네 번째 인자인 nMaxPos는 스크롤바의 최대값이다.
마지막 인자인 bRedraw는 스크롤바의 범위를 변경한 후 다시 그릴 것인지 여부로 TRUE로 하면 다시 그린다.


int SetScrollPos(HWND hWnd,        // 스크롤 바의 윈도우 핸들 
                    int nBar,               // 메인 윈도우에 부착된 표준 스크롤바 또는 별도의 스크롤바(SB_CTL) 지정 
                    int nPos,               // 스크롤박스의 위치
                    BOOL bRedraw);      // 스크롤바의 범위를 변경한 후 다시 그릴 것인지 여부

SetScrollPos( )는 스크롤바의 위치..정확히 말하면 스크롤박스의 위치를 지정하는 함수이다.
SetScrollRange( )와 다른 부분은 세 번째 인자가 스크롤박스의 위치를 받도록 되어 있다는 것이다. 사용법은 비슷하다.


image 

이해하기 쉽도록 상기와 같이 스크롤바에 최소값, 최대값과 현재값을 표시하였다.


image

다른 컨트롤들은 자신에게 변화가 있을 때 부모 윈도우로 WM_COMMAND 통지 메시지를 보내는데 비해,
스크롤 바는 수평일 경우 WM_HSCROLL, 수직일 경우 WM_VSCROLL이라는 별도의 메시지를 부모 윈도우로 보낸다.

image

메시지 전달 후 파리미터는 상기와 같은 값들이 들어가 있고,
wParam의 상위워드인 HIWORD(wParam)은 스크롤바의 스크롤박스의 현재 위치가 저장되어 있고,
             하위워드인 LOWORD(wParam)은 스크롤바의 어디를 눌렀나 알 수 있는 정보가 들어가 있다.
lParam은 다른 컨트롤과 마찬가지로 변화가 발생한 스크롤바 컨트롤의 윈도우 핸들이 들어가 있다.

이 중에서 LOWORD(wParam)의 값들의 종류는 아래와 같다.

LOWORD(wParam)의 값

설명

SB_LINELEFT
또는 SB_LINEUP

image  값이 1씩 감소

SB_LINERIGHT
또는 SB_LINEDOWN

image  값이 1씩 증가

SB_PAGELEFT
또는 SB_PAGEUP

image  값이 크게 감소

SB_PAGERIGHT
또는 SB_PAGEDOWN

image  값이 크게 증가
   9:  

SB_THUMBPOSITION

image 

막대를 잡고 이동 후
놓았다.

SB_THUMBTRACK

image

막대를 잡고 이동 중
이면 이 메시지가
계속 발생한다.




● windows API정복 page.220 예제: ScrollBar
▷ MsgProc.cpp (메시지 처리함수 모음)만 미리보기

   1: //MsgProc.cpp
   2:  
   3: #include "MsgProc.h"
   4:  
   5: HWND hRed, hGreen, hBlue;
   6: int Red, Green, Blue;        //전역변수는 0으로 초기화됨.
   7: HDC hdc;
   8:  
  10: LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
  11: {
  12:     hRed = CreateWindow(TEXT("scrollbar"), NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ,
  13:         10, 10, 400, 20, hWnd, (HMENU)ID_SCRRED, g_hInst, NULL);
  14:     hGreen = CreateWindow(TEXT("scrollbar"), NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ,
  15:         10, 40, 400, 20, hWnd, (HMENU)ID_SCRGREEN, g_hInst, NULL);
  16:     hBlue = CreateWindow(TEXT("scrollbar"), NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ,
  17:         10, 70, 400, 20, hWnd, (HMENU)ID_SCRBLUE, g_hInst, NULL);
  18:  
  19:     SetScrollRange(hRed, SB_CTL, 0, 255, TRUE);        //0~255사이의 값을 가짐.
  20:     SetScrollPos(hRed, SB_CTL, 0, TRUE);            //위치는 0
  21:     SetScrollRange(hGreen, SB_CTL, 0, 255, TRUE);    //0~255사이의 값을 가짐.
  22:     SetScrollPos(hGreen, SB_CTL, 0, TRUE);            //위치는 0
  23:     SetScrollRange(hBlue, SB_CTL, 0, 255, TRUE);    //0~255사이의 값을 가짐.
  24:     SetScrollPos(hBlue, SB_CTL, 0, TRUE);            //위치는 0
  25:  
  26:     return 0;
  27: }
  28:  
  29: LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
  30: {
  31:     return 0;
  32: }
  33:  
  34: LRESULT OnHScroll(HWND hWnd, WPARAM wParam, LPARAM lParam)    //수평스크롤 변화시 발생하는 메시지처리
  35: {
  36:     int TempPos;        //지역변수는 쓰레기값 초기화안됨.
  37:  
  38:     // 윈도우 핸들을 검사하여 어느 스크롤바를 변화시켰는지 알아냄.
  39:     if((HWND)lParam == hRed) TempPos = Red;
  40:     if((HWND)lParam == hGreen) TempPos = Green;
  41:     if((HWND)lParam == hBlue) TempPos = Blue;
  42:  
  43:     switch(LOWORD(wParam)) {
  44:     case SB_LINELEFT:
  45:         TempPos = max(0, TempPos - 1);        // 인자 두 개 중 최대값을 추출.
  46:         break;                                // 반환값은 0보다 크거나 같다. 
  47:  
  48:     case SB_LINERIGHT:
  49:         TempPos = min(255, TempPos + 1);    // 인자 두 개 중 최소값을 추출.
  50:         break;                                // 반환값은 255보다 작거나 같다.
  51:  
  52:     case SB_PAGELEFT:
  53:         TempPos = max(0, TempPos - 10);
  54:         break;
  55:  
  56:     case SB_PAGERIGHT:
  57:         TempPos = min(255, TempPos + 10);
  58:         break;
  59:  
  60:     // 스크롤 박스를 움직이는 경우
  61:     case SB_THUMBTRACK:
  62:         TempPos = HIWORD(wParam);    //현재 위치를 TempPos에 저장
  63:         break;
  64:     }
  65:  
  66:     // 움직인 스크롤 바에 대응하는 색상변수에 스크롤바의 현재위치를 저장.
  67:     if((HWND)lParam == hRed) Red = TempPos;
  68:     if((HWND)lParam == hGreen) Green = TempPos;
  69:     if((HWND)lParam == hBlue) Blue = TempPos;
  70:  
  71:     SetScrollPos((HWND)lParam, SB_CTL, TempPos, TRUE);    //스크롤바의 위치를 갱신
  72:     InvalidateRect(hWnd, NULL, FALSE);                    //윈도우 무효화해 다시 그리게 함.
  73:  
  74:     return 0;
  75: }
  76:  
  77: LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
  78: {
  79:     return 0;
  80: }
  81:  
  82: LRESULT OnRButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
  83: {
  84:     return 0;
  85: }
  86:  
  87:  
  88: LRESULT OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
  89: {
  90:  
  91:     return 0;
  92: }
  93:  
  94: LRESULT OnLButtonUp(HWND hWnd, WPARAM wParam, LPARAM lParam)
  95: {
  96:     return 0;
  97: }
  98:  
  99: LRESULT OnLButtonDBLCLK(HWND hWnd, WPARAM wParam, LPARAM lParam)
 100: {
 101:  
 102:     return 0;
 103: }
 104:  
 105:  
 106: LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
 107: {
 108:     HDC hdc;
 109:     PAINTSTRUCT ps;
 110:     HBRUSH MyBrush, OldBrush;
 111:  
 112:     hdc = BeginPaint(hWnd, &ps);        //DC얻기
 113:     MyBrush = CreateSolidBrush(RGB(Red, Green, Blue));    //사용자 브러시 오브젝트 생성.
 114:     OldBrush = (HBRUSH)SelectObject(hdc, MyBrush);        //사용자 브러시 적용.
 115:     Rectangle(hdc, 10, 100, 410, 300);                    //사각형을 그림.
 116:     SelectObject(hdc, OldBrush);                        //브러시를 예전 것으로 되돌림.
 117:     DeleteObject(MyBrush);                                //오브젝트핸들 지움.
 118:     
 119:     EndPaint(hWnd, &ps);
 120:  
 121:     return 0;
 122: }
 123:  
 124: LRESULT OnDestroy(HWND hWnd, WPARAM wParam, LPARAM lParam)
 125: {
 126:     PostQuitMessage(0);
 127:     return 0;
 128: }

전체소스코드 다운로드 : 0926_ScrollBar.zip




<실행결과>

image image image


image image image

image image image
image image image