Cannot "attach" multiple applications in my WPF project

1

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>
c#
wpf
asked on Stack Overflow Feb 22, 2015 by MyDaftQuestions • edited Feb 22, 2015 by MyDaftQuestions

1 Answer

1

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.

answered on Stack Overflow Feb 22, 2015 by EngineerSpock

User contributions licensed under CC BY-SA 3.0