none
Как создать свой Desktop C# WPF RRS feed

  • Вопрос

  • Есть задача привязать exe процесс к окну и показать его в ListBox при нажатии на ListBox открыть выбранное окно.

    Подскажите как это сделать?

    15 августа 2019 г. 18:30

Ответы

  • Чтобы приложение запускалось внутри рабочего стола то есть в WPF окне

    Я вам уже сказал что никак такое не сделать. В лучшем случае можно поместить окно приложения поверх вашего.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    16 августа 2019 г. 16:19
    Модератор
  • Функция 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());
                    }
                }
            }             
        }  
    }
    
    
    
    
    
    


    17 августа 2019 г. 16:15

Все ответы

  • Есть задача привязать exe процесс к окну и показать его в ListBox при нажатии на ListBox открыть выбранное окно.

    Подскажите как это сделать?

    Что такое "привязать exe процесс к окну"?


    This posting is provided "AS IS" with no warranties, and confers no rights.

    15 августа 2019 г. 18:46
    Модератор
  • Чтобы приложение запускалось внутри рабочего стола то есть в WPF окне
    16 августа 2019 г. 16:17
  • Чтобы приложение запускалось внутри рабочего стола то есть в WPF окне

    Я вам уже сказал что никак такое не сделать. В лучшем случае можно поместить окно приложения поверх вашего.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    16 августа 2019 г. 16:19
    Модератор
  • Как развернуть окно приложения UWP из панели задач и поместить поверх всех окон?
    16 августа 2019 г. 20:18
  • Функция 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());
                    }
                }
            }             
        }  
    }
    
    
    
    
    
    


    17 августа 2019 г. 16:15