在WPF的程序中,嵌入其他进程的窗体

2022/1/17 7:07:22

本文主要是介绍在WPF的程序中,嵌入其他进程的窗体,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

我最近遇到了这样一个问题,就是我的WPF程序中,需要用到32位的COM组件。所以我的WPF程序也是要32位的。但是32的程序的逻辑内存最多只有2G,因此,当这个COM组件比较吃内存的时候,程序就会出现内存不够的情况,就会出现异常。因此,我的解决方案是使用winform来调用这个COM组件。然后WPF程序再调用winform。这样,就把内存分配到了多个进程当中,就不会出现一个进程使用太多内存的情况。

下面是WPF实现此功能的简单代码

窗体XAML代码

<Window x:Class="WPF_Open_Exe.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:WPF_Open_Exe"
        mc:Ignorable="d"
        Loaded="Window_Loaded"
         Title="Window1" Height="450" Width="800">
    <Grid>
        <WindowsFormsHost x:Name="WindowsFormsHost1" Background="Red" VerticalAlignment="Top" HorizontalAlignment="Left" Height="450" Width="800">
        </WindowsFormsHost>
    </Grid>
</Window>

页面的逻辑代码:

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        [DllImport("user32.dll", SetLastError = true)]
        public static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent);


        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);

        Process _process;
        System.Windows.Forms.Panel _hostPanel;

        public bool StartAndEmbedProcess(string processPath)
        {
            bool isStartAndEmbedSuccess = false;


            if (WindowsFormsHost1 != null)
            {
                _hostPanel = new System.Windows.Forms.Panel();
                WindowsFormsHost1.Child = _hostPanel;
            }

            _process = System.Diagnostics.Process.Start(processPath);

            //确保可获取到句柄
            Thread thread = new Thread(new ThreadStart(() =>
            {
                while (true)
                {
                    if (_process.MainWindowHandle != (IntPtr)0)
                    {
                        break;
                    }
                    Thread.Sleep(10);
                }
            }));
            thread.Start();

            Thread.Sleep(1000);
            isStartAndEmbedSuccess = EmbedApp(_process);
            if (!isStartAndEmbedSuccess)
            {
                CloseApp(_process);
            }
            return isStartAndEmbedSuccess;
        }

        public bool EmbedExistProcess(Process process)
        {
            _process = process;
            return EmbedApp(process);
        }

        /// <summary>
        /// 将外进程嵌入到当前程序
        /// </summary>
        /// <param name="process"></param>
        private bool EmbedApp(Process process)
        {
            //是否嵌入成功标志,用作返回值
            bool isEmbedSuccess = false;
            //外进程句柄
            IntPtr processHwnd = process.MainWindowHandle;
            //容器句柄
            IntPtr panelHwnd = _hostPanel.Handle;

            if (processHwnd != (IntPtr)0 && panelHwnd != (IntPtr)0)
            {
                //把本窗口句柄与目标窗口句柄关联起来
                int setTime = 0;
                while (!isEmbedSuccess && setTime < 10)
                {
                    isEmbedSuccess = (SetParent(processHwnd, panelHwnd) != 0);
                    Thread.Sleep(100);
                    setTime++;
                }
                //设置初始尺寸和位置
                MoveWindow(_process.MainWindowHandle, 0, 0, (int)ActualWidth, (int)ActualHeight, true);
            }

            if (isEmbedSuccess)
            {
                //_embededWindowHandle = _process.MainWindowHandle;
            }

            return isEmbedSuccess;
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            if (_process != null)
            {
                MoveWindow(_process.MainWindowHandle, 0, 0, (int)ActualWidth, (int)ActualHeight, true);
            }
            base.OnRender(drawingContext);
        }

        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            if (_hostPanel != null)
            {
                _hostPanel.Width = (int)this.Width;
                _hostPanel.Height = (int)this.Height;

                WindowsFormsHost1.Width = (int)this.Width;
                WindowsFormsHost1.Height = (int)this.Height;
            }

            this.InvalidateVisual();
            base.OnRenderSizeChanged(sizeInfo);
        }

        /// <summary>
        /// 关闭进程
        /// </summary>
        /// <param name="process"></param>
        private void CloseApp(Process process)
        {
            if (process != null && !process.HasExited)
            {
                process.Kill();
            }
        }

        public void CloseProcess()
        {
            CloseApp(_process);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            StartAndEmbedProcess(@"C:\Windows\system32\mspaint.exe");
        }
    }

运行后的效果图,这里是把系统的画图程序调进来了,调用其他的程序也是可以的,亲测有效。

代码链接:链接:https://pan.baidu.com/s/1BO7DLC0uy6pka8cjsaTUDA 
提取码:zxhe 
--来自百度网盘超级会员V3的分享 



这篇关于在WPF的程序中,嵌入其他进程的窗体的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程