2013-05-29 4 views
24

Отказ от ответственности: Я не знаком с API Win32, особенно с тем, как работают окна.Родительское окно замерзает, когда дочернее окно зависает от другого процесса

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

Представьте себе, что container.exe notepad.exe 'хозяев и someApplication.exe

Когда я приостановить основную нить someApplication.exe в течение нескольких секунд, его окно заморожен на эту сумму времени. Это совершенно понятно. Но окно container.exe будет также висит за то же время. Детские окна других размещенных процессов (например, notepad.exe) будут продолжать работать нормально.

Я использую команду SetParent, чтобы сделать обычное окно без ДЕТСКОГО ребенка моего container.exe:

SetParent(
    childProcess.HWND, 
    myOwnHWND 
); 

После этого, я использую setWindowPos:

SetWindowPos(
    childProcess.HWND, 
    HWND_TOP, 
    someXPos, 
    someYPos, 
    0, 
    0, 
    SWP_FRAMECHANGED or SWP_NOSIZE or SWP_SHOWWINDOW 
) 

As MSDN article on SetParent предлагает, я также очищаю атрибут стиля WS_POPUP и добавляю атрибут WS_CHILD. Так как это тоже не помогло, я также добавил атрибут расширенного стиля WS_EX_NOACTIVATE, используя команду SetWindowLongPtr. Наконец, я попытался отправить оба окна WM_UPDATEUISTATE, а затем сообщение WM_CHANGEUISTATE, но это также не изменило ничего.

Что меня смущает, так это то, что окно родительского процесса продолжает рисоваться нормально, пока я не коснусь его. Затем он полностью замораживается, пока дочернее окно не размораживается. Я подозреваю, что что-то называется 'входной очереди'. MSDN article около WM_ACTIVATE сообщений гласят:

Направлена ​​как окно активируется и деактивируется окно. Если в окнах используется одна и та же входная очередь, то сообщение отправляется синхронно, сначала к оконной процедуре деактивируется окно верхнего уровня, а затем к оконной процедуре активированного окна верхнего уровня. Если окна используют разные входные очереди, сообщение отправляется асинхронно, поэтому окно активируется немедленно.

Из-за этого я возлагал большие надежды на атрибут расширенного стиля WS_EX_NOACTIVATE.

Подводя итог: на самом деле возможно разместить окно другого процесса и не замораживать собственное окно, когда дочернее окно зависает?

+8

+1 Этот вопрос невероятно тщательный. –

+2

Связанные чтения: [Разрешено ли иметь право на переключение между родительскими/дочерними или зависимыми отношениями между родителями и дочерними компаниями?] (Http://blogs.msdn.com/b/oldnewthing/archive/2013/04/12/10410454 .aspx) – GSerg

+1

* Зачем вам это нужно? Я уверен, что есть лучший и простой способ достичь вашей фактической цели. Не попадайте в ловушку проблем XY. –

ответ

17

Вы не можете ожидать блокировки нити GUI любого процесса. В вашем сценарии ситуация немного сложнее, потому что есть два потока графического интерфейса. Один для каждого процесса.

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

Windows, которые находятся в отношениях родителя/ребенка, отправят друг другу сообщения. И если эти сообщения синхронны, они отправляются, а не отправляются, то блокирование одного потока GUI приведет к блокировке другого.

Золотое правило программирования GUI остается в силе: не блокируйте нить GUI. Если у вас многолетняя задача, переместите ее на фоновый поток.

Update

ОК, как описано here, когда вы связываете окна из разных потоков прикреплении их очереди сообщений друг другу. И если вы блокируете один поток, вы блокируете все связанные потоки.

Итак, не блокируйте нить GUI.

+1

Спасибо. Конечно, поток GUI не должен блокироваться. Однако я тестирую худший сценарий, например, приложение _hosted_ полностью замораживает. В этом случае приложение-хозяин просто НЕ МОЖЕТ замораживаться. Кроме того, я все еще удивляюсь, как здесь взаимодействуют отношения между родителями и дочерними процессами. Если дочернее окно процесса не является дочерним по отношению к родительскому процессу, последнее, конечно, не будет зависеть. Поэтому они не могут быть действительно отправлены ** сообщениями. –

+0

«Если дочернее окно не является дочерним по отношению к родительскому процессу, последнее, конечно, не замерзнет». Ваш вызов SetParent делает одно окно дочерним. «Они не могут отправлять сообщения». Почему нет? Весь графический интерфейс Windows основан на сообщениях. Это абсолютно то, что делают окна. Если блокировать поток GUI, ожидайте, что ваш графический интерфейс завершится с ошибкой. –

+2

Итак, ключевым моментом является то, что оба окна теперь используют одну и ту же _input queue_. Основная проблема заключается в синхронной ** отправке ** сообщения WM_ACTIVATE на замороженное окно. Вот еще одна новостная группа, которая охватывает тот же самый вопрос: [Ссылка] (http://narkive.com/YmRDFrDR). Поскольку я не ожидаю, что удалю дочерние окна _input queue_ с помощью команды «AttachThreadInput», я принимаю это как ответ и буду жить счастливой жизнью без отношений родительского/дочернего окна. Большое спасибо! –

Смежные вопросы