2016-11-08 59 views
0

Я пытаюсь разместить/запустить приложение Exe внутри панели внутри главного окна моей программы. В главном окне есть сетка с тремя столбцами - два столбца разделены равномерно с помощью вертикального разделителя сетки для разделения левого и правого столбцов. В левом столбце есть элемент управления вкладкой, но правый столбец - это то, что я хочу разместить в exe-приложении внутри и, по существу, изменить размер приложения на основе док-станции внутри правого столбца.Внешнее приложение-хозяин в панели WPF

Я разработал программу аналогично Hosting external app in WPF window. Этот пример намного проще, чем то, что я буду использовать для exe и дополнительных функций, но пример должен объяснить мою текущую проблему.

Я могу запустить exe в окно, но не внутри Dockpanel, или любой другой в правой колонке. exe просто остается внутри окна статически, где он помещен, а не размещен внутри столбца. Я могу войти и изменить начальное местоположение окна процесса, чтобы оно действительно открывалось поверх правая колонка и, как представляется, находится в панели док-станции этого столбца, но опять же она статична.

Все примеры, которые я видел, размещают процесс внутри окна, а не внутри контейнера. WindowsInteropHelper на панель док-станции, но он все еще просто отправляет это в главное окно.

var helper = new WindowInteropHelper(GetWindow(this.ApplicationDock)); 

Я также попробовал несколько статей, включая два ниже, но все еще не нашли решение, которое я "ищу.

How can I run another application within a panel of my C# program?

Docking Window inside another Window

Одним из возможных вариантов Я думал о том, что при обновлении окна обновляется обработчик окна процесса, который должен быть помещен в правильные координаты, где начинается правый столбец. Мне кажется, что это должно быть последним средством, хотя и не соответствующим ct способ справиться с этим.

Моя главная заявка

<Window x:Class="ProgramInProgram.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:ProgramInProgram" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition /> 
     <ColumnDefinition Width="Auto"/> 
     <ColumnDefinition /> 
    </Grid.ColumnDefinitions> 
    <TabControl Grid.Column="0"> 
     <TabItem Header="Blue Tab"> 
      <Grid Background="Blue"></Grid> 
     </TabItem> 
     <TabItem Header="Red Tab" > 
      <Grid Background="Red"></Grid> 
     </TabItem> 
    </TabControl> 
    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" /> 
    <DockPanel Grid.Column="2" x:Name="ApplicationDock"> 
    </DockPanel> 
</Grid> 
</Window> 

Кодекс за

public partial class MainWindow : Window 
{ 

    [DllImport("user32.dll")] 
    public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); 

    [DllImport("user32.dll", SetLastError = true)] 
    public static extern int GetWindowLong(IntPtr hWnd, int nIndex); 

    [DllImport("user32.dll")] 
    private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); 

    [DllImport("user32.dll")] 
    private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, int uFlags); 

    private Process process; 

    private const int SWP_ZOZORDER = 0x0004; 
    private const int SWP_NOACTIVATE = 0x0010; 
    private const int GWL_STYLE = (-16); 
    private const int WS_CAPTION = 0x00C00000; 
    private const int WS_VISIBLE = 0x10000000; 
    private const int WS_THICKFRAME = 0x00040000; 
    const string patran = "patran"; 

    public MainWindow() 
    { 
     InitializeComponent(); 

     Loaded += (s, e) => LaunchChildProcess(); 
    } 

    private void LaunchChildProcess() 
    { 
     this.process = Process.Start("Notepad.exe"); 
     this.process.WaitForInputIdle(); 

     var helper = new WindowInteropHelper(GetWindow(this.ApplicationDock)); 

     SetParent(this.process.MainWindowHandle, helper.Handle); 

     int style = GetWindowLong(this.process.MainWindowHandle, GWL_STYLE); 
     style = style & ~WS_CAPTION & ~WS_THICKFRAME; 
     SetWindowLong(this.process.MainWindowHandle, GWL_STYLE, style); 
     ResizeEmbeddedApp(); 
    } 

    private void ResizeEmbeddedApp() 
    { 
     if (this.process == null) 
     { 
      return; 
     } 

     UIElement container = VisualTreeHelper.GetParent(this.ApplicationDock) as UIElement; 
     Point relativeLocation = this.ApplicationDock.TranslatePoint(new Point(0, 0), container); 
     } 

    protected override Size MeasureOverride(Size availableSize) 
    { 
     Size size = base.MeasureOverride(availableSize); 
     ResizeEmbeddedApp(); 
     return size; 
    } 
} 
+0

Я постараюсь избежать таких хаков. Если вам действительно нужен блокнот, используйте TextBox. Вы можете использовать OLE, в то время как это действительно избыток для простого редактирования файла. https://en.wikipedia.org/wiki/Object_Linking_and_Embedding – Mat

+0

Возможный дубликат [Хостинг внешнего приложения в окне WPF] (http://stackoverflow.com/questions/5028598/hosting-external-app-in-wpf-window) – FreeMan

+0

Это пример программы, в моей реальной программе я использую другое приложение для EXE, которое является более сложным - ничего подобного редактированию текстового файла. – Caleb

ответ

0

У меня такая же потребность, как мой клиент хочет приборную панель с 4 приложения WPF работает. Я считаю, что это должно помочь и, кстати, если кто-нибудь знает лучший способ создать панель инструментов Windows app, я бы с удовольствием услышал об этом. Ключом является использование windowsformhost.

string exeName = @"C:\Repos\OnSpot17\OnTheSpot\bin\Debug\OnTheSpot.exe"; 
     var procInfo = new System.Diagnostics.ProcessStartInfo(exeName); 
     procInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(exeName); 
     procInfo.WindowStyle = ProcessWindowStyle.Minimized; 
     // Start the process 
     _childp = Process.Start(procInfo); 
     System.Windows.Forms.Panel _pnlSched = new System.Windows.Forms.Panel(); 
     WindowsFormsHost windowsFormsHost1 = new WindowsFormsHost(); 

     windowsFormsHost1.Child = _pnlSched; 

     test.Children.Add(windowsFormsHost1); 

     // Wait for process to be created and enter idle condition 
     // _childp.WaitForInputIdle(); 
     // The main window handle may be unavailable for a while, just wait for it 
     while (_childp.MainWindowHandle == IntPtr.Zero) 
     { 
      Thread.Yield(); 
     } 

     // Get the main handle 
     _appWin = _childp.MainWindowHandle; 
    //  PR.WaitForInputIdle(); // true if the associated process has reached an idle state. 
     SetParent(_appWin, _pnlSched.Handle); // loading exe to the wpf window.