最顶层 window 超过所有内容,子进程除外
Topmost window over everything, except child processes
我的程序是全屏和最顶层的,我希望 window 的所有子进程都在我程序的主进程 window 之上。这些过程是未知的,并且是外部的。
我可以使用 System.Diagnostics.Process.Start(exeName,procArgs).WaitForExit()
启动该进程,但从那里我卡住了。
基本上,您使用 SetParent() API 使外部应用程序成为您的子应用程序。在这里,我还使用 GetWindowRect() 和 SetWindowPos() APIs 将 window 在其父项更改后保持在相同的启动位置。最后,您需要跟踪进程并手动关闭它们,以便它们在关闭表单时不会成为孤立的:
Imports System.ComponentModel
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text.RegularExpressions
Public Class Form1
Private Const SWP_NOSIZE As Integer = &H0001
<StructLayout(LayoutKind.Sequential)>
Public Structure RECT
Public Left As Integer, Top As Integer, Right As Integer, Bottom As Integer
End Structure
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
End Function
<DllImport("user32.dll")>
Private Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
End Function
<DllImport("user32.dll", SetLastError:=True)>
Private Shared Function SetWindowPos(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 Integer) As Boolean
End Function
Private Ps As New List(Of Process)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim exeName As String = "Notepad"
Dim procArgs As String = ""
LaunchExe(exeName, procArgs)
End Sub
Private Sub LaunchExe(ByVal exeName As String, ByVal procArgs As String)
Try
Dim p As Process = System.Diagnostics.Process.Start(exeName, procArgs)
If Not IsNothing(p) Then
p.WaitForInputIdle()
Dim rc As RECT
GetWindowRect(p.MainWindowHandle, rc)
Dim pt As New Point(rc.Left, rc.Top)
pt = Me.PointToClient(pt)
SetParent(p.MainWindowHandle, Me.Handle)
SetWindowPos(p.MainWindowHandle, 0, pt.X, pt.Y, 0, 0, SWP_NOSIZE)
Ps.Add(p)
End If
Catch ex As Exception
MessageBox.Show(exeName & vbCrLf & procArgs, "Error Starting Application")
End Try
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Me.Close()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
For Each P As Process In Ps
If Not P.HasExited Then
P.CloseMainWindow()
End If
Next
End Sub
End Class
我的程序是全屏和最顶层的,我希望 window 的所有子进程都在我程序的主进程 window 之上。这些过程是未知的,并且是外部的。
我可以使用 System.Diagnostics.Process.Start(exeName,procArgs).WaitForExit()
启动该进程,但从那里我卡住了。
基本上,您使用 SetParent() API 使外部应用程序成为您的子应用程序。在这里,我还使用 GetWindowRect() 和 SetWindowPos() APIs 将 window 在其父项更改后保持在相同的启动位置。最后,您需要跟踪进程并手动关闭它们,以便它们在关闭表单时不会成为孤立的:
Imports System.ComponentModel
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text.RegularExpressions
Public Class Form1
Private Const SWP_NOSIZE As Integer = &H0001
<StructLayout(LayoutKind.Sequential)>
Public Structure RECT
Public Left As Integer, Top As Integer, Right As Integer, Bottom As Integer
End Structure
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
End Function
<DllImport("user32.dll")>
Private Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
End Function
<DllImport("user32.dll", SetLastError:=True)>
Private Shared Function SetWindowPos(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 Integer) As Boolean
End Function
Private Ps As New List(Of Process)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim exeName As String = "Notepad"
Dim procArgs As String = ""
LaunchExe(exeName, procArgs)
End Sub
Private Sub LaunchExe(ByVal exeName As String, ByVal procArgs As String)
Try
Dim p As Process = System.Diagnostics.Process.Start(exeName, procArgs)
If Not IsNothing(p) Then
p.WaitForInputIdle()
Dim rc As RECT
GetWindowRect(p.MainWindowHandle, rc)
Dim pt As New Point(rc.Left, rc.Top)
pt = Me.PointToClient(pt)
SetParent(p.MainWindowHandle, Me.Handle)
SetWindowPos(p.MainWindowHandle, 0, pt.X, pt.Y, 0, 0, SWP_NOSIZE)
Ps.Add(p)
End If
Catch ex As Exception
MessageBox.Show(exeName & vbCrLf & procArgs, "Error Starting Application")
End Try
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Me.Close()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
For Each P As Process In Ps
If Not P.HasExited Then
P.CloseMainWindow()
End If
Next
End Sub
End Class