[windowsAPI] 3주차(1), Timer와 Random다루기

교내 전공과목인 윈도우즈 API수업을 정리합니다

 

 

 

 

1. Timer을 알아보자.

(1) 코드소스

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	SYSTEMTIME st;
	static TCHAR sTime[128];
	static RECT rt={100,100,400,120};

	switch (iMessage) {
	case WM_CREATE: //window를 켰을 때 한 번 나타남. (p.99)
		SetTimer(hWnd,1,1000,NULL); // (1) SetTime(윈도우핸들, 타이머 번호, 메시지 생성간격, 보통 NULL지정)
//		SendMessage(hWnd, WM_TIMER, 1, 0);
		return 0;
	case WM_TIMER:
		GetLocalTime(&st); //시스템에서 현재시간 알아오기, &왜 붙이는지 알아오기
		wsprintf(sTime,TEXT("지금 시간은 %d:%d:%d입니다"),   //sTime = buffer, %d= format(정수), 
			st.wHour,st.wMinute,st.wSecond);
		InvalidateRect(hWnd,NULL,FALSE); // TRUE를 FALSE로 바꿔보는 것도 괜츈 
//		InvalidateRect(hWnd,&rt,TRUE);
		return 0;
	case WM_PAINT:
		hdc=BeginPaint(hWnd,&ps);
		TextOut(hdc,100,100,sTime,lstrlen(sTime));
		EndPaint(hWnd,&ps);
		return 0;
	case WM_DESTROY:
		KillTimer(hWnd,1);
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
  • SetTimer(HWND hWnd, int nIDEvent,WORD wElapse,FARPROC lpTimerFunc) 
    hWnd: 메시지를 받을 윈도우 핸들
    nIDEvent: 타이머의 번호(여러개 생길 수도 있는 타이머의 구분)
    wElapse: 메시지가 생성될 시간 간격(1/1000초 단위)
    lpTimerFunc: 보통 NULL값으로 지정, WM_TIMER메시지를 WndProc에 전달되도록 함

  • SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
    Msg: 전달할 메시지
    wParam: 메시지 추가 정보, 메시지에 따라 의미 달라짐
    lParam: 메시지 추가 정보

  • GetLocalTime(LPSYSTEMTIME lpSystemTime);
    lpSystemTime: 현재 로컬 시간을 대입받을 SYSTEMTIME 구조체

  • InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase)
    lpRect: 무효화할 영역, NULL이면 작업 영역 전체가 무효화 됨
    bErase: 무효 영역의 배경을 먼저 지울 것인가를 지정, True면 함수가 배경은 먼저 지우고 작업 영역을 그림)
    * 무효화영역: 윈도우의 화면의 일부가 변경되어 다시 그려져야 할 부분

  • TextOut(HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString);
    nXStart: X좌표
    nYStart: Y좌표
    lpString: 출력할 문자열
    cbString: 문자열의 길이, 반들시 길이를 밝혀 주어야 함 (null인식 불가)

  • KillTimer(HWND hWnd, UINT_PTR uIDEvent);
    uIDEvent: 삭제할 타이머의 ID, SetTimer의 ID와 일치해야 함.

  • PostQuitMessage(int nExitCode);
    nExitCode: 종료코드, 보통 0으로 전달함.메인 윈도우 파괴시 응용 프로그램 종료 역할 


(2) 실행모습

1초단위로 현재 시간을 출력하는 윈도우가 만들어진다.

 

 

2.  TIMER을 이용하여 문자열이 (수직방향) 움직이도록 만들자

(1) 코드소스

int x, y;
TCHAR str[26];

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	SYSTEMTIME st;
	static RECT rect;

	switch (iMessage) {
	case WM_CREATE:
		srand((unsigned int)time(NULL)); // 랜덤 위치 설정
		GetClientRect(hWnd, &rect); // (hWnd, Rect구조체포인터), 윈도우의 작업영역 크기를 계산함
		SetTimer(hWnd, 1, 100, NULL); // 0.1초 단위로 수직방향의 위치 변환
		//	SendMessage(hWnd, WM_TIMER, 1, 0);
		str[0] = rand() % 26 + 97; // 출력할 알파벳 코드 얻기
		y = rand() % (rect.right - 40) + 20; // 출력위치의 랜덤 x좌표 얻기

		return 0;

	case WM_SIZE:
		GetClientRect(hWnd, &rect);
		return 0;

	case WM_TIMER:
		if (y >= rect.bottom){ //문자가 바닥 위치를 넘으면
			str[0] = rand() % 26 + 97; //새로운 문자 지정
			x = rand() % (rect.right - 40) + 20; //  x축(시작위치) . 40은 양 끝의 총 길이, 시작점은 20보다 커야 함.
			y = 0; // y축(시작위치)
		}
		y += 60; // 위치 하향
		InvalidateRect(hWnd, NULL, TRUE);
		return 0;

	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		TextOut(hdc, x, y, str, lstrlen(str)); // (hdc, x좌표, y좌표, 문자열, 문자열길이)
		EndPaint(hWnd, &ps);
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

 

  • GetClientRect(HWND hWnd, LPRECT lpRect);
    lpRect: 리턴값을 돌려받기 위한 RECT 구조체의 포인터
    윈도우의 작업영역 크기를 계산해준다. 좌상단값은 항상 (0, 0) 이고 우하단좌표는 (right, bottom)이 곧 윈도우의 크기가 된다. 

 

(2) 실행모습

랜덤위치에서 랜덤알파벳이 수직낙하함.

 

 

 

 

내일은 3주차-2로 타이핑 맞추기만들기.