Programming Language/Windows API

도형 자동이동

D4tai1 2018. 9. 30.

1. 상하좌우버튼으로 원 자동이동

[1] 상하좌우 중 하나의 버튼이 한 번 눌렸을 때 그 방향으로 1초마다 20씩 이동한다.

[2] 이동할 때마다 원의 색상이 랜덤하게 변경된다.

[3] 동작 시 버튼을 누르면 원이 멈추고, 멈춘상태에서 버튼을 누르면 다시 이동한다.

 

2. 소스

1) 사용자 정의함수

#include<time.h>

void my_init(HDC hdc, HBRUSH *hBrush, int *x, int *y) {
	srand(time(NULL));
	
	int a = (rand() % 1000 + *x*100) % 256;
	int b = (rand() % 10000 + *x * 100) % 256;
	int c = (rand() % 5000 + *x * 100) % 256;
	
	SelectObject(hdc, CreateSolidBrush(RGB(a, b, c)));
	//원의 색상을 부여하기 위해 랜덤값 사용. 
	//RGB는 0~255사이의 3개의 숫자값을 입력하면 해당하는 색상을 반환

	Ellipse(hdc, *x - 30, *y - 30, *x + 30, *y + 30);
	//원 그리기
}

 

2) 윈도우 메세지 처리함수

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static int x;
	static int y;
	//원의 좌표

	static RECT rect;
	//화면 전체 영역의 좌표를 저장하는 구조체

	static RECT rt;

	static BOOL flag[5];
	//1~4의 인덱스를 사용하여 방향키를 지정

	static HBRUSH hBrush;
	//원의 색상을 저장

    switch (message)
    {
	case WM_CREATE:
	{
		x = 100;
		y = 100;
		//초기 원의 좌표.

		GetClientRect(hWnd, &rect);
		//프로그램 실행시 실행창의 영역의 좌표를 rect구조체에 저장한다.

		for (int i = 0; i < sizeof(flag); i++) {
			flag[i] = FALSE;
		}
		//상하좌우 4개의 방향키 모두 FALSE
	}
	break;

	case WM_KEYDOWN:
		//입력된 키 중에
	{
		if (wParam == VK_UP) {
			//위 방향키가 입력되었다면?
			if (!flag[1]) {
				//동작하지 않는상태면?
				SetTimer(hWnd, 1 1000, NULL);
				//타이머번호 1번 = 1초에 1번씩 WM_TIMER발생
				flag[1] = TRUE;
				//눌렸다.
			}
			else {
				//이미 동작하고 있는 상태면?
				KillTimer(hWnd, 1);
				//타이머번호 1번 = 삭제
				flag[1] = FALSE;
				//동작하지 않는 상태로 변경
			}
			
		}
		else if (wParam == VK_DOWN) {
			if (!flag[2]) {
				SetTimer(hWnd, 2, 1000, NULL);
				flag[2] = TRUE;
			}
			else {
				KillTimer(hWnd, 2);
				flag[2] = FALSE;
			}
		}
		else if (wParam == VK_LEFT) {
			if (!flag[3]) {
				SetTimer(hWnd, 3, 1000, NULL);
				flag[3] = TRUE;
			}
			else {
				KillTimer(hWnd, 3);
				flag[3] = FALSE;
			}
		}
		else if (wParam == VK_RIGHT) {
			if (!flag[4]) {
				SetTimer(hWnd, 4, 1000, NULL);
				flag[4] = TRUE;
			}
			else {
				KillTimer(hWnd, 4);
				flag[4] = FALSE;
			}
		}
	}
	break;

	case WM_TIMER:
	{
		rt.left = x - 50;
		rt.right = x + 50;
		rt.top = y - 50;
		rt.bottom = y + 50;
		//rt구조체 영역 표시

		switch (wParam) {
		case 1:
			y -= 20;
			//위 키가 눌렸다면 위로 20 증가
			InvalidateRect(hWnd, &rt, TRUE);
		break;

		case 2:
			y += 20;
			//아래 키가 눌렸다면 아래로 20 증가
			InvalidateRect(hWnd, &rt, TRUE);
		break;

		case 3:
			x -= 20;
			//왼쪽 키가 눌렸다면 좌측으로 20 증가
			InvalidateRect(hWnd, &rt, TRUE);
		break;

		case 4 :
			x += 20;
			//오른쪽 키가 눌렸다면 우측으로 20 증가
			//InvalidateRgn(hWnd, NULL, TRUE);  인발리업데이트리전
			InvalidateRect(hWnd, &rt, TRUE);
			// &rt 사각형구조체 영역만 무효화
		}
		break;
	}
	break;

    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 메뉴 선택을 구문 분석합니다:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
			
			my_init(hdc, &hBrush, &x, &y);
			//처음 초기화한 함수와 비슷하므로 같이 사용
			//PAINT메세지 발생 시 색상에 따른 원 그리기

            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

 

3. 시연

- 아래버튼과 우측버튼을 동시에 누르면 대각선으로 이동하는 것도 확인할 수 있다.

 

'Programming Language > Windows API' 카테고리의 다른 글

입력된 방향키 확인  (0) 2018.09.30
사각형 그리기  (0) 2018.09.30
마우스로 도형 옮기기  (0) 2018.09.30
keyboard[마지막]  (0) 2018.09.10
shape  (0) 2018.08.27

댓글