18,.Net Micro Framework研究—让MF支持鼠标

       作者: 刘洪峰

 

MF的标准模块仅支持按键,并不支持鼠标功能。但是对一些常见应用来说,如果没有鼠标(或触摸屏)用起来就太不习惯了。有什么办法可以让MF支持鼠标功能呢?第一,外部设备必须把鼠标信息传到MF应用程序,应用程序根据这些信息绘制鼠标及执行相应的动作。鼠标信息最少包含三种,鼠标按键状态(按下或放开),鼠标坐标(x,y)。

      目前,Spi通道可以非常方便地建立设备和用户程序之间的联系,所以就考虑用Spi来实现该功能。

      第一步,还是从我编写的模拟器入手,添加了一个Spi驱动类。

//MouseDevice

    public class MouseComponent : SpiDevice

    {

        public static Int16 State = 0;

        public static Int16 X = 0;

        public static Int16 Y = 0;

 

        protected override byte[] Write(byte[] data)

        {

            //------------

            //改写坐标值

            try

            {

                //State = (Int16)((data[0] << 8) + data[1]);

                //X = (Int16)((data[2] << 8) + data[3]);

                //Y = (Int16)((data[4] << 8) + data[5]);

            }

            catch { }

            //------------

            //返回当前值

            byte[] bytes = new byte[6];

            bytes[0] = (byte)(State >> 8);

            bytes[1] = (byte)(State & 0xff);

            bytes[2] = (byte)(X >> 8);

            bytes[3] = (byte)(X & 0xff);

            bytes[4] = (byte)(Y >> 8);

            bytes[5] = (byte)(Y & 0xff);

            return bytes;

        }

        protected override ushort[] Write(ushort[] data)

        {

            //------------

            //改写坐标值

            try

            {

                //State = (Int16)data[0];

                //X = (Int16)data[1];

                //Y = (Int16)data[2];

            }

            catch { }

            //------------

            //返回当前值

            ushort[] Int16s = new ushort[3];

            Int16s[0] = (ushort)State;

            Int16s[1] = (ushort)X;

            Int16s[2] = (ushort)Y;

            return Int16s;

        }

}

第二步:编写鼠标应用程序

为了通用,我封装了一个windowbase基类

//鼠标事件

        public class MouseEventArgs : EventArgs

        {

            public int X;

            public int Y;

            public int Button;

            public MouseEventArgs()

            {

                X = 0;

                Y = 0;

                Button = 0;

                State = MouseState.None;

            }

            public MouseEventArgs(int x, int y)

            {

                X = x;

                Y = y;

                Button = 0;

                State = MouseState.None;

            }

            public MouseEventArgs(int x, int y, int button)

            {

                X = x;

                Y = y;

                Button = button;

                State = MouseState.None;

            }

        }

       

        //窗体基类

        internal class WindowBase : Window

        {

            protected YFWinApp m_app;

            Thread MouseThread;          

            private ushort state=0, x = 0, y = 0;

            SPI _spi=null;

 

            protected WindowBase(YFWinApp app)

            {

                m_app = app;

                this.Visibility = Visibility.Visible;

                this.Width = SystemMetrics.ScreenWidth;

                this.Height = SystemMetrics.ScreenHeight;

                Buttons.Focus(this);

 

                //SPI的pin定义

                _spi = new SPI(new SPI.Configuration((Cpu.Pin)127, true, 0, 0, false, false, 4000, SPI.SPI_module.SPI1));

                x =(ushort)( this.Width/2);

                y =(ushort)( this.Height/2);

                MouseThread = new Thread(new ThreadStart(MouseInfo));

                MouseThread.Start();

            }

           

            protected override void OnButtonDown(ButtonEventArgs e)

            {

                this.Close();

                m_app.GoHome();

            }

           

            //获得鼠标信息

            private void MouseInfo()

            {

                ushort[] bout = new ushort[3];

                ushort[] bin = new ushort[3];

                ushort mX, mY, mState;

                while (true)

                {

                    //----------------------------------

                    //通过spi通道获取鼠标信息 这部分信息解析和模拟器相对应

                    _spi.WriteRead(bout, bin); 

                    mState = bin[0]; //鼠标的状态 1- 按下 0 - 放开

                    mX = bin[1]; //鼠标X坐标

                    mY = bin[2]; //鼠标Y坐标

                    //----------------------------------

 

                    if (x != mX|| y != mY)

                    {

                        x = mX; y = mY;

                        OnMouseMove(new MouseEventArgs(mX, mY, mState));

                    }

                    if (state != mState)

                    {

                        state = mState;

                        if (state == 1)

                        {

                            OnMouseDown(new MouseEventArgs(mX, mY, mState));

                        }

                        else if(state==0)

                        {

                            OnMouseUp(new MouseEventArgs(mX, mY, mState));

                            OnMouseClick(new MouseEventArgs(mX, mY, mState));                          

                        }

                    }

                }

            }

          

            //鼠标移动

            protected virtual void OnMouseMove(MouseEventArgs e)

            {

                Debug.Print("MouseMove:" + e.X.ToString() + "," + e.Y.ToString() + "," + e.Button.ToString());

            }

 

            //鼠标单击

            protected virtual void OnMouseClick(MouseEventArgs e)

            {

                Debug.Print("MouseClick:" + e.X.ToString() + "," + e.Y.ToString() + "," + e.Button.ToString());

            }

 

            //按下

            protected virtual void OnMouseDown(MouseEventArgs e)

            {

                Debug.Print("MouseDown:" + e.X.ToString() + "," + e.Y.ToString() + "," + e.Button.ToString());

            }

 

            //抬起

            protected virtual void OnMouseUp(MouseEventArgs e)

            {

                Debug.Print("MouseUp:" + e.X.ToString() + "," + e.Y.ToString() + "," + e.Button.ToString());

            }

            //绘制鼠标

            public override void OnRender(DrawingContext dc)

            {

                if (state == 1)

                {

                    Pen pp=new Pen(ColorUtility.ColorFromRGB(255,255,0));

                    dc.DrawLine(pp, x, y - 5, x, y + 5);

                    dc.DrawLine(pp, x-5, y, x+5, y);

                }

                int[] points = { x, y, x+10, y+4, x+5,y+5, x+4,y+10};

                Pen p = new Pen(Color.White, 1);

                dc.DrawPolygon(null, p, points);

            }

            //窗体刷新

            protected void Refresh()

            {

                this.Left = this.Left;

                this.UpdateLayout();  

            }

     }

下面是我们实际运行的效果图,已经非常完美的支持鼠标了(并且模拟器可两种方式提供鼠标信息,一种是鼠标直接在LCD屏上操作,一种是通过扩展面板上的滑块进行移动)。

直接用外部鼠标操作。

 通过滑块进行鼠标操作。