Notice
Recent Posts
관리 메뉴

Hacking Arts

타이머 본문

Programing/API Programing

타이머

Rakehell 2014. 10. 11. 00:37

- 타이머 메시지란 알람과 같이 1초, 1분 등의 일정 시간이 되었을 때마다 임의의 어떤 작업을 수행하도록 해준다.


[ 그림 1 SetTimer 정의 ]

- 인자 값으로 윈도우 핸들 , 그리고 타이머 식별 번호가 들어가게 되는데 여러개의 타이머를 사용 할 수 있기 때문이다. 그 다음 인자값이 시간 주기이다. msec 단위라서 10000 값이 1분을 뜻한다. 그리고 그다음 콜백 함수 인자 값이 들어가게 된다. 아래 그림 과 같은 과정을 거친다.

[ 그림 2 타이머 단계 ]

[ 그림 3 타이머 구현 ]

- 아래 소스를 이용해서 위 타이머를 구현 할 수 있다

#include
#include
#include
#pragma warning(disable:4996)

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPWSTR lpszClass = (LPWSTR)"OutPut";

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
	HWND hWnd;
	MSG Message;
	WNDCLASS WndClass;
	g_hInst = hInstance;

	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hInstance = hInstance;
	WndClass.lpfnWndProc = (WNDPROC)WndProc;
	WndClass.lpszClassName = (LPCSTR)lpszClass;
	WndClass.lpszMenuName = NULL;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;

	RegisterClass(&WndClass);

	hWnd = CreateWindow((LPCSTR)lpszClass, (LPCSTR)lpszClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);

	ShowWindow(hWnd, nCmdShow);

	while (GetMessage(&Message, 0, 0, 0)){
		TranslateMessage(&Message);
		DispatchMessage(&Message);
	}

	return Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	static char curTime[10];
	static RECT rt = { 100, 100, 400, 120 };
	HDC hdc;
	PAINTSTRUCT ps;

	switch (iMessage)
	{
	case WM_CREATE:
		SetTimer(hWnd, 1, 1000, NULL);
		return 0;
	case WM_TIMER:
		_strtime(curTime);
		InvalidateRect(hWnd, &rt, TRUE);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		TextOut(hdc, 100, 100, curTime, strlen(curTime));
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		KillTimer(hWnd, 1);
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
- 이런식으로 생성하면 타이머를 2개도 사용가능 하다.

-콜백 함수란? 응용 프로그램에 정의 되어 있는 함수를 운영체제가 필요할 때 호출하는 함수이다. 콜백 함수는 응용 프로그램 내에서 호출할 수 없고, 반드시 운영체제만이 호출할 수 있다. 그렇다면 왜 운영체제가 호출해야만 하는가? 자원의 독점을 막기 위해서라고 할 수 있다. 즉 콜백 함수의 사용 효과는 자원의 독점을 막고 수행 처리 속도의 향상을 가져온다.

[ 그림 4 콜백 함수 ]

- 왜 타이머는 콜백 함수를 사용하는가? 만약 타이머가 0.1초 분기마다 실행되고 여러개가 실행된다면 타이머도 메시지가 발생하기때문에 메시지 큐에 병목현상이 일어날 수 있다. 즉 여러개의 짧은 주기의 타이머를 정확하게 동작시키기 위해 콜백함수를 사용하게 된 것이다.

[ 그림 5 콜백 함수 구현]

- 아래 소스를 통해서 그림 5를 구현할 수 있다. 랜덤한 크기의 사각형과 원을 출력시키고 있다.

#include
#include
#include
#pragma warning(disable:4996)

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
HINSTANCE g_hInst;
LPWSTR lpszClass = (LPWSTR)"OutPut";

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
	HWND hWnd;
	MSG Message;
	WNDCLASS WndClass;
	g_hInst = hInstance;

	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hInstance = hInstance;
	WndClass.lpfnWndProc = (WNDPROC)WndProc;
	WndClass.lpszClassName = (LPCSTR)lpszClass;
	WndClass.lpszMenuName = NULL;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;

	RegisterClass(&WndClass);

	hWnd = CreateWindow((LPCSTR)lpszClass, (LPCSTR)lpszClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);

	ShowWindow(hWnd, nCmdShow);

	while (GetMessage(&Message, 0, 0, 0)){
		TranslateMessage(&Message);
		DispatchMessage(&Message);
	}

	return Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	static char curTime[10];
	static RECT rt = { 100, 100, 400, 120 };
	HDC hdc;
	PAINTSTRUCT ps;

	switch (iMessage)
	{
	case WM_CREATE:
		SetTimer(hWnd, 1, 1000, (TIMERPROC)TimerProc);
		return 0;
	case WM_DESTROY:
		KillTimer(hWnd, 1);
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

void CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
	HDC hdc;
	hdc = GetDC(hWnd);
	Rectangle(hdc, rand() % 500, rand() % 500, rand() % 500, rand() % 500);
	Ellipse(hdc, rand() % 500, rand() % 500, rand() % 500, rand() % 500);
	ReleaseDC(hWnd,hdc);
}

-참고 자료

API Programing / 이창현 / 혜지원

'Programing > API Programing' 카테고리의 다른 글

resource (icon/cursor)  (0) 2014.11.04
키보드 입력  (0) 2014.10.10
마우스 입력  (0) 2014.10.10
문자열 / 점 / 선 / 사각형 / 원 / 다각형 / 메시지 박스  (0) 2014.10.10
출력 / GDI / DC  (0) 2014.10.10