【原創】Matlab.NET混合編程調用Figure窗體


              本博客所有文章分類的總目錄:【總目錄】本博客博文總目錄-實時更新

      Matlab和C#混合編程文章目錄 :【目錄】Matlab和C#混合編程文章目錄

1.前言

做Matlab.NET混合編程好幾年了,雖然Matlab很多函數忘記得差不多了,但基本的東西還是能熟練使用。特別是在C#調用Matlab函數這方面,積累了比較多的經驗,和使用經驗密切相關。根據很多朋友經常遇到的WinForm窗體混編調用MatlabFigure的問題,花了一些功夫,把這個封裝為C#控件,使得大家可以很容易調用MatlabFigure了。 

2.Matlab.NET混合編程概述 

這方面就不仔細闡述了,主要是利用MatlabDeploytool工具將m函數編譯為.NET程序集,然后在C#中調用的過程。然后程序可以在安裝MCR的機器上運行,這個過程如果懂MatalbC#的人,其實看看幫助很容易理解,也有例子。在這里不仔細講解。2012年,我錄制過國內第一套Matlab.NET混合編程視頻教程,與ILoveMatab論壇的管理員Math商量之后,已經免費開放,大家去論壇下載即可。 

混合編程最重要的是利用matlab的科學計算功能和強大的工具箱函數。但目前很多學生做這個,都只是為了簡單的繪圖,.NET繪圖其實也很強大。很多人混編,就想把Matlab繪圖產生的FigureWinForm窗體中顯示,但是Matlab並沒有提供直接的解決方法。只能找另外的方法,我目前想到的有2種: 

1.先把Figure保存為圖片,然后WinForm窗體去讀取圖片; 

2.利用Windows API 技術,動態的獲取窗體句柄,然后嵌入到WinForm中。

 第一種方法很容易想到,也很容易解決,就不仔細講了。

 第二中方法懂開發的人一般能想得到,但是學生一般不是很容易想到,即使想到,做出來也很難。

 下面我就把第二種方法的實現過程講解一下。

3.MatlabFigure控件的封裝過程

控件的設計思想:

1.能夠在WinForm桌面程序調用Matlab混編產生的Figure,主要是根據Figure的標題文字

2.Figure嵌入在控件C中,C的大小應該和Figure的大小一致,程序只需要關心控件的大小狀態就可以

3.初始化的時候,Figure的大小根據控件C的大小進行調整

4.Figure的大小將隨着控件的大小改變而改變

其實根據上面闡述的原理,精通Windows API的人很快就可以解決,主要就這么幾個函數,我貼一下代碼: 

 1 DllImport("user32.dll")]
 2 public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
 3 
 4 [DllImport("user32.dll")]
 5 public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
 6 
 7 [DllImport("user32.dll")]
 8 public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
 9 
10 [StructLayout(LayoutKind.Sequential)]
11 public struct RECT
12 {
13     public int left;
14     public int top;
15     public int right;
16     public int bottom;
17 }
18 
19 [DllImport("user32.dll")]
20 public static extern int GetClientRect(IntPtr hwnd, ref RECT rc);
21 
22 [DllImport("user32.dll", EntryPoint = "SendMessage")]
23 private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
24 
25 /// <summary>最大化窗口,最小化窗口,正常大小窗口
26 /// nCmdShow:0隱藏,3最大化,6最小化,5正常顯示
27 /// </summary>
28 [DllImport("user32.dll", EntryPoint = "ShowWindow")]
29 public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
30 
31 [DllImport("user32.dll")]
32 public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
33 
34 
35 public class _SW
36 {
37     public const int SW_HIDE = 0;
38     public const int SW_SHOWNORMAL = 1;
39     public const int SW_SHOWMINIMIZED = 2;
40     public const int SW_SHOWMAXIMIZED = 3;
41     public const int SW_MAXIMIZE = 3;
42     public const int SW_SHOWNOACTIVATE = 4;
43     public const int SW_SHOW = 5;
44     public const int SW_MINIMIZE = 6;
45     public const int SW_SHOWMINNOACTIVE = 7;
46     public const int SW_SHOWNA = 8;
47     public const int SW_RESTORE = 9;
48 }

 

在Figure窗體顯示后,通過FindWindow("SunAwtFrame", figureTitleName);來動態獲取窗體的句柄,注意Figure的類型都是”SunAwtFrame”,這個要專業點的軟件查出來。獲取窗體之后,然后通過 SetParent和MoveWindow來設置子窗體,並改變窗體的大小。控件的詳細代碼就不貼了,主要是上面的封裝過程吧,把邏輯搞懂了,很容易。由於源代碼是給商業項目使用,暫時不開放。貼一段窗體尋找的代碼,為了防止Figure還未顯示,程序已經在尋找,特意加了一個延時: 

 1 #region 尋找窗體
 2 int num = 0 ;
 3 while (num <5 )
 4 {
 5     num++;
 6     //若找不到窗體,循環5次,每次100ms
 7     if (wf == IntPtr.Zero)
 8     {
 9         wf = FindWindow("SunAwtFrame", figureTitleName);                    
10         Thread.Sleep(timeSpan);
11     }
12     else
13     {   //找到隱藏起來
14         ShowWindow(wf, _SW.SW_HIDE);break;
15     }
16 }           
17 if (wf == IntPtr.Zero)
18 {
19     MessageBox.Show("無法獲取Figure窗體,請確認信息是否正確");
20     return;
21 }
22 #endregion

 看看效果圖:

特意新建了一個混編QQ交流群:154957583,有經驗的朋友可以一起探討。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM