将MATLAB的figure窗体嵌入到C#窗体应用的(panel)中

本文主要讲解将MATLAB绘制的figure窗体嵌入到C#winform窗体的panel控件中。

在网上找了相关的资料后,发现网上大部分的处理方法是创建新线程和跨线程的方式,复不复杂我就不说了,而且我用网上的方法后,还出现了不少的奇葩bug。

首先,为了程序的美观和易读性,我们将MATLAB的figure嵌入C#这个功能封装成一个我们自定义的类,这样的好处是当有多个C#窗体需要嵌入figure时,不需要再重写代码,直接调用即可。

MATLAB部分

步骤一:

编写一个简单的绘图程序。

 

步骤二:

封装成dll,这里就不展开讲了,具体步骤看我另一篇博客,链接放下面了https://blog.csdn.net/yty2545340913/article/details/123127784?spm=1001.2014.3001.5501

 记住这个文件,一会儿要用

 

C#部分

步骤一:

新建一个C#窗体应用。这就不用我教了吧,哈哈哈。

步骤二:

修改目标平台为x64,一定要记得改呀兄弟们,这个错误我踩了好几次坑了,每次都不记得改。

步骤三:

新建一个.cs文件,命名为“GetFigure.cs”。

步骤四:

引入Windows的API,这一部分主要是引入对窗体处理的函数,抄就行了,他是个dll,我也不知道咋实现的。不要忘了using

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Runtime.InteropServices; // 对Windows窗体进行的操作
using System.Windows.Forms; // 对C#窗体进行的操作
using System.Threading; // 这个不说了,线程的问题了

namespace WindowsFormsApp1
{
    internal class GetFigure
    {
        #region 引入WindowsAPI
        //FindWindow用来查找窗体。
        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string strclassName, string strWindowText);

        //SetParent用来设置窗体的父窗体。
        [DllImport("user32.dll")]
        public static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        //MoveWindow用来改变窗体大小。
        [DllImport("user32.dll")]
        public static extern int MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool BRePaint);

        //DestroyWindow用来关闭并窗体。
        [DllImport("user32.dll")]
        public static extern bool DestroyWindow(IntPtr hWnd);

        private const int GWL_STYLE = (-16);
        public const int WS_CAPTION = 0xC00000;

        //GetWindowLong 获取index
        [DllImport("USER32.DLL")]
        public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

        //SetWindowLong 隐藏标题栏
        [DllImport("user32.dll")]
        public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

        #endregion 引入dll


        /// <summary>
        /// 将指定的figure放入指定的控件(Control)中
        /// </summary>
        /// <param name="windowName">想要嵌入的figure的名称</param>
        /// <param name="control">想要嵌入到哪个控件中</param>
        public static void getFifure(string windowName, Control control)
        {
            IntPtr hWnd = new IntPtr(0); // 定义一个图像句柄
            hWnd = FindWindow(null, windowName); // 寻找有没有这个图窗
            //判断这个窗体是否有效 
            if (hWnd != IntPtr.Zero)
            {
                //MessageBox.Show("找到窗口"); // 调试的时候可以观察有没有成功
                // 设置窗体的父窗体
                SetParent(hWnd, control.Handle);
                control.Tag = hWnd;
                // 隐藏标题栏
                SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) & ~WS_CAPTION);
                // 改变窗体大小
                MoveWindow(hWnd, 0, 0, control.ClientSize.Width, control.ClientSize.Height, true);
                // 这个地方我也是结合网上查找的资料,应该是刷新的功能吧,你们也可以去掉试试
                Thread.Sleep(200);
                MoveWindow(hWnd, 0, 0, control.ClientSize.Width, control.ClientSize.Height, true);
            }

        }
    }
}

步骤五:

在Form1窗体上拖动一些控件,还有个timer定时器别忘了

 

步骤六:

添加引用,就是刚才保存的“test.dll”文件,由于没有数据传输,所以就不需要添加MWArray.dll。个人建议是将test.dll复制到C#项目文件下的bin\Debug文件夹里,方便管理和打包。具体步骤都在我上面那一篇博客里。

 

步骤七:

下面就是写代码了,讲一下大致思路。

窗体生成前的命令:设置定时器的周期并开启定时器

定时器执行的命令:寻找是否有figure窗体,并将窗体嵌入到指定控件

按钮执行的命令:调用dll,执行绘图命令,生成figure窗体

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// 实例化dll
        /// </summary>
        test.Class1 tst1 = new test.Class1();

        /// <summary>
        /// 定义要查找的figure窗体的名称
        /// </summary>
        string winName = "figure 1";

        /// <summary>
        /// Form1的构造函数,这个是自带的
        /// </summary>
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 窗体生成前要执行的命令
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            // 设置定时器的运行周期
            timer1.Interval = 400;
            // 开启定时器
            timer1.Start();
        }

        /// <summary>
        /// 定时器执行的命令
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer1_Tick(object sender, EventArgs e)
        {
            // 调用了我们刚才创建的类中的getFigure方法
            // 要查找的figure图窗的名字为winName
            // 图窗要嵌入到的对象是panel1
            GetFigure.getFifure(winName, panel1);
        }

        /// <summary>
        /// "干就完了"按钮点击后执行的命令
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            // 调用dll,执行绘图的命令
            tst1.test();
        }

    }
}

结果展示

 

几个注意点:

1. 目标平台一定要改为x64

2. 可能会出现figure在空间中显示不全,解决方法

        (1)C#窗体默认打开方式为最大化,即WindowState属性设置为Maximized

        (2)调整timer1的执行周期和线程休眠的时间,这块地方我也不是很懂

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值