SetForegroundWindow игнорируется

Я пишу небольшую утилиту, чтобы позволить мне мультиплексировать вход в несколько окон терминала;

Любой вход, полученный формой (в центре), ретранслируется на все окна терминала, которыми он управляет.

Это хорошо работает, но возникает проблема, если перед терминалами появляется другое окно. Форма ввода Topmost так всегда видно, но терминальные сессии скрыты.

Чтобы обойти это, двойной щелчок в окне ввода перебирает все терминалы и вызовы. SetForegroundWindow (от user32.dll) на каждом по очереди.

For Each Manager In Managers
    SetForegroundWindow(ProcessInfo.MainWindowHandle)
    'Threading.Thread.Sleep(15)
Next

Если я сделаю этот звонок без Thread.Sleep(15)только первое и последнее окно в списке выводятся на передний план. Sleep работает вокруг проблемы, но немного хакерский (и немного уродливый, когда открыто много терминалов).

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

Я прав в своем предположении? И есть ли способ обойти это ограничение? Что-то вроде MoveAllToForeground() или способ поставить в очередь сообщения?

Редактировать:

Чтобы уточнить: терминальный процесс, который я автоматизирую, не является частью моего приложения, это PuTTY

Если я поменяю вызов SetForegroundWindow за BringWindowToTopЯ получаю аналогичную проблему - хотя в этом случае только первый из терминалов вынесен вперед, остальные остаются за любыми другими окнами.

Изменить 2:

Следуя предложению Дэвида ниже. Декларации:

Private Declare Auto Function SetWindowPos Lib "user32.dll" (
    ByVal hWnd As IntPtr,
    ByVal hWndInsertAfter As IntPtr,
    ByVal X As Integer,
    ByVal Y As Integer,
    ByVal cx As Integer,
    ByVal cy As Integer,
    ByVal uFlags As SetWindowPosFlags
    ) As Boolean

Private Shared ReadOnly HWND_TOPMOST As New IntPtr(-1)
Private Shared ReadOnly HWND_NOTOPMOST As New IntPtr(-2)
Private Shared ReadOnly HWND_TOP As New IntPtr(0)
Private Shared ReadOnly HWND_BOTTOM As New IntPtr(1)

Private Enum SetWindowPosFlags
    NOSIZE = &H1
    NOMOVE = &H2
    NOZORDER = &H4
    NOREDRAW = &H8
    NOACTIVATE = &H10
    DRAWFRAME = &H20
    FRAMECHANGED = &H20
    SHOWWINDOW = &H40
    HIDEWINDOW = &H80
    NOCOPYBITS = &H100
    NOOWNERZORDER = &H200
    NOREPOSITION = &H200
    NOSENDCHANGING = &H400
    DEFERERASE = &H2000
    ASYNCWINDOWPOS = &H4000
End Enum

И звонок...

SetWindowPos(ProcessInfo.MainWindowHandle,
             HWND_TOP,
             0, 0, 0, 0,
             SetWindowPosFlags.NOMOVE Or
             SetWindowPosFlags.NOSIZE Or
             SetWindowPosFlags.NOACTIVATE)

1 ответ

Решение

По-видимому, вы хотите перенести эти окна на передний план, а не делать их окнами переднего плана. Способ сделать это - позвонить SetWindowPos прохождение HWND_TOP, Вам нужно будет пройти SWP_NOMOVE | SWP_NOSIZE как uFlags параметр, так как вы хотите изменить только z-порядок, а не позицию и размер.

После каждого звонка SetWindowPos, вызов SetForegroundWindow передавая дескриптор главного окна вашего приложения.

Другие вопросы по тегам