.Net Micro Framework研究—应用实例

简介: 在前几篇关于.Net Micro Framework的研究文章中,我对它的绘图功能实不敢恭维,不过微软的MF开发人员很聪明,对位图方面的功能实现的就比较完善,这样做起图形应用来就不至于捉襟见肘了。前段时间用.Net Compact Framework实现了一个奥运场馆查询

试验平台:.Net Micro Framework 模拟器
在前几篇关于.Net Micro Framework的研究文章中,我对它的绘图功能实不敢恭维,不过微软的MF开发人员很聪明,对位图方面的功能实现的就比较完善,这样做起图形应用来就不至于捉襟见肘了。
前段时间用.Net Compact Framework实现了一个奥运场馆查询(相关文章请参见:http://blog.csdn.net/yefanqiu/archive/2007/11/13/1882835.aspx),现在我们用.Net Micro Framework也实现一个,看看哪一个更炫。
image.png
image.png

(效果是不是比用.Net Compact Framework做的还棒!)
我这个程序脱胎于MF的示例文件NewPresentation,不过我对它进行了大刀阔斧的改进,原程序在实现菜单时至少需要两套大小不同的图片,现在我已经修改成仅需要一套图片了,此外我对tinyfnt中文字库的创建程序又进行了优化,可以更高效、更完美的创建字库了(相关文章请参见:http://blog.csdn.net/yefanqiu/archive/2007/11/01/1862300.aspx)。
如优化前菜单添加代码:

MenuItem menuItem1 = new MenuItem(Resources.BitmapResources.Vertical_Stack_Panel_Icon_Small, Resources.BitmapResources.Vertical_Stack_Panel_Icon, "Vertical Stack Panel", Resources.BitmapResources.Canvas_Panel_Icon);
      MenuItem menuItem2 = new MenuItem(Resources.BitmapResources.Horizontal_Stack_Panel_Icon_Small, Resources.BitmapResources.Horizontal_Stack_Panel_Icon, "Horizontal Stack Panel", Resources.BitmapResources.Canvas_Panel_Icon);
      MenuItem menuItem3 = new MenuItem(Resources.BitmapResources.Canvas_Panel_Icon_Small, Resources.BitmapResources.Canvas_Panel_Icon, "Canvas Panel", Resources.BitmapResources.Canvas_Panel_Icon);
      MenuItem menuItem4 = new MenuItem(Resources.BitmapResources.Diagonal_Panel_Icon_Small, Resources.BitmapResources.Diagonal_Panel_Icon, "Diagonal Panel", Resources.BitmapResources.Canvas_Panel_Icon);
      MenuItem menuItem5 = new MenuItem(Resources.BitmapResources.Scrollable_Panel_Icon_Small, Resources.BitmapResources.Scrollable_Panel_Icon, "Scrollable Panel", Resources.BitmapResources.Canvas_Panel_Icon);
      MenuItem menuItem6 = new MenuItem(Resources.BitmapResources.Free_Drawing_Panel_Icon_Small, Resources.BitmapResources.Free_Drawing_Panel_Icon, "Free Drawing Panel", Resources.BitmapResources.Canvas_Panel_Icon);
 
      // Add each of the menu items to the menu item panel
      m_MenuItemPanel.AddMenuItem(menuItem1);
      m_MenuItemPanel.AddMenuItem(menuItem2);
      m_MenuItemPanel.AddMenuItem(menuItem3);
      m_MenuItemPanel.AddMenuItem(menuItem4);
      m_MenuItemPanel.AddMenuItem(menuItem5);
 m_MenuItemPanel.AddMenuItem(menuItem6);

优化后的代码:

   m_MenuItemPanel.AddMenuItem(new MenuItem(Resources.BitmapResources.M1, "国家体育馆"));
   m_MenuItemPanel.AddMenuItem(new MenuItem(Resources.BitmapResources.M2, "北京大学体育馆"));
   m_MenuItemPanel.AddMenuItem(new MenuItem(Resources.BitmapResources.M3, "国家游泳中心-水立方"));
   m_MenuItemPanel.AddMenuItem(new MenuItem(Resources.BitmapResources.M4, "国家体育场-鸟巢"));
   m_MenuItemPanel.AddMenuItem(new MenuItem(Resources.BitmapResources.M5, "北京射击馆"));
   m_MenuItemPanel.AddMenuItem(new MenuItem(Resources.BitmapResources.M6, "顺义奥林匹克水上公园"));

实事求是的说,MF示例实现的图形菜单动画比我在北京2008奥运场馆速查中实现的要好,它的更规范,更具有通用性。相关代码如下:

// 菜单类
internal sealed class MenuItemPanel : Control
{
    private int _currentChild = 0;
    private int _width;
    private int _height;
    private int _animationStep;
    private Color ForeColor;
    public ArrayList MenuItemList;
 
    public MenuItemPanel(int width, int height, Color ForeColor,Color BackColor)
    {
        //背景色
        Background = new SolidColorBrush(BackColor);
        //前景色
        this.ForeColor = ForeColor;
        //大小
        _width = width;
        _height = height;
        //菜单选项集合
        MenuItemList = new ArrayList();
    }
   
    //添加菜单选项
    public void AddMenuItem(MenuItem menuItem)
    {
        MenuItemList.Add(menuItem);
    }
 
   //当前菜单选项索引
    public int CurrentChild
    {
        get { return _currentChild; }
        set
        {
            if (value > _currentChild) _animationStep = maxStep;             // 向右移动
            else if (value < _currentChild) _animationStep = -maxStep;       // 向左移动
            else _animationStep = 0;                                         // 没有移动
 
            if (value >= MenuItemList.Count) value = 0;                      // 菜单项是一个环状结构
            if (value < 0) value = MenuItemList.Count - 1;                      
 
            //开始重绘
            if (_animationStep != 0)
            {
                _currentChild = value;
                Invalidate();                                                //开始移动
            }
        }
    }
 
    static public int maxStep = 5;      //动画帧数
    const int xOffsetSeparation =2;     //每个菜单项的间距
    const int timerInterval = 20;       //移动每一个帧之间的动画时间ms
 
    //绘制菜单
    public override void OnRender(DrawingContext dc)
    {
        base.OnRender(dc);
 
        //获得图片宽度
        int largeX = ((MenuItem)MenuItemList[0]).ImageWidth + xOffsetSeparation;
 
        //起始坐标
        int x = (_width / 2) - ((largeX * 2) + (largeX / 2));
        int y =22;
 
        //缩放比例
        int scale = 0;
 
        //缩放比例的步长
        int scaleOffset = System.Math.Abs(_animationStep);
 
        //X方向移动
        x += _animationStep * 5;
 
        //绘背景
        dc.DrawImage(Resources.GetBitmap(Resources.BitmapResources.Main), 0, 0);
 
        #region //绘菜单图像
        for (int i = _currentChild - 2; i < _currentChild + 3; i++)
        {
            if (i == _currentChild) //中间图像
            {
                scale = maxStep - scaleOffset;
            }
            else //两边图像
            {
                if ((_animationStep < 0 && i == _currentChild + 1) || (_animationStep > 0 && i == _currentChild - 1))
                    scale = scaleOffset;
                else
                    scale = 0;
            }
 
            //当前菜单项
            MenuItem menuItem = null;
            if (i < 0) menuItem = (MenuItem)MenuItemList[MenuItemList.Count + i];
            else if (i > MenuItemList.Count - 1) menuItem = (MenuItem)MenuItemList[i - MenuItemList.Count];
            else menuItem = (MenuItem)MenuItemList[i];
 
            menuItem.Render(dc, x, y, scale);
            x += largeX;
        }
        #endregion
 
        #region //写菜单文本
        if (_width > 0)
        {
            int step = 20;
            int row = 125;
            if (_width < _height) step = 40;
 
            //写说明
            string text = ((MenuItem)MenuItemList[_currentChild]).Description;
            dc.DrawText(ref text, Resources.GetFont(Resources.FontResources.china2008), ForeColor, 10, row, _width - 20, step, TextAlignment.Center, TextTrimming.None);
        }
        #endregion
 
        //启动动画时钟
        StartAnimationTimer();
    }
 
    private DispatcherTimer _animationTimer;
    private void StartAnimationTimer()
    {
        if (_animationStep != 0)
        {
            if (_animationTimer == null)
            {
                _animationTimer = new DispatcherTimer(this.Dispatcher);
                _animationTimer.Interval = new TimeSpan(0, 0, 0, 0, timerInterval);
                //每隔一段时间触发该事件
                _animationTimer.Tick += new EventHandler(OnAnimationTimer);
            }
            _lastTick = DateTime.Now.Ticks;
            _animationTimer.Start();
        }
    }
    long _lastTick = 0;
    private void OnAnimationTimer(object o, EventArgs e)
    {
        _animationTimer.Stop();
        long ms = ((DateTime.Now.Ticks - _lastTick) / 10000);
        _lastTick = DateTime.Now.Ticks;
        int increment = (int)(ms / timerInterval);
 
        if (increment < 1) increment = 1;
        else if (increment > maxStep) increment = maxStep;
 
        if (_animationStep < 0) _animationStep += increment;
        else if (_animationStep > 0) _animationStep -= increment;
 
        //重新触发OnRender函数的执行
        Invalidate();
    }
 
    //窗体可用尺寸
    protected override void MeasureOverride(int availableWidth, int availableHeight, out int desiredWidth, out int desiredHeight)
    {
        desiredWidth = _width;
        desiredHeight = _height;
    }
}
 
// 菜单选项类
internal sealed class MenuItem : Control
{
    private Bitmap _image;         // 菜单图标
    private string _description;   // 菜单说明
    private int[] _widthSteps;     // 宽度步长数组
    private int[] _heightSteps;    // 高度步长数组
    public int ImageWidth;         // 图像宽度
    public int ImageHeight;        // 图像高度
    private float fScale = (float)0.8;   // 缩小因子
    public int SmallWidth;         // 缩小后的宽度
    public int SmallHeight;        // 缩小后的高度
 
    public MenuItem()
    {
    }
    public MenuItem(Resources.BitmapResources rBitmap, string description)
    {
        //菜单图像
        _image = Resources.GetBitmap(rBitmap);
       
        //图像尺寸
        ImageWidth = _image.Width;
        ImageHeight = _image.Height;
        SmallWidth = (int)(fScale * ImageWidth);
        SmallHeight = (int)(fScale * ImageHeight);
 
        //菜单说明
        _description = description;
 
        //创建中间动画帧尺寸数组
        _widthSteps = new int[MenuItemPanel.maxStep];
        _heightSteps = new int[MenuItemPanel.maxStep];
 
        //动画变化总大小
        int wDiff = ImageWidth - SmallWidth;
        int hDiff = SmallHeight - SmallHeight;
 
        //保存每次变化的大小
        for (int i = 1; i < MenuItemPanel.maxStep; i++)
        {
            _widthSteps[i] = (wDiff / MenuItemPanel.maxStep) * i;
            _heightSteps[i] = (hDiff / MenuItemPanel.maxStep) * i;
        }
 
    }
    //菜单说明
    public string Description
    {
        get { return _description; }
        set { _description = value; }
    }
    //菜单绘制
    public void Render(DrawingContext dc, int x, int y, int scale)
    {
        // 图像必须存在
        if (_image != null)
        {
            if (scale == MenuItemPanel.maxStep)
            {
                Width = ImageWidth;
                Height = ImageHeight;
                dc.DrawRectangle(new SolidColorBrush(Color.Black), new Pen(Color.Black), x+2, y+2, Width, Height);
                dc.DrawImage(_image, x, y);
            }
            else
            {
                if (scale == 0)
                {
                    Width = SmallWidth;
                    Height = SmallHeight;
                    x += ((ImageWidth - Width) / 2);
                    y += ((ImageHeight - Height) / 2);
                    dc.DrawRectangle(new SolidColorBrush(Color.Black), new Pen(Color.Black), x + 2, y + 2, Width, Height);
                    dc.Bitmap.StretchImage(x, y, _image, Width, Height, 255);
                 }
                else
                {
                    int wDiff = ImageWidth - SmallWidth;
                    int hDiff = SmallHeight - SmallHeight;
                    Width = SmallWidth + _widthSteps[scale];
                    Height = SmallHeight + _heightSteps[scale];
                    x += ((ImageWidth - Width) / 2);
                    y += ((ImageHeight - Height) / 2);
                    dc.DrawRectangle(new SolidColorBrush(Color.Black), new Pen(Color.Black), x + 2, y + 2, Width, Height);
                    dc.Bitmap.StretchImage(x, y, _image, Width, Height, 255);
                }
            }
        }
    }
}

本程序的源代码下载链接:http://www.sky-walker.com.cn/yefan/SourceCode/YFPresentation.rar
有条件的网友可以和微软提供的示例NewPresentation对比一下看看,也许更能看出它们的异同。有时间我在把这个类封装成一个控件(基于.Net CF),这样在windows和wince平台就都能使用了。

相关文章
|
存储 Shell Linux
快速上手基于 BaGet 的脚本自动化构建 .net 应用打包
本文介绍了如何使用脚本自动化构建 `.net` 应用的 `nuget` 包并推送到指定服务仓库。首先概述了 `BaGet`——一个开源、轻量级且高性能的 `NuGet` 服务器,支持多种存储后端及配置选项。接着详细描述了 `BaGet` 的安装、配置及使用方法,并提供了 `PowerShell` 和 `Bash` 脚本实例,用于自动化推送 `.nupkg` 文件。最后总结了 `BaGet` 的优势及其在实际部署中的便捷性。
552 10
|
5月前
|
Go
在golang中发起http请求以获取访问域名的ip地址实例(使用net, httptrace库)
这只是追踪我们的行程的简单方法,不过希望你跟着探险家的脚步,即使是在互联网的隧道中,也可以找到你想去的地方。接下来就是你的探险之旅了,祝你好运!
189 26
|
9月前
|
C# Android开发 iOS开发
2025年全面的.NET跨平台应用框架推荐
2025年全面的.NET跨平台应用框架推荐
348 23
|
8月前
|
人工智能 机器人
D1net阅闻 | 谷歌DeepMind研究发现LLM新特性
D1net阅闻 | 谷歌DeepMind研究发现LLM新特性
|
11月前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
174 5
|
11月前
|
JSON 算法 安全
JWT Bearer 认证在 .NET Core 中的应用
【10月更文挑战第30天】JWT(JSON Web Token)是一种开放标准,用于在各方之间安全传输信息。它由头部、载荷和签名三部分组成,用于在用户和服务器之间传递声明。JWT Bearer 认证是一种基于令牌的认证方式,客户端在请求头中包含 JWT 令牌,服务器验证令牌的有效性后授权用户访问资源。在 .NET Core 中,通过安装 `Microsoft.AspNetCore.Authentication.JwtBearer` 包并配置认证服务,可以实现 JWT Bearer 认证。具体步骤包括安装 NuGet 包、配置认证服务、启用认证中间件、生成 JWT 令牌以及在控制器中使用认证信息
391 2
|
数据采集 JSON API
.NET 3.5 中 HttpWebRequest 的核心用法及应用
【9月更文挑战第7天】在.NET 3.5环境下,HttpWebRequest 类是处理HTTP请求的一个核心组件,它封装了HTTP协议的细节,使得开发者可以方便地发送HTTP请求并接收响应。本文将详细介绍HttpWebRequest的核心用法及其实战应用。
473 6
|
10月前
|
监控 前端开发 API
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
237 5
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
200 7