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