叶帆工作室

嵌入式开发爱好者(十年开发经验,精通C/C++/VC/VB/C#...)

刘洪峰ID:yefanqiu
504433次访问,排名80好友0人,关注者137
微软MVP / CSDN 2008十大MVB/MSDN中文技术论坛版主
yefanqiu的文章
原创 215 篇
翻译 0 篇
转载 3 篇
评论 1057 篇
叶帆的公告
本博客原创文章,作者保留一切权利,需经作者同意后方可转载,转载时 请注明[叶帆工作室]及文章链接。yefan@vip.sina.com
【简介】叶帆[微软MVP]
【文章】叶帆文章列表
【软件】叶帆共享软件列表
最近评论
yefanqiu:知道这个软件,不过更深层次知识我目前也不清楚。
吴为仁:请问你熟悉神奇的Reflector软件吗?用它可以得到.NET的源码。请问Reflector输出的源码与真正的源码有什么区别?要注意那些问题?您这个MVP写一点此方面的东西,可否?
yefanqiu:在C#上直接调用该控件吧。
yefanqiu:这是支持两种不同字符集的函数(ANSI/Unicode)
jingang123gz:我用C#怎么写代码捏???
文章分类
收藏
    相册
    叶帆照片
    【叶帆软件】
    [01]VB源码之友(V2.1.548)
    [02]API浏览器.net(V5.0)
    [03]叶帆成语词典(V2.0.8)
    [04]叶帆密码库(V1.2.8)
    【叶帆资源】
    DAO 2.0引擎
    叶帆快速通道
    Windows Embedded 专题
    中文MSDN
    叶帆圈子--工业自动化
    叶帆工作室(博客园)
    叶帆工控--工业自动化
    叶帆群组--工业应用开发
    微软中文技术论坛
    瑞康社区论坛
    叶帆友情链接
    张欣
    枕善居
    莫依
    葛涵涛
    郑建
    陈辉
    马宁
    马骐
    魏涛序
    黎波
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 .Net Micro Framework研究—应用实例收藏

    新一篇: Windows Mobile 5.0横竖屏自识别技术 | 旧一篇: C# API方式串口读写

     
    试验平台:.Net Micro Framework 模拟器
    在前几篇关于.Net Micro Framework的研究文章中,我对它的绘图功能实不敢恭维,不过微软的MF开发人员很聪明,对位图方面的功能实现的就比较完善,这样做起图形应用来就不至于捉襟见肘了。
    前段时间用.Net Compact Framework实现了一个奥运场馆查询(相关文章请参见:http://blog.csdn.net/yefanqiu/archive/2007/11/13/1882835.aspx),现在我们用.Net Micro Framework也实现一个,看看哪一个更炫。
    (效果是不是比用.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);
                    }
                }
            }
        }
    }
    有条件的网友可以和微软提供的示例NewPresentation对比一下看看,也许更能看出它们的异同。有时间我在把这个类封装成一个控件(基于.Net CF),这样在windows和wince平台就都能使用了。
     

    发表于 @ 2007年11月28日 22:25:00|评论(loading...)|编辑

    新一篇: Windows Mobile 5.0横竖屏自识别技术 | 旧一篇: C# API方式串口读写

    评论

    #yanro 发表于2007-11-29 11:42:09  IP: 219.142.59.*
    我也比较喜欢.NET .看了您的 .net micro framework 系列的文章,也想试着做点小东西。怎么去搭建一个开发环境。您能不能写一篇这样的文章。呵呵!谢谢 了 。
    #aawolf 发表于2007-12-05 12:00:24  IP: 207.46.92.*
    呵呵,COOL啊
    #truelove12 发表于2007-12-13 10:38:00  IP: 60.163.175.*
    Micro Framework 是什么,和Compact FrameWork有什么关系吗?
    #yefanqiu 发表于2007-12-14 00:18:40  IP: 221.217.132.*
    微软的另一款嵌入式产品开发语言,目前仅支持C#语法,和.net Frmaework/Compact Framework有一定的血缘关系。至少是表兄弟吧:-)
    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 叶帆