호스트 응용 프로그램의 메시지 대기열 구현에 문제가 있다고 생각합니다. 예를 들어 단축키를 구현하는 대신 전달하는 대신 일부 메시지가 처리됩니다. 코드를 변경할 수 없으므로 메시지 대기열을 연결하는 것이 합리적인 방법으로 들립니다.
은 다음 코드 조각은 문제 및 솔루션을 모두 보여줍니다
#define WINDOW_CLASS _T("StackOverflow_41911104")
HINSTANCE g_Instance = 0;
HHOOK g_Hook = 0;
HWND g_TargetWindow = 0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
HWND CreateMainWindow()
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = g_Instance;
wcex.hIcon = nullptr;
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = nullptr;
wcex.lpszClassName = WINDOW_CLASS;
wcex.hIconSm = nullptr;
ATOM windowClass = RegisterClassExW(&wcex);
HWND mainWindow = CreateWindowW(WINDOW_CLASS, WINDOW_CLASS, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 400, 400, nullptr, nullptr, g_Instance, nullptr);
g_TargetWindow = CreateWindow(_T("Edit"), nullptr, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE, 0, 0, 300, 300, mainWindow, (HMENU)1000, g_Instance, nullptr);
return mainWindow;
}
HACCEL CreateAccelerators()
{
ACCEL acceleratorsList[] =
{
{FVIRTKEY, 'R', 1000},
{FVIRTKEY, 'T', 1001},
};
return CreateAcceleratorTable(acceleratorsList, _countof(acceleratorsList));
}
void ProcessHookMessage(MSG* a_Message)
{
// Only affect our window and its children
if ((g_TargetWindow != a_Message->hwnd) && !IsChild(g_TargetWindow, a_Message->hwnd))
return;
// Deliver the message directly
TranslateMessage(a_Message);
DispatchMessage(a_Message);
// Do not allow to process this message the second time
a_Message->message = WM_NULL;
}
LRESULT CALLBACK Hook_GetMsgProc(int a_Code, WPARAM a_WParam, LPARAM a_LParam)
{
if ((HC_ACTION == a_Code) && (PM_REMOVE == a_WParam))
ProcessHookMessage((MSG*)a_LParam);
return CallNextHookEx(g_Hook, a_Code, a_WParam, a_LParam);
}
void InstallHook()
{
g_Hook = SetWindowsHookEx(WH_GETMESSAGE, Hook_GetMsgProc, g_Instance, GetCurrentThreadId());
}
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int)
{
g_Instance = hInstance;
HWND mainWindow = CreateMainWindow();
HACCEL hAccelTable = CreateAccelerators();
InstallHook();
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
// The problem lurks here: some messages are handled directly and never reach the target window
if (TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
continue;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
이 코드에서 당신이 InstallHook()
호출을 주석하는 경우, 당신은 R 및 T을 인쇄 할 수 있기 때문에하지 않습니다 이러한 키는 가속기 테이블에 사용됩니다. 그러나 InstallHook()
을 사용하면 일반 메시지 큐 동작을 강제로 수행하고 모든 것이 정상적으로 작동합니다.
제안 후크 코드가 관심의 다음과 같은 사항이 : 그것은 단지 그것은 일반적인 메시지 큐와 같은 방식으로 작동 창문 및 다른
아무것도에 영향을
- 을 것 대신
SendMessage
덤비는의/PostMessage
- 그것은 응용 프로그램
호스팅에 의해 차단되지 않은 메시지의 이중 효과를 방지 브라우저 컨트롤이 때 전자 키보드 포커스를 가지고 있는가 통풍구가 분실 되었습니까? – Anders
@ 앤더스 나는 그렇게 생각한다. 일부 이벤트가 통과하고 다른 이벤트가 차단된다는 사실은 포커스가 획득되었다고 제안 할 것입니다. –
후크를 설정하는 것은 꽤 큰 망치입니다. 나는 호스트 응용 프로그램이 왜 그 메시지를 당신의 윈도우에 전달하지 않는지를 이해하는 것이 더 낫다고 생각한다. 당신은 또한 어떤 사람들은오고 있지만 다른 사람들은 그렇지 않다고 말했습니다. 어떤 패턴을 발견 했습니까? –