?? guivc.txt
字號:
將MATLAB窗口畫在VC的GUI上
山城棒棒兒軍 @ 2004-06-29 17:18
將MATLAB窗口畫在VC的GUI上
這幾天,根據(jù)simwe論壇的scie提供的思路以及源代碼,照著練習(xí)了一下。估計scie的matlab是6.1的,反正直接下載他的源代碼,在我的機(jī)器上編譯不通過。仔細(xì)設(shè)置斷點,單步調(diào)試分析,總算找出了出錯的地方,在于函數(shù)mlfHGInitialize( ),這個函數(shù)的調(diào)用方式不對。scie以及何強(qiáng)、何英的《MATLAB擴(kuò)展編程》一書中講到的調(diào)用方式都是mlfHGInitialize( NULL,NULL)。而我在libsglinit.cpp文件中看到的調(diào)用格式只有兩種:
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();} }
因此,照類似的調(diào)用方式修改源代碼后,程序就能夠正常運行了。
下面說說整個程序的實現(xiàn)步驟及其關(guān)鍵部分。
我自己的程序是采用matlab數(shù)學(xué)庫編寫的,沒有利用對m文件進(jìn)行預(yù)先編譯的源文件。不過,可以寫出m文件,進(jìn)行編譯,采用的命令是:
mcc -p -W mainhg libmwsglm.mlib drawSin.m
經(jīng)過編譯,得到cpp文件,利于自己找到需要的命令。譬如,在編譯后的cpp文件中,我找到了Nfigure,Nclose等命令。在基于對話框的VC的MFC界面上畫圖。具體步驟是:
1. 在VC中建立一個基于對話框的MFC工程MatVcGUI;
2. 在Dialog上布置好相應(yīng)的控件,其中主要有接收輸入?yún)?shù)的Edit box控件、畫圖窗口(將MATLAB的figure放置位置的地方)的Group box控件(IDC_MATDRAW),以及運行按鈕控件;
3. 編寫繪圖按鈕的響應(yīng)函數(shù)大致如下:
void CMatVcGUIDlg::OnDraw()
{
int bWait = 0;
if(tobool(isempty(h_a)))
{
// figure窗口的一些屬性設(shè)置
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);
// 根據(jù)屬性值創(chuàng)建axis對象句柄,稍后解釋CreateAxis函數(shù)
h_a = CreateAxis(mwFigName,mwBKColor,mwVisible);
// Win32API函數(shù)FindWindow根據(jù)窗口名稱尋找窗口句柄
HWND hFig=::FindWindow(NULL,FigName);
if(hFig == NULL)
{
AfxMessageBox("不能夠創(chuàng)建Figure窗口,繪圖失敗!");
return;
}
// Win32API函數(shù)獲取窗口屬性,具體含義查找MSDN
long lStyle = ::GetWindowLong(hFig,GWL_STYLE);
// Win32API函數(shù)設(shè)置窗口屬性,去掉標(biāo)題欄與邊框
::SetWindowLong(hFig, GWL_STYLE,lStyle&
(~WS_CAPTION) & (~WS_THICKFRAME));
// 設(shè)置窗口初始位置(反正窗口不可見的,無所謂)
::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)的矩形區(qū)域位置
PlotArea->GetWindowRect(&PlotRec);
// 得到繪圖窗口控件的寬與高
long Width = PlotRec.right - PlotRec.left;
long Height = PlotRec.bottom - PlotRec.top;
// 用Win32API函數(shù)將figure窗口(hFig)的父窗口設(shè)置為繪圖窗口控件
::SetParent(hFig, PlotArea->GetSafeHwnd());
// 用Win32API函數(shù)設(shè)置figure窗口在繪圖窗口控件中的相對位置及其顯示風(fēng)格
::SetWindowPos(hFig,NULL,1,7,Width-2,Height-10,
SWP_NOZORDER | SWP_NOACTIVATE);
// 繪制圖形,稍后解釋
DrawSin();
// 將axes的父figure窗口設(shè)置為可見,稍后解釋
SetVisible(h_a,mwArray("On"));
bWait = 1;
// 進(jìn)入窗口等待狀態(tài),運行了Vclose()函數(shù)后,將接著此句之后往下執(zhí)行
mlfHGWaitForFiguresToDie();
}
if(bWait == 0)
DrawSin();
}
其中,涉及到的幾個函數(shù)的應(yīng)用的解釋:
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是類成員變量,接收輸入?yún)?shù)
// h_a是類成員變量,為創(chuàng)建的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()中加入如下代碼,進(jìn)行MATLAB的庫的初始化:
h_a = empty();
libmmfileInitialize();
libmwsglmInitialize();
int argc;
argc=1;
const char *p = "lib";
mlfHGInitialize(&argc,&p);
5. 在void CMatVcGUIDlg::OnClose() 加入函數(shù)Vclose在退出程序的時候關(guān)閉打開的figure窗口。
void CMatVcGUIDlg::OnClose()
{
// close('all');
Vclose(mwArray("all"));
CDialog::OnClose();
}
6. 在void CMatVcGUIDlg::OnDestroy() 中加入如下代碼中止MATLAB的一些庫
libmwsglmTerminate();
libmmfileTerminate();
mlfHGTerminate();
總結(jié)
1. 用到的Win32API函數(shù):
FindWindow()
GetWindowLong()
SetWindowLong()
SetWindowPos()
GetDlgItem()
GetWindowRect()
SetParent()
SetWindowPos()
具體的使用查找Win32API手冊以及MSDN,其實還有很多其他的有用的API函數(shù),有空了解了解Win32API手冊。
2. 用到的MATLAB庫函數(shù)主要有:
libmmfileInitialize();
libmwsglmInitialize();
mlfHGInitialize(&argc,&p);
mlfHGWaitForFiguresToDie();
libmwsglmTerminate();
libmmfileTerminate();
mlfHGTerminate();
figure,axes,plot,Vclose等函數(shù),這些函數(shù)也可以有其他的一些形式。
具體的再libmwsglm.hpp中,其中還給出了很多其他函數(shù)的原型。在程序調(diào)試過程中出現(xiàn)一些錯誤的時候,應(yīng)該可以自己想辦法在這些頭文件中尋找解決辦法。涉及繪圖的函數(shù)主要在libmwsglm.hpp,libsgl.hpp中,想必其他函數(shù)(數(shù)學(xué)庫的)也應(yīng)該在某些頭文件中找到他們的聲明。
3. mlfHGWaitForFiguresToDie()函數(shù)的作用
mlfHGWaitForFiguresToDie()函數(shù)使得窗口進(jìn)入等待狀態(tài),沒有他,生成的figure立即銷毀,在Vclose all之后,返回到該函數(shù)的下一個語句接著往下執(zhí)行。
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -