Внедрение HWND во внешний процесс с использованием SetParent
Я пытаюсь встроить окно из моего процесса в окно внешнего процесса с помощью функции SetParent и столкнулся с несколькими проблемами, которые я надеюсь, что кто-то может мне помочь. Во-первых, вот схема того, что я сейчас делаю, чтобы вставить мое окно в приложение:
HWND myWindow; //Handle to my application window
HWND externalWindow; //Handle to external application window
SetParent(myWindow,externalWindow);
//Remove WS_POPUP style and add WS_CHILD style
DWORD style = GetWindowLong(myWindow,GWL_STYLE);
style = style & ~(WS_POPUP);
style = style | WS_CHILD;
SetWindowLong(myWindow,GWL_STYLE,style);
Этот код работает, и мое окно появляется в другом приложении, но вводит следующие проблемы:
- Когда мое окно получает фокус ввода, основное окно приложения внешнего процесса теряет фокус (т.е. строка заголовка меняет цвет)
- Команды быстрого доступа к клавиатуре основного приложения не работают, когда мое окно имеет фокус
Кто-нибудь знает обходное решение для этого? Я хотел бы, чтобы мое окно рассматривалось как еще одно дочернее окно основного приложения.
Ответы
Ответ 1
Ну, наконец, я нашел ответ на свой вопрос.
Чтобы устранить проблему, когда основное приложение потеряло фокус, вам нужно использовать функцию AttachThreadInput, чтобы прикрепить встроенный поток окна к основному потоку приложения.
Кроме того, можно использовать функцию TranslateAccelerator в ответ на сообщения WM_KEYDOWN, чтобы обеспечить запуск сообщений ускорителя главного приложения.
Ответ 2
Я не уверен, что вы все еще интересуетесь этой темой через почти три года.
Я работаю над аналогичным приложением. Мое решение - изменить стиль окна перед вызовом SetParent. С помощью этого решения мне не нужно называть AttachThreadInput.
Однако одна из основных проблем размещения дочерних окон от внешнего процесса заключается в том, что если внешний процесс зависает при ответе на ввод пользовательской клавиатуры или мыши, основное приложение также зависает. Цикл сообщений в основном приложении все еще запущен. Однако он больше не принимает события ввода пользователя. Поэтому кажется, что он висит. Я считаю, что прямой результат AttachThreadInput, поскольку входные события двух потоков теперь синхронизированы. Если один из них заблокирован, оба заблокированы.
Ответ 3
Я нашел информацию об этом на Catch22.net с помощью сообщения WM_NACTIVE.
Это в разделе Запретить деактивацию окна.
Надеюсь, что это поможет.
Ответ 4
Я столкнулся с той же проблемой, внимательно прочитав документ MSDN, я нашел это легким решением.
Вы должны удалить WS_POPUP и добавить WS_CHILD ПЕРЕД, вы вызываете setParent
В MSDN указано:
По соображениям совместимости SetParent не изменяет стили окна WS_CHILD или WS_POPUP окна, родительский элемент которого изменяется. Поэтому, если hWndNewParent равно NULL, вы также должны очистить бит WS_CHILD и установить стиль WS_POPUP после вызова SetParent. И наоборот, если hWndNewParent не является NULL, а окно ранее было дочерним элементом рабочего стола, вы должны очистить стиль WS_POPUP и установить стиль WS_CHILD перед вызовом SetParent.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms633541(v=vs.85).aspx