2013년 6월 21일 금요일

GetMessage와 PeekMessage

윈도우지 프로그램은 사용자가키보드를 두드리고 있거나 마우스를 굴리고 있지 않는 경우 대부분
GetMessage에서 다음 메시지를 기다리고 있다.
이 노는 시간에 다른 프로세스가 CPU를 쓸 수 있도록 양보하는데 GetMessage의 이런 특성 때문에
멀티 태스킹이 부드럽게 이루어지는 것이다.

만약 메시지 루프가 무한 루프를 돌며 끊임없이 메시지 큐를 감시하기만 한다면 CPU는 한없이
바쁘기만 하겠지만 GetMessage가 적당히 양보를 하기 때문에 CPU가 쉬어갈 시간이 있는 것이다.
그래서 GetMessage 함수는 멀티 태스킹의 핵심 함수이며 대부분의 응용 프로그램은 GetMessage에서 대기하면서
한가롭게 놀고 있는 셈이다.
GetMessage 함수의 주요한 세가지 특징을 요약하면 1) 제거한다. 2) 대기한다. 3) 양보한다. 로 정리할 수 있다.

이렇게 GetMessage에서 놀고 있는 시간을 데드 타임(dead time)이라고 한다.
데드 타임을 잘 활용하면 에니메이션이나 기타 틈틈이 해야 할 일을 다른 작업 시간에 영향을 주지 않고도 할 수 있다.
그런데 문제는 GetMessage 함수가 메시지를 받기 전에는 절대로 리턴하지 않기 때문에 데드 타임을 활용할 수 없다는 점이다.
이때는 GetMessage 함수를 대신 다음 함수를 사용한다.

BOOL PeekMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg );

PeekMessage는 GetMessage의 세 가지 특징과 완전히 반대되는 성질을 가지는데 메시지 큐에서 메시지를 꺼내거나
검사하되 메시지가 없더라도 즉각 리턴한다. 즉, 대기하지 않으며 따라서 양보도 할 줄 모른다. 이때 리턴값이
TRUE이면 메시지가 있다는 뜻이며 FALSE 이면 메시지가 없다는 뜻이다.

wRemoveMsg 플래그는 메시지가 있을 경우 이 메시지를 큐에서 제거할 것인가 아닌가를 지정하는데 PM_REMOVE 이면
GetMessage처럼 메시지를 큐에서 제거하지만 PM_NOREMOVE 이면 제거하지 않을 수도 있다. 즉, 슬쩍 엿보기만 하는 것이
가능한데 그래서 이름이 Peek이다. PM_NOREMOVE 플래그를 사용하면 메시지 큐에 어떤 메시지가 있는지 검사만 해 볼 수
있다. PeekMessage는 메시지가 있든 없든 즉시 리턴하므로 메시지가 없을 때 다른 일을 할 수 있다.
즉, 데드 타임을 활용할 수 있다.

PeekMessage 함수는 메시지 루프 밖에서도 사용할 수 있다. 단순히 원하는 메시지가 있는지 검사해 보는 용도로
쓸 수 있고 시간이 좀 오래 걸리는 작업중에 다른 메시지를 처리할 기회를 주기 위해 쓸수도 있다.

요약
GetMessage
메시지 큐에 메시지가 있다면 즉각 리턴, 메시지 제거
메시지가 없다면 대기(다른 프로세스가 CPU를 쓸수 있도록 양보 = 멀티 태스킹)
메시지를 받기 전에는 절대로 리턴하지 않기 때문에 데드 타임을 활용할 수 없다.(  Blocking )

PeekMessage
메시지 큐에서 메시지를 꺼내거나 검사하되 메시지가 없더라도 즉각 리턴한다.
즉, 대기하지 않으며 따라서 양보도 할 줄 모른다.
메시지가 있든 없든 즉시 리턴하므로 메시지가 없을 때 다른 일을 할 수 있다.(=데드 타임을 활용할 수 있다. = NonBlocking)

댓글 없음:

댓글 쓰기