wpf exe加载成控件

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms.Integration;
using System.Windows.Interop;

namespace ClientHelper
{
    public static class ExtentionMethods
    {
        #region 调用外部exe程序
        /// <summary>
        /// 在一个WPF控件Boder里显示一个exe程序,程序铺满窗口,但程序有标题栏,可以拖动
        /// </summary>
        /// <param name="border">border对象</param>
        /// <param name="exePath">exe程序路径</param>
        /// <param name="processName">exe进程名称</param>
        public static void ShowExeInBorder_Movable(this System.Windows.Controls.Border border, string exePath, string processName)
        {
            ExeHost e = new ExeHost(exePath, processName);
            border.Child = e;
        }
        /// <summary>
        /// 在一个WPF控件Boder里显示一个exe程序,程序铺满窗口,不可拖动
        /// </summary>
        /// <param name="border">border对象</param>
        /// <param name="exePath">exe程序路径</param>
        /// <param name="processName">exe进程名称</param>
        /// <param name="exeTitleBarHeight">exe程序标题栏高度</param>
        /// <param name="exeWidth">exe程序显示宽度</param>
        /// <param name="exeHeight">exe程序显示高度(包括标题栏高度)</param>
        public static void ShowExeInBorder_NoTitleBar(this System.Windows.Controls.Border border, string exePath, string processName, int exeTitleBarHeight, int exeWidth, int exeHeight)
        {
            border.Height = exeHeight - exeTitleBarHeight;
            border.Width = exeWidth;
            border.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
            border.VerticalAlignment = System.Windows.VerticalAlignment.Center;
            WindowsFormsHost host = new WindowsFormsHost() { Width = border.Width, Height = border.Height };

            ExeHostUserControl uc = new ExeHostUserControl();

            InvalidataExeProcess(uc, exeHeight, exeWidth, exePath, processName);

            host.Child = uc;

            border.Loaded += new System.Windows.RoutedEventHandler((s, e) =>
            {
                IntPtr notepadHandle = uc.EXEIntprt = uc._process.MainWindowHandle;
                //强制使用样式,给exe程序设置父窗体
                int style = GetWindowLong(notepadHandle, GWL_STYLE);
                style = style & ~((int)WS_CAPTION) & ~((int)WS_THICKFRAME); // Removes Caption bar and the sizing border
                style |= ((int)WS_CHILD); // Must be a child window to be hosted

                SetWindowLong(notepadHandle, GWL_STYLE, style);
                SetParent(notepadHandle, uc.Handle);

                uc.Invalidate();
                //移动exe程序的位置。
                MoveWindow(uc.EXEIntprt, 0, exeTitleBarHeight * (-1), exeWidth, exeHeight, true);
            });
            border.Child = host;
            border.InvalidateVisual();
        }
        private static void InvalidataExeProcess(ExeHostUserControl uc, int exeHeight, int exeWidth, string exePath, string processName)
        {
            Process[] ps = Process.GetProcessesByName(processName);
            if (ps.Length > 0)
            {
                var p = ps[0];
                p.Kill();
            }

            ProcessStartInfo psi = new ProcessStartInfo(exePath);
            psi.WindowStyle = ProcessWindowStyle.Minimized;
            uc._process = Process.Start(psi);
            uc._process.WaitForInputIdle();

            uc.Size = new System.Drawing.Size(exeWidth, exeHeight);


            // The main window handle may be unavailable for a while, just wait for it
            while (uc._process.MainWindowHandle == IntPtr.Zero)
            {
                Thread.Yield();
            }

            IntPtr notepadHandle = uc.EXEIntprt = uc._process.MainWindowHandle;
            int style = GetWindowLong(notepadHandle, GWL_STYLE);
            style = style & ~((int)WS_CAPTION) & ~((int)WS_THICKFRAME); // Removes Caption bar and the sizing border
            style |= ((int)WS_CHILD); // Must be a child window to be hosted

            SetWindowLong(notepadHandle, GWL_STYLE, style);
            SetParent(notepadHandle, uc.Handle);

            uc.Invalidate();
        }
        [DllImport("user32.dll")]
        static extern bool MoveWindow(IntPtr Handle, int x, int y, int w, int h, bool repaint);

        #region win32
        [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.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Unicode)]
        internal static extern bool DestroyWindow(IntPtr hwnd);


        private const int WS_CAPTION = 0x00C00000;
        private const int WS_THICKFRAME = 0x00040000;
        private const int GWL_STYLE = -16;
        private const int WS_CHILD = 0x40000000;
        #endregion
        #endregion
    }

    class ExeHost : HwndHost
    {

        public ExeHost(string exePath, string processName)
        {
            this._processName = processName;
            this._path = exePath;
        }
        private Process _process;
        protected override HandleRef BuildWindowCore(HandleRef hwndParent)
        {

            Process[] ps = Process.GetProcessesByName(_processName);
            if (ps.Length > 0)
            {
                var p = ps[0];
                p.Kill();
            }
            ProcessStartInfo psi = new ProcessStartInfo(_path);
            psi.WindowStyle = ProcessWindowStyle.Minimized;
            _process = Process.Start(psi);
            _process.WaitForInputIdle();

            // The main window handle may be unavailable for a while, just wait for it
            while (_process.MainWindowHandle == IntPtr.Zero)
            {
                Thread.Yield();
            }

            IntPtr notepadHandle = _process.MainWindowHandle;

            int style = GetWindowLong(notepadHandle, GWL_STYLE);
            style = style & ~((int)WS_CAPTION) & ~((int)WS_THICKFRAME); // Removes Caption bar and the sizing border
            style |= ((int)WS_CHILD); // Must be a child window to be hosted

            SetWindowLong(notepadHandle, GWL_STYLE, style);
            SetParent(notepadHandle, hwndParent.Handle);

            this.InvalidateVisual();

            HandleRef hwnd = new HandleRef(this, notepadHandle);
            return hwnd;
        }

        protected override void DestroyWindowCore(HandleRef hwnd)
        {
            DestroyWindow(hwnd.Handle);
        }

        private const int GWL_STYLE = -16;
        private const int WS_CAPTION = 0x00C00000;
        private const int WS_THICKFRAME = 0x00040000;
        private const int WS_CHILD = 0x40000000;
        private string _path;
        private string _processName;

        [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.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Unicode)]
        internal static extern bool DestroyWindow(IntPtr hwnd);
    }
}

 

posted @ 2020-04-18 20:30  灰主流  阅读(325)  评论(0编辑  收藏  举报