Freigeben über


Установка родительского окна из другого процесса — это трюк, но в некоторых случаях так делать правильно

У клиента есть основное приложение (давайте, назовем его A) и вспомогательное приложение (давайте, назовем его B). Клиент хочет, что окно из приложения B вело себя как модальное окно по отношению к окну приложения A.

Когда запускается приложение B, мы блокируем окно A и вызываем функцию SetForegroundWindow(hwndB) для эмуляции поведения модального окна. Как нам сделать так, чтобы фокус переходил к окну приложения B, а не окну приложения A? Мы обнаружили, что если пользователь нажимает на окно из процесса A (которое в данный момент недоступно), окно B теряет фокус. Настоящие диалоговые окна ведут себя по-другому: при нажатии на заблокированное окно должно активироваться модальное окно.

Одной из идей было наблюдение за событиями WM_ACTIVATE(FALSE) для дескриптора hwndSecondProcess, и если окно, которое забрало у нас фокус ввода, принадлежит первому процессу, тогда мы забираем его обратно при помощи вызова SetForegroundWindow(hwndSecondProcess).

Но потом мы засомневались: ведь мы заблокировали окно A, дойдет ли до него это сообщение активации?

Поскольку окно заблокировано, оно не будет получать сообщения об активации, потому что заблокированные окна не могут быть активированы. Поэтому, нет, это решение не будет работать.

Однако тема, указанная клиентом в вопросе, уже содержит ответ, хоть поначалу это и незаметно. В теме вопроса было написано «Межпроцессная псевдо-связь между родительским и дочерним окном». (Ладно, там было написано вместо «родительским и дочерним окном» — «окном-владельцем и принадлежащим ему окном», но это допустимая небрежность, когда разговор идет об отношении между окнами).

Вместо реализации псевдо-связи между окном-владельцем и принадлежащим ему окном сделайте настоящую связь. Зачем ее эмулировать, если мы можем создать настоящую связь между окнами?

Когда вы отображаете диалоговое окно в процессе B, передайте ему дескриптор hwndA в качестве окна-владельца. Теперь у этих окон есть настоящая подчиненная связь вместе со всем стандартным поведением, присущим такой связи. Для окон вполне допустимо иметь подчиненную связь, которая пересекает границы процесса. Лишь имейте в виду, что такая операция связывает обе очереди обработки сообщений вместе, поэтому вам нужно быть очень осторожным, чтобы оба окна не обрабатывали пользовательский ввод одновременно. К счастью, в случае диалогового окна пользовательский ввод обрабатывается одновременно только одним окном, поэтому самая страшная часть этого решения обходит нас стороной.