본문 바로가기

Mobile Develop/Windows Programing

[스크랩] - [컨트롤이야기] 아무도 말해주지않은 스크롤바 기능

스크롤바 관련해서 정보를 찾던 도중 유용하게 쓰일 정보를 발견해서 스크랩 하였다
Ospace님께 다시한번 감사 드립니다
---------------------------------------------------------------------------------------------------

[컨트롤이야기] 아무도 말해주지않은 스크롤바 기능

작성자: Ospace (ospace114 at naver.com) http://discount77.com/blog/ospace

스크롤바는 상당히 많이 사용하고 있는 컨트롤 중에 하나이다. 내용을 한 화면에 표시하지 못할 경우 그 일부를 표시하고 나머지 내용은 스크롤 바로 상하, 혹은 좌우로 이동하면서 볼 수 있게 한다.
또는 일정 정수 구간 값을 이동하면서 원하는 지점의 정수 값을 가져올 수도 있다.

먼저 스크롤 바의 기본적인 이야기를 하고 후반에 좀더 깊이 다루겠다.

Note: 예제 코드는 거의 없기에 간단하게 스크롤바를 작성하는 강좌를 보고 읽는게 이해하기 쉽다.



스크롤바 들어가기


사용자 삽입 이미지

Fig 1. Scroll Bar (from Windows XP)


위의 그림은 Windows XP에 있는 스크롤 바이다. 그전 스크롤바보다 이쁘게 변했다. ^^;
MS에서는 이렇게 스킨을 어떻게 했길래 선택적으로 바뀔 수 있지. 컨트롤 스킨 변경하려면 수많은 코드와 삽질을 해야만 되는데.. OTL

아래는 실제 스크롤 바에 구성요소들이다.
사용자 삽입 이미지

Fig 2. Scroll Bar 구성요소



스크롤바는 많이 사용해서 각 기능이야 대충 알고 있지만, 다시 대충 살표보자.

좌우에 삼각형 모양의 버튼이 보인다. 이는 좌후로  1 발자국(step)씩 움직인다. 이는 스크롤바 전체 값 범위에서 실제 1값을 의미의한다.
예를 들어 스크롤바 값 범위가 1~100 혹은 1~1000이든 상관없이 무조건 1을 의미한다.

가운데 홀로 떨어진 스크롤박스가 보인다. 이는 MSDN의 스크롤바 설명을 참조했다. 이를 이용해 값을 찾아간다. 좌우측에 빈 페이지가 보인다.

스크롤바의 정보를 가져오는 API로 GetScrollInfo 함수가 있다. 그리고 정보를 설정하는 API는 SetScrollInfo 함수가 있다.

스크롤바는 100% 수동적인 컨트롤이다. 이말은 모든 부분을 프로그래머가 제어해줘야한다.
예를 들어 가운데 스크롤박스를 움직이면 끝나는 것이 아니라. 그때 스크롤바 위치를 얻고, 해당 값을 다시 스크롤바에 갱신하고 화면을 다시 그리게 한다는 의미이다. 주의하길 바란다!

스크롤바 값은 정수형이다. 실수는 사용할 수 없다. 사용하려면 값변환을 통해서 사용해야 한다. 최대 최소값을 지정하지 않으면 기본 범위는 0~100을 가진다. 일단 정확히 지정해주는게 좋다.

예를 들어 문서를 불러와서 표시하려 한다. 총 줄수가 150개라고 하면, 스크롤바 값 범위는 0~150으로 설정한다. 이건 고정된 값은 아니다. 스크롤바 범위는 300, 450도 가능하고 200도 가능하다.
단지 스크롤바 1스텝이 라인 1줄에 해당하는 형태로 일치시키기 위해서이다.

이렇게 최대 최소 값을 지정하는건 그다지 큰 문제가 없고 다른 사이트에서 많이 다루는 예제이다.


스크롤바 깊게 들어가기


지금은 스크롤바 페이지에 대해서 보도록 하겠다. 페이지는 스크롤바 가운데 있는 스크롤상자 크기에 대한 이야기이다. 스크롤상자는 때에 따라서 커지고 작아지기도 한다. 손오공 여의봉처럼 마음대로 커지고 마음대로 작아지는 놈일까?
그렇지 않다. 사용 목적이 있기 때문에 크기가 그에 따라 변경이된다.

스크롤바 크기는 페이지 크기이다. 한페이지에 들어가는 값 개수이다. 어차피 정수이니 한페이지에 들어가는 정수값 크기라고 보면 된다.

페이지 크기라고 하면 감이 안잡힌다. 예를 들어 책을 살펴보는게 쉽게 이해할 수 있다.
책에는 방대한 양의 글자들이 들어가 있다. (물론 그림, 사진 등도 있다^^;) 모든 내용을 하나의 종이메 모두 담지 못했기에 페이지 단위로 나눠서 표시한다.

예를 들어, 총 1234줄의 내용이 있고 한페이지에 들어가는 줄수는 100줄이라고 가정하면 총 페이지 수는 얼마가될까?

답은 13 페이지
마지막 12페이지를 꽉채우고 34줄이 남지만 한 페이지는 반으로 나눌 수는 없기에 1페이지로 만들어서 넣는다. 추가로 표지, 목차, 속지, 인지 등을 포함하면 더 늘어날 수 있지만 ㅡ.ㅡㅋ

마찬가지로 컴퓨터 화면도 방대한 내용을 한화면에 모두 표시할 수 없기에 페이지 단위로 나눠서 표시한다. 책과 다른 점은 컴퓨터는 연속적으로 페이지를 볼 수 있다.

앞의 책의 예를 일반 텍스트 문서라고 가정해서 스크롤바 설정을 해보자.

최대 최소 값 범위: 0~1234
페이지크기(스크롤박스 크기): 100


너무 쉬어 보인다. 내가 설명을 잘해서인가? ㅋㅋㅋ

그러나 주의할 점이 있다. 바로 스크롤박스가 움직일 수 있는 최대값이 스크롤바 최대값과는 틀리다.
이는 스크롤박스 크기에 따라 가변적이기에 주의해야한다.
사용자 삽입 이미지

Fig 3. Scroll Bar 값들

위 그림은 스크롤바에서 사용되는 값을 표시하였다.
스크롤박스 왼쪽 경계가 현재 값이다. (Current Position)
스크롤바 양쪽 버튼을 제외한 영역이 스크롤바 전체 값 범위이다.(MAX Range Value)
그리고, 양쪽 버튼과 스크롤박스 크기를 제외한 나머지 영역이 스크롤박스가 움직일 수 있는 범위이다.(MAX Scroll Pos)

여기서 중요한 값이 MAX Scroll Pos이다. 현재 위치(Current Position)이 MAX Scroll Pos값을 넘을 수 없다. 단, 최소값은 항상 0으로 가정한다.

0 <= Current Position <= MAX Scroll Pos

그럼 MAX Scroll Pos을 구하는게 중요하다.

MAX Scroll Pos = MAXRangeValue - (Page Size - 1)

Page Size에서 -1은 당연히 Page Size 왼쪽 경계까지 값 범위이기 때문이다. 이를 앞에 책의 예를 이용해서 다시 스크롤바 설정을 해보자.

최대 최소 값 범위: 0~1234
페이지크기(스크롤박스 크기): 100
스크롤박스 이동 범위: 0 ~ 1135




스크롤바 전문가 과정

좀더 스크롤바를 깊게 들어가자. 지금 부터 조금 머리 아파질 수 있으니, 지금 머리가 조금 아프신 분들은 창문가서 밖같 하늘 한번 구경하자.

지금 다를 내용은 크게 두가지 이다. 하나는 프로그램 크기(resize)와 데이터 변경되는 경우와 다른하나는 스크롤을 좀더 세밀하기 하기 위해 스크롤바 최대 최소 범위를 변경하는 경우이다.


프로그램 크기와 데이터 변경

먼저 프로그램 크기와 데이터가 변경되는 경우를 살펴보자.
프로그램 크기가 변경되는 의미는 내용이 나타나는 화면 크기가 바뀌었다는 의미이고 스크롤 바에서는 한 화면에 표시되는 크기를 가리키는 스크롤박스 크기가 달라졌다는 의미이다.

앞의 책의 예를 보면 한페이지에 표시할 수 있는 줄수가 100줄에서 130줄 혹은 50줄로 커지거나 작아졌다는 의미이다.
일단 내용 변경이 없다면 스크롤바 최대 최소 값 범위은 변경되지 않고 페이지 크기가 변경되었고, 즉, 스크롤박스가 이동할 수 있는 범위가 변경되었다는 의미이다.

책의 예제에서 한페이지(한화면)에서 표시할 수 있는 줄수가 100줄에서 130줄로 변경되었다면 스크롤바 설정을 살펴보자.

스크롤바 최대 최소 값 범위: 0 ~ 1234
페이지크기(스크롤박스 크기): 100 -> 130 (변경)
스크롤박스 이동 범위: 1234 - (130 - 1) = 1103 (변경)
페이지수: 10 페이지 (이는 스크롤바 설정 값은 아니다.)


그리고 데이터가 변경되었다면 어떻게 될까?
일단 스크롤바 최대 최소 값 범위가 변경된다. 페이지 크기는 고정이지만, 스크롤 박스 이동 범위도 바뀌게 된다. 즉, 전체 크기가 변경되었으므로 이동가능한 범위도 변경되었다는 의미이다. 그럼 마찬가지로 앞의 책의 예로 계산해보자.
가정은 데이터 량이 1234줄에서 1500줄로 늘어낳고 한 페이지 크기는 130줄로 계산해보자.

스크롤바 최대 최소 값 범위: 0 ~ 1500 (변경)
페이지크기(스크롤박스 크기): 130
스크롤박스 이동 범위: 1500 - (130 - 1) = 1371 (변경)
페이지수: 12 페이지 (이는 스크롤바 설정 값은 아니다.)


화면 크기 혹은 데이터 크기 변경은 각각 페이지 크기 변경 혹은 스크롤바 최대 값 변화가 따로 생기지만 스크롤박스 이동 범위는 둘 다 새로 계산해야 된다.


스크롤바 정밀도 조절하기

데이터 크기와 스크롤바 크기가 일치하지 않은 경우를 살펴보자.
앞에서는 텍스트 한줄이 스크롤바 한스텝과 일치한다. 스크롤바에서 3값이 움직이면 텍스트에서 3줄이 움직인다.

간혹 1 스텝 이동이 1/2 줄 이동이나 1 스텝 이동이 2줄 이동으로 할 경우도 있다.

사용자 삽입 이미지

Fig 4. 1스텝 이동시 반줄 이동


이 그림은 1 스텝 이동은 반 줄 이동하는 예를 보여둔다. 즉 2 스텝 이동해야 한 줄이 이동된다는 의미이다. 즉 한 스텝 이동하면 글자 반정도 크기만 움직이고 화면 경계에 있다면 반은 보이고 반은 가려서 보이지 않게된다. 한 스텝이 글자 반 정도 움직이는 느린 스크롤이 된다.

사용자 삽입 이미지

Fig 5. 1스텝 이동시 2줄 이동



이 그림은 1 스템 이동이 2줄 이동하는 예이다. 즉, 반 스텝 이동이 한줄 이동이지만 반 스텝 이동은 없다. 스크롤 바는 정수 값만 사용하기 때문이다.
한스텝 이동은 2줄이 한꺼번에 움직이므로 빠른 화면 스크롤을 볼 수 있다.

그러면 위와 같은 경우 스크롤바 값 설정은 어떻게 될 것인다.
간단하게 계산하기 위해서 텍스트 줄수는 100줄이고 한화면 표시되는 페이지 크기는 10라고 하자.


1스텝에 1/2줄 이동

먼저 한 스텝에 반 줄 이동하는 예를 보자.
즉, 한줄이 2스텝을 차지하므로 총 100줄이므로,

100줄 x 2 스텝 / 줄 = 200 스텝

결국 스크롤바 값 범위가 0 ~ 200를 가진다. 좀더 생각을 하면 앞에서 스크롤바는 정수값만 사용한다고 했지만, 위의 값의 범위는 0~100줄은 0.5줄 단위까지 잘라서 얻을 수 있다는 의미이다.
페이지 크기가 10는 스템 수가 아닌 화면에 나타나는 줄 수 이다. 그러면 페이지 크기는

10줄 x 2 스텝 / 줄 = 20 스텝

페이지 크기는 20스텝이 된다.
그러면 스크롤박스 최대 이동 가능한 값이 계산된다.

스크롤박스 최대 이동 값 = 200 - (20 - 1) = 181

스크롤박스 최대 이동 값은 181이 된다.


1스텝에 2줄 이동

다음으로 1스텝이 2줄 이동하는 예를 살펴보자. 앞의 계산 법의 확인일 뿐이다.
앞의 계산 법에 의해서 단위 줄에 변하는 스텝 값은 1/2이 된다.

스크롤바 최대값: 100줄 x 1/2 스텝/줄 = 50 스텝
페이지 크기: 10줄 x 1/2 스텝/줄 = 5 스텝
스크롤박스 최대 이동 값: 50 - (5 - 1) = 46


계산 방법은 동일하다. 이부분은 텍스트를 예로 들어서 설명했지만, 그래픽 처리에서 상당히 유용하리라 생각한다.


후기

이 부분을 해결하는데 많은 시간이 소요되었다. 이에 웹 사이트를 아무리 뒤져봐도 이에 대해 잘 설명해준 곳이 없었다. 심지어 책에도 없었다. 분명 모든 개발자가 스크롤바를 사용함에 있어서 이에 대해서 한번 쯤은 고민해봤을 거라 생각한다.
대부분 화면이 고정인 경우만 고려했을 거라 생각한다. 홤녀이 고정이면 계산은 간단하다. 약간의 계산 오류가 있어도 시행착끝에 근사 계산값을 얻을 수도 있다.

결정적인 힌트를 준 자료는 MSDN의 "About Scroll Bars"이다. 결국 MSDN으로 오게 된다.
아직 못다른 부분도 많을 것이다. 스크롤바로 활용가능한 부분도 상당히 광범위하기 때문이다.

위의 내용은 스크롤 바를 사용하고 있으면서 좀더 넓은 생각을 가지기 위해서 작성했다. 첫 사용자는 다른 자료를 참고하기길 바란다.

스크롤바 강좌: http://www.winapi.co.kr/win32lec/lec7/lec7-5-1.htm

앞으로 어떻게 응용하는가는 본인의 의지에 달려있다.
모두 즐프를 향해~


참고: MSDN "About Scroll Bars"