Вновь созданный рабочий стол не получает события клавиатуры

Я создал небольшую программу, которая запускается на новом рабочем столе.

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() заставляет его работать. Согласно документации:

функции SwitchDesktop

делает указанный рабочий стол видимым и активирует его. это позволяет рабочему столу получать входные данные от пользователя.

keybd_event(), mouse_event(), SendInput(), все они просто генерируют и хранят входные сообщения в той же очереди ввода, что физическая мышь / клавиатура размещать свои сообщения. Система ввода не знает разницы между пользовательским вводом и синтезированным вводом при отправке входных сообщений в приложения.

Реймонд Чен коснулся этого в своем блоге:

как имитировать ввод без SendInput?

SendInput работает на нижнем уровне входного стека. это просто бэкдор в тот же механизм ввода, что и драйверы клавиатуры и мыши, чтобы сообщить оконному менеджеру, что пользователь сгенерировал ввод. функция SendInput не знает, что произойдет с входом. Это обрабатывается гораздо более высокими уровнями оконного менеджера, такими как компоненты, которые хит-тестируют ввод мыши, чтобы увидеть, в какое окно сообщение должно быть доставлено изначально.

Он также опубликовал небольшую диаграмму в другом блоге статья показывает, где SendInput() сидит по отношению к входной очереди:

когда что-то добавляется в очередь, требуется время, чтобы оно вышло из передней части очереди

diagram