试验平台:.Net Micro Framework 模拟器

由于Digi提供的开发板没有LCD显示屏,所以有关绘图方面的操作,只好在模拟器上进行了。

如果大家参加了9月18日在北京召开的.Net Micro Framework2007技术大会,并且耐心等到最后,大会的礼品U盘里就有.Net Micro Framework的开发包。

不过微软这方面对.Net Micro Framework更新很快,如果你到网站上下载,最新的.Net Micro Framework SDK2.0 SP1已经发布了。

下载链接:http://www.microsoft.com/downloads/details.aspx?familyid=32f5df20-6c95-4fe8-a76c-0ed56a839ad2&displaylang=en

 

如果你用的是大会优盘的开发包,你会发现,微软真是萝卜快了不洗泥,模拟器不仅粗糙,而且按钮并没有完全拉开,下半截的按钮的圆弧不见了(可参见我以前写的文章:http://yfsoft.blog.51cto.com/1635641/323413)。如果你下载最新的开放包,这个问题已经解决了(看来微软的战略就是快速抢占市场,问题以后在一一修补)。

无论怎样模拟器还是非常难看,估计n个版本之后,才能推出很漂亮的模拟器。正好微软SDK开发包中,有模拟器外壳的开发程序,所以练练手,给.Net Micro Framework武装一个“顶级模拟器”。

下面就是我开发的模拟器(应该称外壳)和微软自带的模拟器比较图,我们先睹为快,接下来我就说说是如何做的。

.Net Micro Framework研究—模拟器改造_第1张图片


(图:MF071030001.jpg)

       .Net Micro Framework SDK中的示例程序里就有一个模拟器外壳开发程序,也就是“SampleEmulator”示例程序,它是一个典型的C#程序(只不过引用了与.Net Micro Framework相关的几个库),你编译成功后,直接运行,它会弹出下面的提示框。

         

.Net Micro Framework研究—模拟器改造_第2张图片

 

    (图:MF071030004.jpg)

    其实它是需要输入如下命令行参数的:

    "/load:%ProgramFiles%\Microsoft .NET Micro Framework\v2.0.3036\Assemblies\Microsoft.SPOT.TinyCore.pe" "/load:%ProgramFiles%\Microsoft .NET Micro Framework\v2.0.3036\Assemblies\Microsoft.SPOT.Hardware.pe" "/load:..\..\..\..\TemperatureSample\TemperatureSample\bin\Debug\TemperatureSample.pe" "/load:%ProgramFiles%\Microsoft .NET Micro Framework\v2.0.3036\Assemblies\Microsoft.SPOT.Graphics.pe" "/load:%ProgramFiles%\Microsoft .NET Micro Framework\v2.0.3036\Assemblies\mscorlib.pe" "/load:%ProgramFiles%\Microsoft .NET Micro Framework\v2.0.3036\Assemblies\Microsoft.SPOT.Native.pe"

      

     我们先不管这些,我们希望以后.Net Micro Framework程序运行的时候,加载的是我们的模拟器,所以我们要找出系统模拟器的位置,功夫不负有心人,竟然在这个位置:

     C:\Program Files\Microsoft .NET Micro Framework\v2.0.3036\Tools

     文件名:Microsoft.SPOT.Emulator.Sample.SampleEmulator.exe

     把我们编译好的模拟器程序(最好先和系统自带的有所不同)覆盖掉该程序,运行其它程序试试,果然加载的是我们新生成的模拟器。

     好了,看看我是如何做的。

     其实,微软提供的模拟器外壳程序比较复杂(具体代码请下载开发包后自行查看),所以我不仅要换肤,还要对代码重新进行整理。成绩还是斐然的,如button控件,资源图片等等统统去掉了,仅添加了一个p_w_picpathlist控件,就在窗体函数里实现了该功能。

       详细代码如下,有兴趣的朋友自己看。


 

   
   
   
   
  1. using System;  
  2.  
  3. using System.Drawing;  
  4.  
  5. using System.Threading;  
  6.  
  7. using System.Windows.Forms;  
  8.  
  9.    
  10.  
  11. using Microsoft.SPOT.Emulator;  
  12.  
  13. using Microsoft.SPOT.Hardware;  
  14.  
  15. using System.Drawing.Drawing2D;  
  16.  
  17.    
  18.  
  19. namespace Microsoft.SPOT.Emulator.Sample  
  20.  
  21. {  
  22.  
  23.     ///   
  24.  
  25.     /// This is the UI for the LCD sample  
  26.  
  27.     ///   
  28.  
  29.     public partial class SampleEmulatorForm : Form  
  30.  
  31.     {  
  32.  
  33.         Emulator _emulator;  
  34.  
  35.         //叶帆添加  
  36.  
  37.         Gpio.GpioPort[] _port=new Microsoft.SPOT.Emulator.Gpio.GpioPort[5];  
  38.  
  39.         delegate void PortWriteDelegate(bool fState);  
  40.  
  41.         int intIndex = 0;  
  42.  
  43.         bool[] _pressed = new bool[] {false,false,false,false,false };  
  44.  
  45.    
  46.  
  47.         public SampleEmulatorForm(Emulator emulator)  
  48.  
  49.         {  
  50.  
  51.             _emulator = emulator;  
  52.  
  53.             // Initializing the component on the UI form  
  54.  
  55.             InitializeComponent();  
  56.  
  57.         }  
  58.  
  59.         protected override void OnLoad(EventArgs e)  
  60.  
  61.         {  
  62.  
  63.             //Give the buttonCollection focus to allow it to handle keyboard events  
  64.  
  65.             //this.buttonCollection.Select();              
  66.  
  67.             base.OnLoad(e);  
  68.  
  69.         }  
  70.  
  71.         public void OnInitializeComponent()  
  72.  
  73.         {  
  74.  
  75.             //initialize the lcd control with the lcd emulator component  
  76.  
  77.             this.lcdDisplay.LcdDisplay = _emulator.LcdDisplay;  
  78.  
  79.    
  80.  
  81.             //叶帆添加  
  82.  
  83.             _port[0] = _emulator.FindComponentById("Pin_Select"as Gpio.GpioPort;  
  84.  
  85.             _port[1] = _emulator.FindComponentById("Pin_Up"as Gpio.GpioPort;  
  86.  
  87.             _port[2] = _emulator.FindComponentById("Pin_Left"as Gpio.GpioPort;  
  88.  
  89.             _port[3] = _emulator.FindComponentById("Pin_Down"as Gpio.GpioPort;  
  90.  
  91.             _port[4] = _emulator.FindComponentById("Pin_Right"as Gpio.GpioPort;  
  92.  
  93.         }  
  94.  
  95.         //按下叶帆添加  
  96.  
  97.         private void picKey_MouseDown(object sender, MouseEventArgs e)  
  98.  
  99.         {  
  100.  
  101.             //OK  
  102.  
  103.             Rectangle rect = new Rectangle(31, 40, 70, 50);  
  104.  
  105.             intIndex = 0;         
  106.  
  107.             if (rect.Contains(e.X, e.Y))  
  108.  
  109.             {  
  110.  
  111.                 intIndex = 0;  
  112.  
  113.             }  
  114.  
  115.             //UP           
  116.  
  117.             GraphicsPath path = new GraphicsPath();  
  118.  
  119.             path.AddPolygon(new Point[] {new Point(0,0),new Point(129,0),new Point(100,40),new Point(30,40) });  
  120.  
  121.             if (path.IsVisible(e.X, e.Y))  
  122.  
  123.             {  
  124.  
  125.                 intIndex = 1;  
  126.  
  127.             }  
  128.  
  129.             //LEFT  
  130.  
  131.             path.Reset();  
  132.  
  133.             path.AddPolygon(new Point[] { new Point(0, 0), new Point(0, 130), new Point(31, 90), new Point(31, 40) });  
  134.  
  135.             if (path.IsVisible(e.X, e.Y))  
  136.  
  137.             {  
  138.  
  139.                 intIndex = 2;  
  140.  
  141.             }  
  142.  
  143.             //DOWN  
  144.  
  145.             path.Reset();  
  146.  
  147.             path.AddPolygon(new Point[] { new Point(0, 130), new Point(129, 130), new Point(100, 90), new Point(30, 90) });  
  148.  
  149.             if (path.IsVisible(e.X, e.Y))  
  150.  
  151.             {  
  152.  
  153.                 intIndex = 3;  
  154.  
  155.             }  
  156.  
  157.             //RIGHT  
  158.  
  159.             path.Reset();  
  160.  
  161.             path.AddPolygon(new Point[] { new Point(129, 0), new Point(129, 130), new Point(100, 90), new Point(100, 40) });  
  162.  
  163.             if (path.IsVisible(e.X, e.Y))  
  164.  
  165.             {  
  166.  
  167.                 intIndex = 4;  
  168.  
  169.             }  
  170.  
  171.             picKey.BackgroundImage = imgKey.Images[intIndex+1];  
  172.  
  173.             OnButtonStateChanged(intIndex, true);  
  174.  
  175.         }  
  176.  
  177.         //弹起叶帆添加  
  178.  
  179.         private void picKey_MouseUp(object sender, MouseEventArgs e)  
  180.  
  181.         {  
  182.  
  183.             picKey.BackgroundImage = imgKey.Images[0];  
  184.  
  185.             OnButtonStateChanged(intIndex, false);  
  186.  
  187.         }  
  188.  
  189.         //按下(无法捕捉方向键)  
  190.  
  191.         private void SampleEmulatorForm_KeyDown(object sender, KeyEventArgs e)  
  192.  
  193.         {  
  194.  
  195.         }  
  196.  
  197.         //抬起  
  198.  
  199.         private void SampleEmulatorForm_KeyUp(object sender, KeyEventArgs e)  
  200.  
  201.         {  
  202.  
  203.             picKey.BackgroundImage = imgKey.Images[0];  
  204.  
  205.             OnButtonStateChanged(intIndex, false);  
  206.  
  207.         }  
  208.  
  209.         //捕捉方向键  
  210.  
  211.         protected override bool ProcessDialogKey(Keys keyData)  
  212.  
  213.         {  
  214.  
  215.             switch (keyData)  
  216.  
  217.             {  
  218.  
  219.                 case Keys.Enter:  
  220.  
  221.                     intIndex = 0;  
  222.  
  223.                     break;  
  224.  
  225.                 case Keys.Up:  
  226.  
  227.                     intIndex = 1;  
  228.  
  229.                     break;  
  230.  
  231.                 case Keys.Left:  
  232.  
  233.                     intIndex = 2;  
  234.  
  235.                     break;  
  236.  
  237.                 case Keys.Down:  
  238.  
  239.                     intIndex = 3;  
  240.  
  241.                     break;  
  242.  
  243.                 case Keys.Right:  
  244.  
  245.                     intIndex = 4;  
  246.  
  247.                     break;  
  248.  
  249.             }  
  250.  
  251.             picKey.BackgroundImage = imgKey.Images[intIndex + 1];  
  252.  
  253.             OnButtonStateChanged(intIndex, true);  
  254.  
  255.             return base.ProcessDialogKey(keyData);  
  256.  
  257.         }  
  258.  
  259.    
  260.  
  261.         //按键状态改变  
  262.  
  263.         private void OnButtonStateChanged(int index,bool pressed)  
  264.  
  265.         {  
  266.  
  267.             if (_port[index] != null)  
  268.  
  269.             {  
  270.  
  271.                 if (_pressed[index] != pressed)  
  272.  
  273.                 {  
  274.  
  275.                     _pressed[index] = pressed;  
  276.  
  277.                     bool val = false;  
  278.  
  279.                     switch (_port[index].Resistor)  
  280.  
  281.                     {  
  282.  
  283.                         case Microsoft.SPOT.Emulator.Gpio.GpioResistorMode.Disabled:  
  284.  
  285.                         case Microsoft.SPOT.Emulator.Gpio.GpioResistorMode.PullUp:  
  286.  
  287.                             val = pressed;  
  288.  
  289.                             break;  
  290.  
  291.                         case Microsoft.SPOT.Emulator.Gpio.GpioResistorMode.PullDown:  
  292.  
  293.                             val = !pressed;  
  294.  
  295.                             break;  
  296.  
  297.                     }  
  298.  
  299.                     //Marshal to MicroFramework thread.    
  300.  
  301.                     //No need to wait for a response.  Just post the message  
  302.  
  303.                     _port[index].BeginInvoke(new PortWriteDelegate(_port[index].Write), !val);  
  304.  
  305.                 }  
  306.  
  307.             }  
  308.  
  309.         }         
  310.  
  311.     }  
  312.  
  313. }  
  314.  

 

在下面的网站上,我们还可以下载最新的.Net Micro Framework示例程序,其中“NewPresentation”程序比“Presentation”已高了一个层次,如下图: 

 

.Net Micro Framework研究—模拟器改造_第3张图片


    (图:MF071030002.jpg)

此外这个温度显示的示例程序也不错,我们可以用上下按钮修改温度值,如下图。

            

.Net Micro Framework研究—模拟器改造_第4张图片

(图:MF071030003.jpg)

 

新示例下载链接:  http://msdn2.microsoft.com/en-us/embedded/bb267253.aspx

   

不过总体来说,示例程序还是很简陋的,有时间我自己做一个最炫的(当然网友有做得更好的,别忘了与我分享)。

 

附录:经典.Net Micro Framework应用欣赏

.Net Micro Framework研究—模拟器改造_第5张图片


     (图:MF071030005.jpg)

我做的模拟器外壳,就是从上图“偷”来的J,不过按钮单击效果倒是费了我不少周折。

想想看,用.Net Micro Framework开发MP3/MP4,电子词典该是多么容易和简单,并且效果一定很炫。(上网查了查 Digi核心小模块要$199,几千两银子呢,介入的厂商越多,相信硬件平台一定会越来越便宜的)。