-
[WinAPI] GetMessage와 PeekMessage의 차이개발 공부/Windows 개발 2023. 2. 12. 18:43
*공통점*
GetMessage와 PeekMessage는 Windows API에서 사용하는 메시지 관리 함수이며,
메시지 큐에 메시지가 있을 때, 메시지를 가져오는 함수이다.
*차이점*
GetMessage ;
- 메시지 큐에 메시지가 없으면 메시지가 생길 때까지 대기한다.
메시지 큐에서 메시지를 사용할 수 있을 때까지 프로그램이 차단된다. (=> Blocking)
- WM_QUIT 메시지 (프로그램 종료 메시지)가 들어오면 0을 반환한다.
PeekMessage :
- 메시지 큐에 메시지가 없으면 대기하지 않고 제어 권한이 바로 반환된다. (=> Non-blocking)
- 메시지가 없으면 0을 반환한다. 메시지가 있다면 0이 아닌 값을 반환한다.
- 메시지 큐에서 메시지를 가져오면서 그 메시지를 삭제하지 않도록 하는 옵션이 있다. `PM_NOREMOVE`
GetMessage와 동일하게 메시지 큐에서 메시지를 삭제시키려면 'PM_REMOVE' 옵션을 사용하면 된다.
번외
기본적으로 Visual Studio에서 프로젝트를 생성했을 때 메시지 처리 코드 :
while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
게임 엔진과 같이 윈도우 메시지 처리 외에 상시적으로 처리해야 할 작업이 있을 경우 :
while (true) { if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) break; if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } //TODO : 상시적으로 처리할 작업 수행 }
위의 경우, 한번 while문을 순회할 때마다 하나의 메시지만 처리할 수 있지만,
한번에 메시지 큐를 모두 처리하고 싶다면
while (true) { while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) break; if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } //TODO : 상시적으로 처리할 작업 수행 }
PeekMessage가 0을 반환할 때 까지 (=메시지 큐가 Empty 가 될 때까지) 반복하고 다음을 처리하면 된다.
해당 방법은 상황에 따라 적용하면 될 것같다.
한번에 너무 많은 양의 윈도우 메시지가 들어온다면, 메시지를 처리하는 동안 상시적으로 처리해주던 작업이 그만큼 딜레이가 생길 것이기 때문에 독이 될 수 있다.
*참고 링크*
GetMessage :
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessage
PeekMessage :
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-peekmessagea
한번의 순회마다 메시지 큐 계속 비우기 :
https://www.gamedev.net/forums/topic/296990-getmessage-vs-peekmessage/