Вновь созданный рабочий стол не получает события клавиатуры
Я создал небольшую программу, которая запускается на новом рабочем столе.
HDESK hDesktop = ::CreateDesktop(strDesktopName.c_str(),
NULL, // Reserved
NULL, // Reserved
0, // DF_ALLOWOTHERACCOUNTHOOK
GENERIC_ALL,
NULL); // lpSecurity
::SetThreadDesktop(hDesktop);
позже запустил другое приложение на этом рабочем столе, используя следующие строки:
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
si.cb = sizeof(si);
si.lpDesktop = &strDesktop[0];
if (FALSE == ::CreateProcess(pathModuleName.file_string().c_str(), L"abc def", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
return false;
DWORD dwWaitRes = ::WaitForSingleObject(pi.hProcess, INFINITE);
pathModuleName
является самостоятельным местоположением, полученным GetModuleFileName(NULL)
.
вновь созданное приложение получает HWND в другое окно и отправляет сообщения окна, используя следующие команды:
// bring window to front
::SetForegroundWindow(hwnd);
// set focus so keyboard inputs will be caught
::SetFocus(hwnd);
::keybd_event(VK_MENU, 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0);
...
так в основном приложения A
на рабочем столе по умолчанию запуск приложения B
на рабочем столе X, который получает HWND в другое приложение C
запущен на том же рабочем столе X.
моя проблема в том, что события клавиатуры, поступающие из приложения B
на рабочем столе X не запускаются в приложении C
. Только если я использую SwitchDesktop(B)
, затем запускаются события и код выполняется правильно.
что я упустил?
1 ответов
вы пытаетесь имитировать ввод пользователя на рабочем столе, который не активен на физической консоли (экран, мышь, клавиатура), который вряд ли будет работать, и почему SwitchDesktop()
заставляет его работать. Согласно документации:
делает указанный рабочий стол видимым и активирует его. это позволяет рабочему столу получать входные данные от пользователя.
keybd_event()
, mouse_event()
, SendInput()
, все они просто генерируют и хранят входные сообщения в той же очереди ввода, что физическая мышь / клавиатура размещать свои сообщения. Система ввода не знает разницы между пользовательским вводом и синтезированным вводом при отправке входных сообщений в приложения.
Реймонд Чен коснулся этого в своем блоге:
как имитировать ввод без SendInput?
SendInput работает на нижнем уровне входного стека. это просто бэкдор в тот же механизм ввода, что и драйверы клавиатуры и мыши, чтобы сообщить оконному менеджеру, что пользователь сгенерировал ввод. функция SendInput не знает, что произойдет с входом. Это обрабатывается гораздо более высокими уровнями оконного менеджера, такими как компоненты, которые хит-тестируют ввод мыши, чтобы увидеть, в какое окно сообщение должно быть доставлено изначально.
Он также опубликовал небольшую диаграмму в другом блоге статья показывает, где SendInput()
сидит по отношению к входной очереди:
когда что-то добавляется в очередь, требуется время, чтобы оно вышло из передней части очереди