GetMessage는 WinEvent 콜백을 실행하는 동안 받은 게시된 메시지를 무시합니다.
- 아티클
- 2023. 07. 17.
이 문서의 내용
이 문서는 콜백 함수가 GetMessage 실행되는 동안 WinEvent API가 게시된 메시지를 받지 못하는 문제를 해결하는 데 도움이 됩니다.
원래 제품 버전: Windows Server 2008, Windows 7, Windows Server 2003 R2, Windows Vista
원래 KB 번호: 2682659
증상
GetMessage 는 콜백 함수가 실행되는 동안 WinEvent 게시된 메시지를 수신하지 않는 것으로 나타납니다. 다른 메시지가 큐에 들어가면 두 메시지가 모두 수신되고 처리됩니다.
원인
알려진 문제 GetMessage 및 자체에서 Windows 메시지를 사용하는 콜백의 사용 WinEvent 이 있습니다. GetMessage 는 콜백을 실행하는 동안 수신되는 메시지를 무시합니다. 따라서 특히 콜백 함수가 호출 PostThreadMessage하는 경우 다른 메시지가 큐에 들어갈 때까지(예: 마우스 이동으로 인해) 해당 메시지가 등록되지 않습니다. 이 시점에서는 이전에 게시된 메시지와 새 메시지가 모두 등록되고 처리됩니다.
해결 방법
이 블록을 해결하려면 대신 사용하는 MsgWaitForMultipleObjectsPeekMessageGetMessage것이 좋습니다. 또한 WinEvent 처리기에서 보낼 수 있는 새 이벤트를 만들어 메시지 루프를 해제해야 합니다.
추가 정보
다음은 제네릭 메시지 루프 및 처리기를 포함하는 코드 조각입니다.WinEvent
// Main message loop of thread that called SetWinEventHook while(GetMessage(&msg, NULL, 0, 0))
{
... process message here ...
}
void CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD eventId,
HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread,
DWORD dwmsEventTime)
{
... process winevent here ...
}
GetMessage 에서 보낸 메시지를 등록하지 못한 후 위의 조각에서 WinEventProc차단할 수 있습니다. 대신 이 조각과 PeekMessage 같이 처리기에서 메시지 루프로 다시 특별한 절전 모드 해제 이벤트를 선언하고 사용하는 것과 함께 사용합니다MsgWaitForMultipleObjects.
HANDLE ghMessageReadyEvent = NULL; // Event used to wake up the main thread
ghMessageReadyEvent = CreateEvent(NULL, FALSE/*bManualReset*/,
FALSE/*bIntialState*/, NULL);
// Main message loop of thread that called SetWinEventHook
// We can't reliably use GetMessage here. If a posted message is received
// while we're in a reentrant call to WinEventProc, when the WinEventProc
// returns, GetMessage does not recognize that a message has been
// received and just blocks. To avoid this we use
// MsgWaitForMultipleObjects + PeekMessage. Code at the end of the
// WinEventProc checks if a posted message was received during the
// callback using PeekMessage; if so, it sets the event which causes
// MsgWaitForMultipleObjects to wake up.
// Note that MsgWaitForMultipleObjects usually only wakes up if a message
// is received during it. Even with QS_ALLPOSTMESSAGE, it only wakes up
// if a message is received between it and the most recent PeekMessage,
// so we have to call PeekMessage *before* calling it in case there are
// multiple queued-up messages.
for(;;)
{
BOOL fGot = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
if(!fGot)
{
MsgWaitForMultipleObjects(1, &ghMessageReadyEvent,
FALSE/*bWaitAll*/, INFINITE,
QS_ALLEVENTS | QS_ALLPOSTMESSAGE);
fGot = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
}
if(!fGot)
{
continue;
}
... process message here ...
}
void CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD eventId, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
... process winevent here ...
// Before we return, check if posted messages were received during this
// callback. If so, fire the event to ensure that we do process them.
MSG msg;
if(PeekMessage(&msg, (HWND)-1, WM_USER + 1, WM_USER + 2, PM_NOREMOVE | PM_QS_POSTMESSAGE))
{
SetEvent(ghMessageReadyEvent);
}
}
'[Microsoft]' 카테고리의 다른 글
Windows 및 Windows Server 릴리스에 대한 메모리 제한 (1) | 2023.12.06 |
---|---|
SPI_SETWORKAREA 플래그를 사용하여 SystemParametersInfo 함수를 호출하는 애플리케이션이 Windows 10 (0) | 2023.11.03 |
자음 표시가 있는 반자 및 전폭 가타카나 및 히라가나 문자는 다른 것으로 처리됩니다. (0) | 2023.11.03 |
관리자 권한으로 실행할 때 데스크톱 브리지 앱이 시작되지 않습니다. (0) | 2023.11.03 |
다중 스레드 아파트에서 셸 함수 및 인터페이스 호출 (0) | 2023.11.03 |