Date: 17.08.2019 16:15:33
Функция SetParent работает и с окнами других процессов, поэтому привязать окно другого приложения к своему, в принципе, возможно (исключение - если процессы находятся в разных режимах DPI Awareness, в этом случае один из них упадет). Основная сложность - определить дескриптор окна, которое нужно привязывать и дождаться момента его загрузки, ведь приложение может иметь несколько разных окон, которые загружаются не сразу. Вот пример, который вроде работает в большинстве простых случаев:
XAML
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="My desktop" Height="350" Width="620.522" Closed="Window_Closed_1"> <Grid > <ListBox x:Name="listbox" HorizontalAlignment="Left" Margin="30,55,0,9.8" VerticalAlignment="Stretch" Width="220" DisplayMemberPath="ProcessName" MouseDoubleClick="listbox_MouseDoubleClick"/> <TextBox x:Name="tbCommand" HorizontalAlignment="Left" Height="23" Margin="30,10,0,0" TextWrapping="Wrap" Text="notepad" VerticalAlignment="Top" Width="220"/> <Button x:Name="bBrowse" Content="Обзор" HorizontalAlignment="Left" Height="23" Margin="266,10,0,0" VerticalAlignment="Top" Width="73" Click="bBrowse_Click" /> <Button x:Name="bRun" Content="Выполнить" HorizontalAlignment="Left" Height="23" Margin="367,10,0,0" VerticalAlignment="Top" Width="73" Click="bRun_Click"/> </Grid> </Window>
C#
using System; using System.Collections.ObjectModel; using System.Text; using System.Runtime.InteropServices; using System.Diagnostics; using System.Windows; using System.ComponentModel; using System.Threading; using System.Threading.Tasks; using System.Windows.Controls; using System.Windows.Interop; namespace WpfApplication1 { public partial class MainWindow : Window { [DllImport("user32.dll")] public static extern int SetParent(IntPtr hWnd, IntPtr NewParent); [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool IsWindowVisible(IntPtr hWnd); const int SW_SHOW = 5; const int SW_HIDE = 0; ObservableCollection<Process> applist = new ObservableCollection<Process>(); public MainWindow() { InitializeComponent(); listbox.ItemsSource = applist; } bool WaitMainWindow(Process pr) { for (int i = 0; i < 5; i++) { Thread.Sleep(1000); try { if (pr.MainWindowHandle != IntPtr.Zero) { return true; } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } } return false; } private async void bRun_Click(object sender, RoutedEventArgs e) { WindowInteropHelper h = new WindowInteropHelper(this); //получаем дескриптор этого окна Process pr = Process.Start(tbCommand.Text);//запускаем процесс if (pr == null) { MessageBox.Show("Не удалось запустить процесс"); return; } //ожидаем запуска цикла обработки сообщений... try { pr.WaitForInputIdle(); } catch (InvalidOperationException ex) { Debug.WriteLine(ex.ToString()); } if (pr.MainWindowHandle != IntPtr.Zero) { //если главное окно уже доступно, связываем с нашим окном SetParent(pr.MainWindowHandle, h.Handle); applist.Add(pr); } else { //ожидаем загрузки главного окна... bool res = false; await Task.Run(() => { res = WaitMainWindow(pr); }); if (res) { SetParent(pr.MainWindowHandle, h.Handle); applist.Add(pr); } } } private void listbox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e) { Process pr = listbox.SelectedItem as Process; if (pr == null) return; //показываем или скрываем окно if (IsWindowVisible(pr.MainWindowHandle)) ShowWindow(pr.MainWindowHandle, SW_HIDE); else ShowWindow(pr.MainWindowHandle, SW_SHOW); } private void bBrowse_Click(object sender, RoutedEventArgs e) { var dialog = new Microsoft.Win32.OpenFileDialog(); bool? res = dialog.ShowDialog(this); if (res.HasValue) { if (res.Value) { tbCommand.Text = dialog.FileName; } } } private void Window_Closed_1(object sender, EventArgs e) { //при закрытии окна закрываем все связанные окна foreach (Process pr in applist) { try { if (!pr.HasExited) { pr.CloseMainWindow(); } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } } } } }
Автор: VadimTagil