WINAPI - 스크롤 바
내장형 하드웨어/WINAPI / 2011. 9. 26. 14:59
- 스크롤바는 이전의 컨트롤들에 비해서는 비교적 복잡한 컨트롤이다.
→ 윈도우의 스크롤 상태를 관리하기 위해 사용하기도 하며 일정 범위에 있는 값을 대충 선택할 때도 사용한다.
→ 예로 사운드 볼륨이나 당구 게임의 힘 세기를 선택할 때 등에는 수치로 된 정확한 값보다는 대충의 값을 신속하게 선택해야 하는데 이럴 때 스크롤 바가 적합하다.
→ 스크롤 바는 "scrollbar" 윈도우 클래스로 생성하며 수평 스크롤 바인 경우 SBS_HORZ 스타일을, 수직 스크롤 바인 경우는 SBS_VERT 스타일을 지정한다.
→ 두 번재 인수 nBar는 메인 윈도우에 부착된 표준 스크롤 바 또는 별도의 스크롤 바 컨트롤을 지정하는데 이 값이 SB_CTL이면 별도의 컨트롤을 지정한다.
→ SetScrollPos는 스크롤 바의 현재 위치를 세 번재 인수 nPos로 지정한다.
→ 다른 컨트롤들은 자신에게 변화가 있을 때 부모 윈도우로 WM_COMMAND 통지 메시지를 보내는데 비해 스크롤 바는 WM_HSCROLL)수평인 경우), WM_VSCROLL(수직인 경우)이라는 별도의 메시지를 부모 윈도우로 보낸다.
→ 이 메시지들은 단순한 사건의 발생뿐만 아니라 스크롤 상태에 대한 다음과 같은 추가 정보를 보내야 하는데 WM_COMMAND의 파라미터는 이미 용도가 예약되어 있으므로 이 정보를 보낼 수 없다.
→ LOWORD(wParam)으로 전달되는 값은 사용자의 스크롤 요구사항을 나타낸다.
→ 수평 스크롤 바를 예로 들어 사용자가 클릭한 부분과 이때 전달되는 메시지를 보면 다음과 같다. 양끝의 버튼을 누르는 것은 비교적 작은 단위(예를 들어 한 줄씩)로 섬세하가 이동하라는 명령이며 몸통 부분을 클릭하는 것은 비교적 큰 단위(예를 들어 한 페이지씩)로 이동하라는 명령이다.
→ 또한 수평 스크롤바는 왼쪽, 오른쪽으로 스크롤되지만 수직 스크롤바는 위, 아래로 스크롤되는데 이때 수평의 왼쪽 이동과 수직의 위쪽 이동은 둘다 값을 감소시키는 점에서 동일하다. 그래서 SB_LINELEFT와 SB_LINEUP은 같은 의미라고 할 수 있다.
→ 예제
스크롤 바 새 개를 사용하여 R, G, B 값을 입력받아 브러시를 만든 후 사각형을 그린다.
→ 메인 윈도우는 스크롤 바가 WM_HSCROLL 메시지를 보내올 때 사용자가 스크롤 바의 어디를 눌렀는지 LOWORD(wParam) 값에 따라 색상값을 적당히 증감시키는데 SB_LINE* 메시지일 경우 1씩 증감시키고 SB_PAGE*일 경우는 19씩 증감시켰다.
→ 증감된 값의 결과는 Red, Green, Blue 전역변수에 대입되며 이 값이 변경될 때마다 작업영역을 무효화하여 다시 그린다. WM_PAINT 메시지에서는 전역변수 Red, Green, Blue 값을 혼합하여 단색의 브러시를 만들고 사각형을 그림으로써 스크롤 바로 선택한 색상값을 출력한다.
→ 색상이란 세 요소의 적당한 종합으로 만들어지므로 이 값들을 빠르게 선택할 때는 스크롤 바가 가장 편리하다.
→ 빨간색 강도 얼마, 파란색은 얼마 하는 식으로 드래그 해서 원하는 색을 빨리 선택할 수 있고 결과를 금방 볼 수 있다.
→ 만약 각 요소에 대해 정확한 수치를 입력하여 색상을 만들고 싶다면 이때는 스크롤 바보다는 에디트 컨트롤을 사용해야 한다.
→
int TempPos; // 를 전역변수로 둔다면
// 아래의 코드는 필요 없다.
if((HWND)lParam == hRed)
{
TempPos = Red;
}
if((HWND)lParam == hGreen)
{
TempPos = Green;
}
if((HWND)lParam == hBlue)
{
TempPos = Blue;
}
→ 윈도우의 스크롤 상태를 관리하기 위해 사용하기도 하며 일정 범위에 있는 값을 대충 선택할 때도 사용한다.
→ 예로 사운드 볼륨이나 당구 게임의 힘 세기를 선택할 때 등에는 수치로 된 정확한 값보다는 대충의 값을 신속하게 선택해야 하는데 이럴 때 스크롤 바가 적합하다.
→ 스크롤 바는 "scrollbar" 윈도우 클래스로 생성하며 수평 스크롤 바인 경우 SBS_HORZ 스타일을, 수직 스크롤 바인 경우는 SBS_VERT 스타일을 지정한다.
BOOL SetScrollRange(HWND hWnd, int nBar, int nMinPos, int nMaxPos, BOOL bRedraw);
int SetScrollPos(HWND hWnd, int nBar, int nPos, BOOL bRedraw);
→ SetScrollRange 함수로 최대값(nMaxPos), 최소값(nMinPos)을 지정하되 첫 번째 인수가 스크롤 바의 윈도우 핸들이다.int SetScrollPos(HWND hWnd, int nBar, int nPos, BOOL bRedraw);
→ 두 번재 인수 nBar는 메인 윈도우에 부착된 표준 스크롤 바 또는 별도의 스크롤 바 컨트롤을 지정하는데 이 값이 SB_CTL이면 별도의 컨트롤을 지정한다.
→ SetScrollPos는 스크롤 바의 현재 위치를 세 번재 인수 nPos로 지정한다.
→ 다른 컨트롤들은 자신에게 변화가 있을 때 부모 윈도우로 WM_COMMAND 통지 메시지를 보내는데 비해 스크롤 바는 WM_HSCROLL)수평인 경우), WM_VSCROLL(수직인 경우)이라는 별도의 메시지를 부모 윈도우로 보낸다.
→ 이 메시지들은 단순한 사건의 발생뿐만 아니라 스크롤 상태에 대한 다음과 같은 추가 정보를 보내야 하는데 WM_COMMAND의 파라미터는 이미 용도가 예약되어 있으므로 이 정보를 보낼 수 없다.
인수 | 설명 |
LOWORD(wParam) | 스크롤 바 내의 어디를 눌렀는가. |
HIWORD(wParam) | 현재 위치 |
lParam | 스크롤 바의 윈도우 핸들 |
→ LOWORD(wParam)으로 전달되는 값은 사용자의 스크롤 요구사항을 나타낸다.
→ 수평 스크롤 바를 예로 들어 사용자가 클릭한 부분과 이때 전달되는 메시지를 보면 다음과 같다. 양끝의 버튼을 누르는 것은 비교적 작은 단위(예를 들어 한 줄씩)로 섬세하가 이동하라는 명령이며 몸통 부분을 클릭하는 것은 비교적 큰 단위(예를 들어 한 페이지씩)로 이동하라는 명령이다.
→ 또한 수평 스크롤바는 왼쪽, 오른쪽으로 스크롤되지만 수직 스크롤바는 위, 아래로 스크롤되는데 이때 수평의 왼쪽 이동과 수직의 위쪽 이동은 둘다 값을 감소시키는 점에서 동일하다. 그래서 SB_LINELEFT와 SB_LINEUP은 같은 의미라고 할 수 있다.
→ 예제
스크롤 바 새 개를 사용하여 R, G, B 값을 입력받아 브러시를 만든 후 사각형을 그린다.
#include "MsgProc.h"
#define ID_SCRRED 100
#define ID_SCRGREEN 101
#define ID_SCRBLUE 102
HWND hRed, hGreen, hBlue;
int Red, Green, Blue; // 전역변수이므로 0으로 초기화
LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
hRed = CreateWindow(TEXT("scrollbar"), NULL, WS_CHILD|WS_VISIBLE|SBS_HORZ,
10, 10, 400, 20, hWnd, (HMENU)ID_SCRRED, g_hInst, NULL);
hGreen = CreateWindow(TEXT("scrollbar"), NULL, WS_CHILD|WS_VISIBLE|SBS_HORZ,
10, 40, 400, 20, hWnd, (HMENU)ID_SCRGREEN, g_hInst, NULL);
hBlue = CreateWindow(TEXT("scrollbar"), NULL, WS_CHILD|WS_VISIBLE|SBS_HORZ,
10, 70, 400, 20, hWnd, (HMENU)ID_SCRBLUE, g_hInst, NULL);
SetScrollRange(hRed, SB_CTL, 0, 255, TRUE);
SetScrollPos(hRed, SB_CTL, 0, TRUE);
SetScrollRange(hGreen, SB_CTL, 0, 255, TRUE);
SetScrollPos(hGreen, SB_CTL, 0, TRUE);
SetScrollRange(hBlue, SB_CTL, 0, 255, TRUE);
SetScrollPos(hBlue, SB_CTL, 0, TRUE);
return 0;
}
LRESULT OnHscroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
int TempPos;
// TempPos의 초기화
if((HWND)lParam == hRed)
{
TempPos = Red;
}
if((HWND)lParam == hGreen)
{
TempPos = Green;
}
if((HWND)lParam == hBlue)
{
TempPos = Blue;
}
switch(LOWORD(wParam))
{
case SB_LINELEFT:
TempPos = max(0, TempPos-1); // 둘 중에 큰 값을 TempPos에 대입한다.
break;
case SB_LINERIGHT:
TempPos = min(255, TempPos+1);// 둘 중에 작은 값을 TempPos에 대입한다.
break;
case SB_PAGELEFT:
TempPos = max(0, TempPos -10);
break;
case SB_PAGERIGHT:
TempPos = min(255, TempPos+10);
break;
case SB_THUMBTRACK:
TempPos = HIWORD(wParam);
break;
}
if((HWND)lParam == hRed)
{
Red = TempPos;
}
if((HWND)lParam == hGreen)
{
Green = TempPos;
}
if((HWND)lParam == hBlue)
{
Blue = TempPos;
}
SetScrollPos((HWND)lParam, SB_CTL, TempPos, TRUE);
InvalidateRect(hWnd, NULL, FALSE);
return 0;
}
LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH MyBrush, OldBrush;
hdc = BeginPaint(hWnd, &ps);
MyBrush = CreateSolidBrush(RGB(Red, Green, Blue));
OldBrush = (HBRUSH)SelectObject(hdc, MyBrush);
Rectangle(hdc, 10, 100, 410, 300);
SelectObject(hdc, OldBrush);
DeleteObject(MyBrush);
EndPaint(hWnd, &ps);
return 0;
}
LRESULT OnDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
PostQuitMessage(0);
return 0;
}
→ 스크롤 바를 드래그하여 이동하면 아래쪽 사각형의 색상이 변경된다.
→ WM_CREAT에서 세 개의 수평 스크롤 바를 만들고 범위를 각각 0~255까지 지정하였다. 색상 요소값은 1바이트이기 때문에 최대값은 155이면 된다. 이 수평 스크롤 바는 사용자가 자신을 드래그하거나 클릭할 때 부모 인도우로 WM_HSCROLL 메시지를 보낼 것이다.#define ID_SCRRED 100
#define ID_SCRGREEN 101
#define ID_SCRBLUE 102
HWND hRed, hGreen, hBlue;
int Red, Green, Blue; // 전역변수이므로 0으로 초기화
LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
hRed = CreateWindow(TEXT("scrollbar"), NULL, WS_CHILD|WS_VISIBLE|SBS_HORZ,
10, 10, 400, 20, hWnd, (HMENU)ID_SCRRED, g_hInst, NULL);
hGreen = CreateWindow(TEXT("scrollbar"), NULL, WS_CHILD|WS_VISIBLE|SBS_HORZ,
10, 40, 400, 20, hWnd, (HMENU)ID_SCRGREEN, g_hInst, NULL);
hBlue = CreateWindow(TEXT("scrollbar"), NULL, WS_CHILD|WS_VISIBLE|SBS_HORZ,
10, 70, 400, 20, hWnd, (HMENU)ID_SCRBLUE, g_hInst, NULL);
SetScrollRange(hRed, SB_CTL, 0, 255, TRUE);
SetScrollPos(hRed, SB_CTL, 0, TRUE);
SetScrollRange(hGreen, SB_CTL, 0, 255, TRUE);
SetScrollPos(hGreen, SB_CTL, 0, TRUE);
SetScrollRange(hBlue, SB_CTL, 0, 255, TRUE);
SetScrollPos(hBlue, SB_CTL, 0, TRUE);
return 0;
}
LRESULT OnHscroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
int TempPos;
// TempPos의 초기화
if((HWND)lParam == hRed)
{
TempPos = Red;
}
if((HWND)lParam == hGreen)
{
TempPos = Green;
}
if((HWND)lParam == hBlue)
{
TempPos = Blue;
}
switch(LOWORD(wParam))
{
case SB_LINELEFT:
TempPos = max(0, TempPos-1); // 둘 중에 큰 값을 TempPos에 대입한다.
break;
case SB_LINERIGHT:
TempPos = min(255, TempPos+1);// 둘 중에 작은 값을 TempPos에 대입한다.
break;
case SB_PAGELEFT:
TempPos = max(0, TempPos -10);
break;
case SB_PAGERIGHT:
TempPos = min(255, TempPos+10);
break;
case SB_THUMBTRACK:
TempPos = HIWORD(wParam);
break;
}
if((HWND)lParam == hRed)
{
Red = TempPos;
}
if((HWND)lParam == hGreen)
{
Green = TempPos;
}
if((HWND)lParam == hBlue)
{
Blue = TempPos;
}
SetScrollPos((HWND)lParam, SB_CTL, TempPos, TRUE);
InvalidateRect(hWnd, NULL, FALSE);
return 0;
}
LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH MyBrush, OldBrush;
hdc = BeginPaint(hWnd, &ps);
MyBrush = CreateSolidBrush(RGB(Red, Green, Blue));
OldBrush = (HBRUSH)SelectObject(hdc, MyBrush);
Rectangle(hdc, 10, 100, 410, 300);
SelectObject(hdc, OldBrush);
DeleteObject(MyBrush);
EndPaint(hWnd, &ps);
return 0;
}
LRESULT OnDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
PostQuitMessage(0);
return 0;
}
→ 메인 윈도우는 스크롤 바가 WM_HSCROLL 메시지를 보내올 때 사용자가 스크롤 바의 어디를 눌렀는지 LOWORD(wParam) 값에 따라 색상값을 적당히 증감시키는데 SB_LINE* 메시지일 경우 1씩 증감시키고 SB_PAGE*일 경우는 19씩 증감시켰다.
→ 증감된 값의 결과는 Red, Green, Blue 전역변수에 대입되며 이 값이 변경될 때마다 작업영역을 무효화하여 다시 그린다. WM_PAINT 메시지에서는 전역변수 Red, Green, Blue 값을 혼합하여 단색의 브러시를 만들고 사각형을 그림으로써 스크롤 바로 선택한 색상값을 출력한다.
→ 색상이란 세 요소의 적당한 종합으로 만들어지므로 이 값들을 빠르게 선택할 때는 스크롤 바가 가장 편리하다.
→ 빨간색 강도 얼마, 파란색은 얼마 하는 식으로 드래그 해서 원하는 색을 빨리 선택할 수 있고 결과를 금방 볼 수 있다.
→ 만약 각 요소에 대해 정확한 수치를 입력하여 색상을 만들고 싶다면 이때는 스크롤 바보다는 에디트 컨트롤을 사용해야 한다.
→
int TempPos; // 를 전역변수로 둔다면
// 아래의 코드는 필요 없다.
if((HWND)lParam == hRed)
{
TempPos = Red;
}
if((HWND)lParam == hGreen)
{
TempPos = Green;
}
if((HWND)lParam == hBlue)
{
TempPos = Blue;
}
'내장형 하드웨어 > WINAPI' 카테고리의 다른 글
WINAPI - 컨트롤과의 통신 (0) | 2011.09.28 |
---|---|
WINAPI - 대화상자 (0) | 2011.09.27 |
WINAPI - EDIT (1) | 2011.09.23 |
WINAPI - Static (1) | 2011.09.22 |
WINAPI - 라디오 버튼 (0) | 2011.09.21 |