My program is full screen and topmost, and I would like all the child processes of that window to be above my program's main window. The processes are unknown, and external.
I can launch the process using System.Diagnostics.Process.Start(exeName,procArgs).WaitForExit()
, but from there I am stuck.
Basically you use the SetParent() API to make the external app a child of yours. Here I'm also using the GetWindowRect() and SetWindowPos() APIs to keep the window in the same launch position after its parent is changed. Finally, you need to keep track of the processes and close them manually so they do not become orphaned when the form is closed:
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