叶帆工作室

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

刘洪峰ID:yefanqiu
518520次访问,排名80好友0人,关注者161
微软MVP / CSDN 2008十大MVB/MSDN中文技术论坛版主
yefanqiu的文章
原创 216 篇
翻译 0 篇
转载 3 篇
评论 1077 篇
叶帆的公告
本博客原创文章,作者保留一切权利,需经作者同意后方可转载,转载时 请注明[叶帆工作室]及文章链接。yefan@vip.sina.com
【简介】叶帆[微软MVP]
【文章】叶帆文章列表
【软件】叶帆共享软件列表
最近评论
findg:今天我看见这个网站:http://www.diybl.com/course/6_system/linux/Linuxjs/2007921/72422.html转载了该篇文章,但没有注明文章来源。
dasheng:应该怎样建立监测串口接收数据事件的线程呢。还请指教。
andy:可以给我发一份Dotnet Framework的ppt么?
My E-Mail:caozhongshuai_andy@163.com
真的非常感谢!
@:我防火墙是关了的为撒也还有这情况呢?
superpope1216:叶老师
现在我要用C# 2005开发一个windows mobile 蓝牙打印的功能,请问又什么方法吗?
因为我对蓝牙通信的原理是通过串口什么的不太清楚
还又是否需要调用API函数?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研究—实现SideShow窗体界面收藏

    新一篇: .Net Micro Framework研究—让MF支持英文输入法 | 旧一篇: .Net Micro Framework研究—数据的永久存储

     
    基于MF系统的Windows SideShow界面是非常炫的(如下图)。既然微软能用.Net Micro Framework实现这么棒的界面效果,我想我们也能做到。
    (SideShow模拟器界面和游戏程序中的右键菜单—注意菜单弹出后,其它的界面变暗了)
    现在的任务是设计一套支持鼠标(或触摸屏)的窗体框架(目前MF提供的Window类仅支持按键功能),所以正好把SideShow如此炫的界面元素也可以添加进来。
    用过MF的人知道是用下面的方法来实现按键事件接收的,既然我们要支持鼠标功能,所以最好也用类似的机理实现。
        //按键事件
        protected override void OnButtonDown(ButtonEventArgs e)
        {
            switch (e.Button)
            {
                //按下确定键
                case Button.Select:
                    break;
                //按下左键
                case Button.Left:
                    break;
                //按下右键
                case Button.Right:
                    break;
                //按向上
                case Button.Up:
                    break;
                //按向下
                case Button.Down:
                    break;
                //按下菜单
                case Button.Menu:
                    break;
                //按下返回键
                case Button.Back:
                    break;
            }
            base.OnButtonDown(e);
        }
    用反编译工具仔细研究了MF底层库代码(.Net FrameWork 太庞大了,一个人绝对短时间内看不完,其实也很难看下去,但是对刚刚起步的MF来说,.Net Micro FrameWork就简单多了),终于理清了头绪。主要原理是在鼠标信息处理线程中通过Application.Current.Windows 属性(该属性存放了当前实例所有派生于Window类的窗体)和应用实例的this.Dispatcher属性的BeginInvoke方法,外部调用窗体鼠标事件函数。充分利用基类虚函数的妙处来实现类似按键信息处理的功能。
    YFWindowBase类中声明如下虚拟鼠标事件函数。
    //鼠标移动
        public virtual void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (MouseMove != null) MouseMove(sender, e);
        }
        //鼠标单击
        public virtual void OnMouseClick(object sender, MouseEventArgs e)
        {
            if (MouseClick != null) MouseClick(sender, e);
        }
        //按下
        public virtual void OnMouseDown(object sender, MouseEventArgs e)
        {
           if (MouseDown != null) MouseDown(sender, e);
        }
        //抬起
        public virtual void OnMouseUp(object sender, MouseEventArgs e)
        {
            if (MouseUp != null) MouseUp(sender, e);
        }
     
    在鼠标信息处理函数中执行如下的代码即可。
       //处理鼠标消息
        private static void TransactMouse(MouseState state, int x, int y, MouseButtons button)
        {
            if (Application.Current == null) return;
            for (int i = Application.Current.Windows.Count - 1; i >= 0; i--)
            {
                try
                {
                    YFWindowBase mw = Application.Current.Windows[i] as YFWindowBase;
     
                    if (mw.Enabled && mw.IsVisible)
                    {
                        //判断子窗体
                        bool bReturn = false;
                        for (int j = mw.Children.Count - 1; j >= 0; j--)
                        {
                            //仅最上层并且可视的控件接收鼠标消息
                            YFControl cl = mw.Children[j];
                            if (!bReturn && cl.Visible && IsRectContains(x, y, mw.Left + cl.Left, mw.Top + cl.Top, cl.Width, cl.Height))
                            {
                                if (cl.Enable) //Enable和Visible不一样,Enable即使无效,下层控件也没有机会获得鼠标消息
                                {
                                    if (!cl._EnterFlag)
                                    {
                                        cl._EnterFlag = true;
                                        _dispatcher.BeginInvoke(new MouseInputEventHandler(cl.OnMouseEnter), cl, new MouseEventArgs(button, x - cl.Left - mw.Left, y - cl.Top - mw.Top));
                                    }
                                    if ((state & MouseState.Move) > 0)
                                        _dispatcher.BeginInvoke(new MouseInputEventHandler(cl.OnMouseMove), cl, new MouseEventArgs(button, x - cl.Left - mw.Left, y - cl.Top - mw.Top));
                                    if ((state & MouseState.Down) > 0)
                                        _dispatcher.BeginInvoke(new MouseInputEventHandler(cl.OnMouseDown), cl, new MouseEventArgs(button, x - cl.Left - mw.Left, y - cl.Top - mw.Top));
                                    if ((state & MouseState.Up) > 0)
                                        _dispatcher.BeginInvoke(new MouseInputEventHandler(cl.OnMouseUp), cl, new MouseEventArgs(button, x - cl.Left - mw.Left, y - cl.Top - mw.Top));
                                    if ((state & MouseState.Click) > 0)
                                        _dispatcher.BeginInvoke(new MouseInputEventHandler(cl.OnMouseClick), cl, new MouseEventArgs(button, x - cl.Left - mw.Left, y - cl.Top - mw.Top));
                                }
                                //向主窗体传OnMouseEvent消息,为了绘制鼠标
                                if ((state & MouseState.Event) > 0)
                                    _dispatcher.BeginInvoke(new MouseInputEventHandler(mw.OnMouseEvent), mw, new MouseEventArgs(button, x - mw.Left, y - mw.Top));
                                bReturn = true;
                            }
                            else
                            {
                                if (cl._EnterFlag)
                                {
                                    cl._EnterFlag = false;
                                    _dispatcher.BeginInvoke(new MouseInputEventHandler(cl.OnMouseLeave), cl, new MouseEventArgs(button, x - cl.Left, y - cl.Top));
                                }
                            }
                        }
                        if (bReturn) return;
                    }
     
                    //仅最上层并且可视的窗体接收鼠标消息
                    if (mw.IsVisible && IsRectContains(x, y, mw.Left, mw.Top, mw.Width, mw.Height))
                    {
                        if (!mw.Enabled) return;
     
                        if ((state & MouseState.Move) > 0)
                            _dispatcher.BeginInvoke(new MouseInputEventHandler(mw.OnMouseMove), mw, new MouseEventArgs(button, x - mw.Left, y - mw.Top));
                        if ((state & MouseState.Down) > 0)
                            _dispatcher.BeginInvoke(new MouseInputEventHandler(mw.OnMouseDown), mw, new MouseEventArgs(button, x - mw.Left, y - mw.Top));
                        if ((state & MouseState.Up) > 0)
                            _dispatcher.BeginInvoke(new MouseInputEventHandler(mw.OnMouseUp), mw, new MouseEventArgs(button, x - mw.Left, y - mw.Top));
                        if ((state & MouseState.Click) > 0)
                            _dispatcher.BeginInvoke(new MouseInputEventHandler(mw.OnMouseClick), mw, new MouseEventArgs(button, x - mw.Left, y - mw.Top));
                        if ((state & MouseState.Event) > 0)
                            _dispatcher.BeginInvoke(new MouseInputEventHandler(mw.OnMouseEvent), mw, new MouseEventArgs(button, x - mw.Left, y - mw.Top));
                        return;
                    }
                }
                catch (Exception e)
                {
                    throw new Exception(e.Message.ToString(), e);
                }
            }
        }
      用户程序的窗体类只要派生于YFWindowBase类,就可以直接支持鼠标和按键功能了。用户代码如下:
        //主窗体
        internal sealed class MFWindow :YFWindowBase
        {
            public YFLabel label1;
            YFButton button1, button2, button3, button4, button5;
            public MFWindow()
            {
                //标签
                label1 = new YFLabel("就绪", 0, Height - 25, Width, 25);
                label1.TextAlign = TextAlignment.Left;
                label1.BackColor = ColorUtility.ColorFromRGB(189, 235, 255);
                label1.BorderStyle = BorderStyle.FixedSingle;
                //添加按钮
                button1 = new YFButton("触摸屏校准", 30, 35, 90, 40);
                button1.MouseClick += new MouseInputEventHandler(button_MouseClick);
                button2 = new YFButton("计算器",200, 35, 90, 40);
                button2.MouseClick += new MouseInputEventHandler(button_MouseClick);
                button3 = new YFButton("简易记事本", 30, 135, 90, 40);
                button3.MouseClick += new MouseInputEventHandler(button_MouseClick);
                button4 = new YFButton("关于...", 200, 135, 90, 40);
                button4.MouseClick += new MouseInputEventHandler(button_MouseClick);
                button5 = new YFButton("主菜单", 125, 85, 70, 40);
                button5.MouseClick += new MouseInputEventHandler(button_MouseClick);
                Children.Add(button1);
                Children.Add(button2);
                Children.Add(button3);
                Children.Add(button4);
                Children.Add(button5);
                Children.Add(label1);
                button3.Enable = false;
                //button3.Visible = false;
                //设置菜单
                Menu.AddItem(new MenuItem("触摸屏校准"));
                Menu.AddItem(new MenuItem("-"));
                Menu.AddItem(new MenuItem("计算器"));
                Menu.AddItem(new MenuItem("简易记事本"));
                Menu.AddItem(new MenuItem("-"));
                Menu.AddItem(new MenuItem("关于..."));
                Menu[3].Enabled = false;
                //Menu[3].Visible = false;
            }       
            //按钮事件
            void button_MouseClick(object sender, MouseEventArgs e)
            {
                YFButton button=((YFButton)sender);
                switch (button.Text)
                {
                    case "主菜单":
                        //弹出菜单
                        this.Menu.Show();
                        break;
                    default:
                        OnMenuClick(new MenuEventArgs(0, button.Text));
                        break;
                }                          
            }
    运行后的界面如下:
     
    1:主界面(按钮即支持鼠标也可以用按键切换输入焦点(right键等同于PC平台上的Tab键),并用OK键触发按键事件)
    2:单击主菜单按钮或单击“Menu”就可以弹出主菜单
     
    3:不要小看了上图的蓝色小圆,是我费了好大劲才绘制出来的(目前MF仅支持矩形框的填充)。
    private void DrawCircle(Color c,int x, int y, int r, DrawingContext dc)
        {
            Pen p=new Pen(c);
            SolidColorBrush b = new SolidColorBrush(c);
            int Offset45=(int)(0.707*r);
            int Offset30 = r / 2;
            int Offset60 = (int)(0.866 * r);
     
            for (int i = Offset45; i < r + 1; i++)
            {
                dc.DrawEllipse(null, p, x, y, i, i);
            }
            dc.DrawRectangle(b, null, x - Offset45, y - Offset45,Offset45*2, Offset45*2);
            dc.DrawRectangle(b, null, x - Offset60, y - Offset30, Offset60 * 2, Offset30 * 2);
            dc.DrawRectangle(b, null, x - Offset30, y - Offset60, Offset30 * 2, Offset60 * 2);
     
            dc.DrawLine(p, x - Offset60, y - Offset30, x - Offset30, y - Offset60);
            dc.DrawLine(p, x+ Offset60 , y + Offset30, x + Offset30 ,y + Offset60 );
            dc.DrawLine(p, x - Offset60, y + Offset30, x - Offset30 , y + Offset60);
            dc.DrawLine(p, x + Offset60, y - Offset30, x + Offset30, y - Offset60);
       }
     
     
    5:终于在MF上实现了计算器的功能,目前不仅支持鼠标,也可以用光标键和OK键进行输入计算了。
    别小看了计算器程序,由于MF仅有数字转字符串功能,没有实现字符串转数字的功能,我自己自定义了一些函数,用了一些特殊的用法才编写完成。
    //数字输入的部分代码
    if (strInput == "0.") dblInput = 0;
            if (strInput != "0.")
            {
                strInput += b.Text;
                if (strInput.IndexOf('.')<1)
                {
                    dblInput *= 10;
                    dblInput += ToDouble(b.Text);
                }
                else
                {
                    int index = strInput.Length - strInput.LastIndexOf('.') - 1;
                    dblInput += ToDouble(b.Text) /System.Math.Pow(10,index);
                }
            }
            else if (b.Text != "0")
            {
                strInput = b.Text;
                dblInput = ToDouble(b.Text);
         }
       下面是窗体的界面搭建部分,你绝对想不到用这么短的代码就实现了上图的界面布局(看过我以前.Net Micro Framework研究的网友,应该对MF本身提供的控件有印象,正是因为系统的控件不好用,我专门重新写了一套MF控件类)。
        YFButton[] button=new YFButton[20];
        YFLabel lblInput = null;
        string[] strText = new string[] { "7", "8", "9", "/", "CE", "4", "5", "6", "*", "%", "1", "2", "3", "-", "1/x", "0", "+/-", ".", "+", "=" };
        public YFCalc(string Title,int Width,int Height,YFWindowBase Parent)
            : base(Title, Width, Height, Parent)
        {
            int x=ClientRect.X,y=ClientRect.Y;
     
            lblInput = new YFLabel("0.", x + 5, y + 5, ClientRect.Width - 10, 20);
            lblInput.TextAlign = TextAlignment.Right;
            Children.Add(lblInput);
            for (int i = 0; i < 20; i++)
            {
                if(i % 5==0 && i!=0)
                {
                    x = ClientRect.X;
                    y = y + 32;
                }
                button[i] = new YFButton("", x + 5, y + 32, 32, 28);
                button[i].Text = strText[i];
                button[i].MouseClick += new MouseInputEventHandler(button_MouseClick);
                x += 37;
                Children.Add(button[i]);
            }              
        }
        //按钮单击
        void button_MouseClick(object sender, MouseEventArgs e)
    {
    }
    其实这段时间以来,我一直在研究MF,虽然目前它还不是很成熟,但是随着研究的深入,越来越对它痴迷,越来越发现很多MF的宝藏(如果你有耐心的话,一定要看看MF底层框架的源码(通过反编译工具Reflector),你会发现很多很有意思的功能)。
    MF相对于Windows XP/Vista、Windows CE而言,还只能算一个婴孩,但就是这样,就如一个伟人所说:孩子就是未来的希望。所以有理由相信MF的明天会更好。
     

    发表于 @ 2008年01月25日 23:20:00|评论(loading...)|编辑

    新一篇: .Net Micro Framework研究—让MF支持英文输入法 | 旧一篇: .Net Micro Framework研究—数据的永久存储

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 叶帆