📄 guivc.txt
字号:
将MATLAB窗口画在VC的GUI上
山城棒棒儿军 @ 2004-06-29 17:18
将MATLAB窗口画在VC的GUI上
这几天,根据simwe论坛的scie提供的思路以及源代码,照着练习了一下。估计scie的matlab是6.1的,反正直接下载他的源代码,在我的机器上编译不通过。仔细设置断点,单步调试分析,总算找出了出错的地方,在于函数mlfHGInitialize( ),这个函数的调用方式不对。scie以及何强、何英的《MATLAB扩展编程》一书中讲到的调用方式都是mlfHGInitialize( NULL,NULL)。而我在libsglinit.cpp文件中看到的调用格式只有两种:
mwLibhgInit( const char *name, mexcpp_information info )
: init(1), mwLibInit( name, info ) { const char *p = "lib"; int argc = 1; mlfHGInitialize( &argc, &p ); }
mwLibhgInit(mexcpp_information info)
: init(1), mwLibInit(info) { const char *p = "lib"; int argc = 1; mlfHGInitialize( &argc, &p ); }
mwLibhgInit(mexcpp_information info, int* argc, const char** argv)
: init(1), mwLibInit(info) { mlfHGInitialize(argc, argv); }
~mwLibhgInit() { if (init) {mlfHGWaitForFiguresToDie(); mlfHGTerminate();} }
因此,照类似的调用方式修改源代码后,程序就能够正常运行了。
下面说说整个程序的实现步骤及其关键部分。
我自己的程序是采用matlab数学库编写的,没有利用对m文件进行预先编译的源文件。不过,可以写出m文件,进行编译,采用的命令是:
mcc -p -W mainhg libmwsglm.mlib drawSin.m
经过编译,得到cpp文件,利于自己找到需要的命令。譬如,在编译后的cpp文件中,我找到了Nfigure,Nclose等命令。在基于对话框的VC的MFC界面上画图。具体步骤是:
1. 在VC中建立一个基于对话框的MFC工程MatVcGUI;
2. 在Dialog上布置好相应的控件,其中主要有接收输入参数的Edit box控件、画图窗口(将MATLAB的figure放置位置的地方)的Group box控件(IDC_MATDRAW),以及运行按钮控件;
3. 编写绘图按钮的响应函数大致如下:
void CMatVcGUIDlg::OnDraw()
{
int bWait = 0;
if(tobool(isempty(h_a)))
{
// figure窗口的一些属性设置
char FigName[]="_Figure_";
double BKColor[] = {0.9,0.9,0.9};
char strVisible[] = "Off";
mwArray mwFigName(FigName);
mwArray mwBKColor(1,3,BKColor);
mwArray mwVisible(strVisible);
// 根据属性值创建axis对象句柄,稍后解释CreateAxis函数
h_a = CreateAxis(mwFigName,mwBKColor,mwVisible);
// Win32API函数FindWindow根据窗口名称寻找窗口句柄
HWND hFig=::FindWindow(NULL,FigName);
if(hFig == NULL)
{
AfxMessageBox("不能够创建Figure窗口,绘图失败!");
return;
}
// Win32API函数获取窗口属性,具体含义查找MSDN
long lStyle = ::GetWindowLong(hFig,GWL_STYLE);
// Win32API函数设置窗口属性,去掉标题栏与边框
::SetWindowLong(hFig, GWL_STYLE,lStyle&
(~WS_CAPTION) & (~WS_THICKFRAME));
// 设置窗口初始位置(反正窗口不可见的,无所谓)
::SetWindowPos(hFig,NULL,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE
| SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
RECT PlotRec;
// 获得绘图窗口的控件的窗口句柄
CWnd *PlotArea = GetDlgItem(IDC_MATDRAW);
// 得到绘图窗口控件(group box)的矩形区域位置
PlotArea->GetWindowRect(&PlotRec);
// 得到绘图窗口控件的宽与高
long Width = PlotRec.right - PlotRec.left;
long Height = PlotRec.bottom - PlotRec.top;
// 用Win32API函数将figure窗口(hFig)的父窗口设置为绘图窗口控件
::SetParent(hFig, PlotArea->GetSafeHwnd());
// 用Win32API函数设置figure窗口在绘图窗口控件中的相对位置及其显示风格
::SetWindowPos(hFig,NULL,1,7,Width-2,Height-10,
SWP_NOZORDER | SWP_NOACTIVATE);
// 绘制图形,稍后解释
DrawSin();
// 将axes的父figure窗口设置为可见,稍后解释
SetVisible(h_a,mwArray("On"));
bWait = 1;
// 进入窗口等待状态,运行了Vclose()函数后,将接着此句之后往下执行
mlfHGWaitForFiguresToDie();
}
if(bWait == 0)
DrawSin();
}
其中,涉及到的几个函数的应用的解释:
A. mwArray CMatVcGUIDlg::CreateAxis(mwArray strFigName,
mwArray BKColor, mwArray strVisible)
{
//hf = figure('NumberTitle','off','Name','testMixFigure','Menubar','none',
// 'Color',[0.8 0.8 0.8],'visible','off','DoubleBuffer','on');
mwArray h_f = figure(
mwArray("NumberTitle"),mwArray("Off"),
mwArray("Name"),strFigName,//strFigName,
mwArray("Menubar"),mwArray("None"),
mwArray("Color"),BKColor,
mwArray("Visible"),strVisible,//strVisible,
mwArray("DoubleBuffer"),mwArray("On"));
// h_a = axes('Parent', h_f, 'Box', 'On');
mwArray h_a = axes(mwArray("Parent"),h_f,mwArray("Box"),mwArray("On"));
return h_a;
}
B. void CMatVcGUIDlg::DrawSin()
{
UpdateData(TRUE);
if(tobool(isempty(h_a)))
OnDraw();
else{
double pi = 3.141592653589793;
// t=0:0.05:2;
mwArray t = colon(0,0.05,2);
// y = a* sin(2pi*w*t); 其中a,w是类成员变量,接收输入参数
// h_a是类成员变量,为创建的axes对象句柄;
mwArray y = a*sin(2*pi*w*t);
// plot(t, y, 'Parent', h_a);
Vplot(t,y,mwArray("Parent"),h_a);
}
}
C. void CMatVcGUIDlg::SetVisible(mwArray h_a, mwArray strVisible)
{
// h_f = get(h_a,"Parent");
mwArray h_f = get(h_a, mwArray("Parent"));
// set(h_f,"Visible",strVisible);
Vset(h_f, mwArray("Visible"), strVisible);
}
4. 在BOOL CMatVcGUIDlg::OnInitDialog()中加入如下代码,进行MATLAB的库的初始化:
h_a = empty();
libmmfileInitialize();
libmwsglmInitialize();
int argc;
argc=1;
const char *p = "lib";
mlfHGInitialize(&argc,&p);
5. 在void CMatVcGUIDlg::OnClose() 加入函数Vclose在退出程序的时候关闭打开的figure窗口。
void CMatVcGUIDlg::OnClose()
{
// close('all');
Vclose(mwArray("all"));
CDialog::OnClose();
}
6. 在void CMatVcGUIDlg::OnDestroy() 中加入如下代码中止MATLAB的一些库
libmwsglmTerminate();
libmmfileTerminate();
mlfHGTerminate();
总结
1. 用到的Win32API函数:
FindWindow()
GetWindowLong()
SetWindowLong()
SetWindowPos()
GetDlgItem()
GetWindowRect()
SetParent()
SetWindowPos()
具体的使用查找Win32API手册以及MSDN,其实还有很多其他的有用的API函数,有空了解了解Win32API手册。
2. 用到的MATLAB库函数主要有:
libmmfileInitialize();
libmwsglmInitialize();
mlfHGInitialize(&argc,&p);
mlfHGWaitForFiguresToDie();
libmwsglmTerminate();
libmmfileTerminate();
mlfHGTerminate();
figure,axes,plot,Vclose等函数,这些函数也可以有其他的一些形式。
具体的再libmwsglm.hpp中,其中还给出了很多其他函数的原型。在程序调试过程中出现一些错误的时候,应该可以自己想办法在这些头文件中寻找解决办法。涉及绘图的函数主要在libmwsglm.hpp,libsgl.hpp中,想必其他函数(数学库的)也应该在某些头文件中找到他们的声明。
3. mlfHGWaitForFiguresToDie()函数的作用
mlfHGWaitForFiguresToDie()函数使得窗口进入等待状态,没有他,生成的figure立即销毁,在Vclose all之后,返回到该函数的下一个语句接着往下执行。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -