WinAPI: 타이머

 메시지는 사용자의 동작으로부터 유발되는 것이 보통이지만 사용자의 동작과는 상관없이 발생하는 메시지도 있습니다. 대표적으로 타이머 메시지인 WM_TIMER를 들 수 있습니다.

 WM_TIMER 메시지는 한 번 지정해 놓으면 일정한 시간간격을 두고 연속적으로 계속 발생할 수 있습니다. 주기적으로 같은 동작을 반복해야 한다거나 여러번 나누어 해야 할 일이 있을 때 이 메시지를 사용합니다.

다음은 타이머 메시지를 이용한 간단한 시계 프로그램의 WndProc입니다.
#include <time.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    time_t mytime;
    static HANDLE hTimer;
    static const char *str;

    switch(iMessage)
    {
    case WM_CREATE:
        hTimer=(HANDLE)SetTimer(hWnd,1,1000,NULL);
        str="";
        return 0;

    case WM_TIMER:
        time(&mytime);
        str=ctime(&mytime);
        InvalidateRect(hWnd, NULL, true);
        return 0;

    case WM_PAINT:
        hdc=BeginPaint(hWnd, &ps);
        TextOut(hdc, 100, 100, str, strlen(str)-1);
        EndPaint(hWnd, &ps);
        return 0;

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

 시간과 관련된 함수를 사용하므로 time.h를 포함시켜 두었습니다. WndProc에는 시간값을 저장할 time_t형의 변수 mytime과 시간값을 문자열로 변경하여 저장할 str, 타이머 핸들인 hTimer 세 개의 변수가 사용되었습니다.

 WM_CREATE 메시지는 윈도우가 처음 발생될 때 한 번 초기화하는 처리를 합니다. 위 프로그램에서는 SetTimer 함수를 사용하여 타이머를 생성시켰습니다.

UINT SetTimer(HWND hWnd, UINT nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);

 hWnd 인수는 타이머 메시지를 받을 윈도우입니다. nIDEvent는 타이머의 번호를 지정합니다. 여러 개의 타이머를 사용할 경우 nIDEvent에 겹치지 않도록 번호를 부여하도록 합니다. 세 번째 인수 uElapse는 1/1000초 단위로 타이머의 주기를 설정합니다. 이 값이 1000이면 1초에 한번씩 타이머 메시지가 hWnd로 보내지게 될 것입니다. 네 번째 인수 lpTimerFunc는 타이머 메시지가 발생할 때마다 호출될 함수를 지정하는데 사용하지 않을 경우 NULL로 설정합니다.


 WM_TIMER 메시지는 wParam으로 타이머 ID를 전달받으며 lParam으로 타이머 메시지 발생시 호출될 함수의 번지가 전달됩니다. 이 예제에서는 time 함수로 시간을 조사한 후 ctime 함수로 문자열로 바꾼 후 문자열 str에 저장해 둡니다.

time_t time(time_t *timer); char *ctime(const time_t *timer);

time 함수는 1970년 1월 1일 자정 이후 경과한 초를 반환합니다.

bool KillTimer(HWND hWnd, UINT uIDEvent);

 타이머는 시스템 전역 자원이므로 윈도우가 파괴되더라도 파괴되지 않고 계속 남아있게 됩니다. 그래서 타이머는 직접적으로 파괴해야 하는데 그 때에 이 함수를 씁니다.

 첫 번째 인수는 타이머를 소유한 윈도우 핸들을 넘겨주며 두 번째 인수로는 타이머 ID를 넘겨줍니다. SetTimer의 반환값은 타이머를 소유하는 윈도우 없이 타이머가 만들어졌을 경우에 한해 특별히 사용합니다.

댓글