C#调用Matlab并嵌入到Winform窗体,可以任意尺寸画图,先看效果:
感谢该博主提供的思路:https://www.cnblogs.com/asxinyu/archive/2013/04/14/3020813.html
需要用到Windows API来设置窗体,用FindWindow查找图像窗体Figure1的句柄,使用SetParent设置Figure1父窗体为Winform的控件Panel,这样就把figure放进Winform里了,之所以放到panel控件里,而不是作为子窗体在winform里,是为了把它当做Winform的一个控件,便于布局。再使用MoveWindow移动到合适的位置,SetWindowLong去掉标题,不能通过边框改变大小,在Winform窗体SizeChanged事件里用MoveWindow改变Figure的大小,就能使Figure的尺寸和窗体同步改变。
关于第一次调用matlab出图慢问题,可以开个线程循环等待窗体的生成,使用多线程就不会造成UI线程卡顿了。
1.使用到的Windows API
#region //Windows API
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool BRePaint);
const int GWL_STYLE = -16;
const int WS_CAPTION = 0x00C00000;
const int WS_THICKFRAME = 0x00040000;
const int WS_SYSMENU = 0X00080000;
[DllImport("user32")]
private static extern int GetWindowLong(System.IntPtr hwnd, int nIndex);
[DllImport("user32")]
private static extern int SetWindowLong(System.IntPtr hwnd, int index, int newLong);
[DllImport("user32")]
private static extern int InvalidateRect(System.IntPtr hwnd, object rect, bool bErase);
/// 最大化窗口,最小化窗口,正常大小窗口
/// nCmdShow:0隐藏,3最大化,6最小化,5正常显示
///
[DllImport("user32.dll", EntryPoint = "ShowWindow")]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
#endregion
2.定义全局变量,窗体载入事件
public delegate void UpdateUI();//委托用于更新UI
Thread startload;//线程用于matlab窗体处理
MatlabFunction matlabFunction;//matlab编译的类
IntPtr figure1;//图像句柄
private void Form1_Load(object sender, EventArgs e)
{
//实例化线程,用来初次调用matlab,并把图像窗体放到winform
startload = new Thread(new ThreadStart(startload_run));
//开始线程
startload.Start();
}
3.线程执行的方法,每隔50ms查找一下figure窗体,找到嵌入到winform的panel控件里。
void startload_run()
{
int count50ms = 0;
//实例化matlab对象
matlabFunction = new MatlabFunction();
//调用方法画高斯分布函数图
matlabFunction.mysurf();//高斯分布函数
//循环查找figure1窗体
while (figure1 == IntPtr.Zero)
{
//查找matlab的Figure 1窗体
figure1 = FindWindow("SunAwtFrame", "Figure 1");
//延时50ms
Thread.Sleep(50);
count50ms++;
//20s超时设置
if (count50ms >= 400)
{
label1.Text = "matlab资源加载时间过长!";
return;
}
}
//跨线程,用委托方式执行
UpdateUI update = delegate
{
//隐藏标签
label1.Visible = false;
//设置matlab图像窗体的父窗体为panel
SetParent(figure1, panel1.Handle);
//获取窗体原来的风格
var style = GetWindowLong(figure1, GWL_STYLE);
//设置新风格,去掉标题,不能通过边框改变尺寸
SetWindowLong(figure1, GWL_STYLE, style & ~WS_CAPTION & ~WS_THICKFRAME);
//移动到panel里合适的位置并重绘
MoveWindow(figure1, 0, 0, panel1.Width + 20, panel1.Height + 40, true);
//调用显示窗体函数,隐藏再显示相当于刷新一下窗体
//radiobutton按钮使能
radioButton1.Enabled = true;
radioButton2.Enabled = true;
radioButton3.Enabled = true;
radioButton4.Enabled = true;
radioButton5.Enabled = true;
radioButton6.Enabled = true;
};
panel1.Invoke(update);
//再移动一次,防止显示错误
Thread.Sleep(100);
MoveWindow(figure1, 0, 0, panel1.Width + 20, panel1.Height + 40, true);
}
1.代码中的MatlabFunction 类是我自己封装的一些matlab演示函数,关于C#调用matlab这方面的网上很多,这里不作介绍。
2.工程使用vs2017和matlab2010b编译,程序运行需要 .net4.0和matlab2010或者matlab运行环境MCRInstaller。
1.C#调用matlab图像嵌入winform工程源码:点击下载
2.matlab运行环境MCRInstaller 7.14:点击下载