ScrollWindow

원형

BOOL ScrollWindow(HWND hWnd, int XAmount, int YAmount, CONST RECT *lpRect, CONST RECT *lpClipRect);

MFC 원형

void CWnd::ScrollWindow( int xAmount, int yAmount, LPCRECT lpRect = NULL, LPCRECT lpClipRect = NULL );

인수

▶hWnd : 스크롤 대상이 되는 윈도우

▶XAmount, YAmount : 수평, 수직으로 스크롤 할 값이며 장치 단위로 표현된다. 단, hWnd가 CS_OWNDC, CS_CLASSDC 스타일을 가지고 있으면 이 값은 논리 단위이다. 왼쪽이나 위로 스크롤 할 때는 음수값이 될 수도 있다.

▶lpRect : 스크롤 될 작업 영역 좌표. NULL이면 전체 작업 영역이 스크롤 된다. 작업 영역중 일부분만 스크롤시할 때는 이 인수에 스크롤 대상 영역을 지정해 주면 된다. 이 값이 NULL일 때 ScrollWindow 함수는 훨씬 더 빠르게 동작한다.

▶lpClipRect : 클리핑 영역 사각형. 이 영역 내부만 스크롤에 의해 다시 그려지며 바깥쪽은 절대로 건드리지 않으므로써 화면이 깨지는 것을 방지한다. lpRect가 작업 영역의 일부분일 때 스크롤 속도가 빠르면 lpRect 바깥으로 스크롤이 발생할 수도 있는데 클리핑 영역을 설정하면 이런 현상을 방지할 수 있다.

리턴

성공하면 0이 아닌 값을 리턴하며 실패하면 0을 리턴한다.

설명

윈도우를 스크롤시킨다. 일반적으로 이 함수는 WM_HSCROLL, WM_SCROLL 등의 스크롤 관련 메시지를 받았을 때 호출되며 스크롤 바로 스크롤 된 양만큼 작업 영역을 이동시키는 역할을 한다. 스크롤된 양만큼 작업 영역을 BitBlt 함수로 고속 복사하며 새로 드러나는 부분은 무효화시켜 WM_PAINT에서 다시 그리도록 해 준다.

만약 스크롤 영역에 캐럿이 있다면 스크롤하기 전에 캐럿을 숨기며 스크롤이 끝난 후 캐럿을 복구시켜준다. 캐럿의 위치는 자동으로 조정된다. 작업 영역의 일부부만을 스크롤시키고자 할 때는 lpRect에 스크롤 영역을 지정할 수 있으며 이때 화면의 깨짐을 방지하기 위해 클리핑 영역을 지정해 주는 것이 좋다.

예제 1

다음 예제는 1000*1000크기의 윈도우에 동심원을 그리고 스크롤 바로 이 동심원을 스크롤하도록 한다.

int yPos,xPos;
int yMax,xMax;
COLORREF col[5]={RGB(255,0,0),RGB(0,255,0),RGB(0,0,255),RGB(255,0,255),RGB(255,255,0)};
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	int i,j;
	HDC hdc;
	PAINTSTRUCT ps;
	int xInc, yInc;
	SCROLLINFO si;
	HBRUSH hBrush,OldBrush;

	switch(iMessage) {
	case WM_CREATE:
		xPos=0;
		yPos=0;
		xMax=1000;
		yMax=1000;
		return 0;
	case WM_SIZE:
		si.cbSize=sizeof(SCROLLINFO);
		si.fMask=SIF_ALL | SIF_DISABLENOSCROLL;
		si.nMin=0;
		si.nMax=1000;
		si.nPage=HIWORD(lParam);
		si.nPos=yPos;
		SetScrollInfo(hWnd, SB_VERT, &si, TRUE);

		si.nPage=LOWORD(lParam);
		si.nPos=xPos;
		SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
		return 0;
	case WM_HSCROLL:
		xInc=0;
		switch (LOWORD(wParam)) {
		case SB_LINEUP:
			xInc=-1;
			break;
		case SB_LINEDOWN:
			xInc=1;
			break;
		case SB_PAGEUP:
			xInc=-20;
			break;
		case SB_PAGEDOWN:
			xInc=20;
			break;
		case SB_THUMBTRACK:
			xInc=HIWORD(wParam)-xPos;
			break;
		default:
			break;
		}
		// 새로운 위치는 최소한 0 이상
		if (xPos+xInc < 0)
			xInc=-xPos;
		// 새로운 위치는 최대한 xMax 이하
		if (xPos+xInc > xMax)
			xInc=xMax-xPos;
		// 새로운 위치 계산
		xPos=xPos+xInc;
		// 스크롤시키고 썸 위치를 다시 계산한다.
		ScrollWindow(hWnd, -xInc, 0, NULL, NULL);
		SetScrollPos(hWnd, SB_HORZ, xPos, TRUE);
		return 0;
	case WM_VSCROLL:
		yInc=0;
		switch (LOWORD(wParam)) {
		case SB_LINEUP:
			yInc=-1;
			break;
		case SB_LINEDOWN:
			yInc=1;
			break;
		case SB_PAGEUP:
			yInc=-20;
			break;
		case SB_PAGEDOWN:
			yInc=20;
			break;
		case SB_THUMBTRACK:
			yInc=HIWORD(wParam)-yPos;
			break;
		default:
			break;
		}
		// 새로운 위치는 최소한 0 이상
		if (yPos+yInc < 0)
			yInc=-yPos;
		// 새로운 위치는 최대한 yMax 이하
		if (yPos+yInc > yMax)
			yInc=yMax-yPos;
		// yInc=max(-yPos, min(yInc, yMax-yPos));
		// 새로운 위치 계산
		yPos=yPos+yInc;
		// 스크롤시키고 썸 위치를 다시 계산한다.
		ScrollWindow(hWnd, 0, -yInc, NULL, NULL);
		SetScrollPos(hWnd, SB_VERT, yPos, TRUE);
		return 0;
	case WM_PAINT:
		hdc=BeginPaint(hWnd, &ps);
		for (i=500,j=0;i>=100;i-=100,j++) {
			hBrush=CreateSolidBrush(col[j]);
			OldBrush=(HBRUSH)SelectObject(hdc,hBrush);
			Ellipse(hdc,500-i-xPos,500-i-yPos,500+i-xPos,500+i-yPos);
			DeleteObject(SelectObject(hdc,OldBrush));
		}
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

WM_H(V)SCROLL 메시지를 받았을 때 스크롤 바의 스크롤 된 양만큼 해당 윈도우를 수평, 수직으로 각각 스크롤시켰다. 작업 영역 전체를 스크롤시키므로 lpRect는 NULL이며 클리핑 영역도 설정할 필요가 없다.

참고함수

SetScrollInfo, ScrollWindowEx

플랫폼

95이상

참조

 


written by http://www.winapi.co.kr