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
передавая дескриптор главного окна вашего приложения.