I'm trying to open both WordPad and Notepad from within my C# WPF application and then 'attach' them to my application (inside a WPF TabControl
). Each application will exist in a different TabItem
.
I have run into an issue where I can achieve this for 1 program only. So, if I try it with Notepad, it works as desired. If I try it with WordPad, it works as desired. If I try it with both, it only "docks" 1 of the applications into my project - the other application is still executed (it loads) but doesn't 'live' inside my WPF app.
I am at a total lost as to what I've done wrong. The only way I can share the code is to share all of it - I've tried to cut it down as much as possible.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using Size = System.Windows.Size;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private System.Windows.Forms.Panel _panel;
private Process _process;
public MainWindow()
{
InitializeComponent();
_panel = new System.Windows.Forms.Panel();
var list = new Dictionary<string, string>();//process and params
list.Add("notepad.exe", null);
list.Add(@"wordpad.exe", null);
foreach (var path in list)
{
BeginThisThing(path.Key.ToString(), Convert.ToString(path.Value)); //I know the naming is poor, for now I'm only testing!!
var host1 = new System.Windows.Forms.Integration.WindowsFormsHost();
host1.Child = this._panel;
try
{
TabItem ti = new TabItem();
this.Tabby.Items.Add(ti);
ti.Header = path.Key.ToString();
ti.Content = host1;
}
catch (Exception ex)
{
string s = ex.ToString();
}
}
}
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent);
[DllImport("user32")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
private const int SWP_NOZORDER = 0x0004;
private const int SWP_NOACTIVATE = 0x0010;
private const int GWL_STYLE = -16;
private const int WS_CAPTION = 0x00C00000;
private const int WS_THICKFRAME = 0x00040000;
private void BeginThisThing(string path, string param)
{
ProcessStartInfo psi = null;
psi = (String.IsNullOrEmpty(param)) ? new ProcessStartInfo(path) : new ProcessStartInfo(path, param);
_process = Process.Start(psi);
_process.WaitForInputIdle();
Thread.Sleep(500);
SetParent(_process.MainWindowHandle, _panel.Handle);
// remove control box
int style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
style = style & ~WS_CAPTION & ~WS_THICKFRAME;
SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);
// resize embedded application & refresh
ResizeEmbeddedApp();
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (_process != null)
{
_process.Refresh();
_process.Close();
}
}
private void ResizeEmbeddedApp()
{
if (_process == null)
return;
SetWindowPos(_process.MainWindowHandle, IntPtr.Zero, 0, 0, (int)_panel.ClientSize.Width, (int)_panel.ClientSize.Height, SWP_NOZORDER | SWP_NOACTIVATE);
}
protected override Size MeasureOverride(Size availableSize)
{
Size size = base.MeasureOverride(availableSize);
ResizeEmbeddedApp();
return size;
}
}
}
XAML is simply
<Grid>
<TabControl x:Name="Tabby"></TabControl>
</Grid>
The panel you declared in the class as a field has to be unique for each host, but in you code it is shared between them, what causes the behaviour you see.
User contributions licensed under CC BY-SA 3.0