22, .Net Micro Framework研究—让MF支持英文输入法

       作者: 刘洪峰

 

一旦支持了鼠标功能,MF可研究的领域,似乎变得无穷无尽,这也许是我近几天一直陷于此中不能自拔的原因了。

有了鼠标即使没有键盘,我们也可以通过虚拟键盘完成输入工作。这个工作很有意义,也很有挑战性,因为这不是windows平台,也不是Dos平台,这是“一穷二白”的MF平台,所有的工作都得从头做起(实现绘制键盘,向有输入焦点控件发送按键信息,删除,添加字符等等功能)。

目前字符串不仅无法转换为数字,并且没有字符插入功能,所以这个函数也必须自己来实现,此外输入焦点光标也需要自己绘制,好了,先不说难处了,先看看最终成果。

 

这是一个文本输入实例,当文本框有输入焦点时,自动弹出输入面板。

虚拟键盘上的“Shift”键也是有效的,切换后可以输入符号和大写字母。

 

当文本框失去输入焦点的时候,虚拟键盘消失。

 

以上应用实现的代码如下:

    //个人信息

    public class YFSelfInfo : YFDialog

    {

        YFLabel[] label=new YFLabel[3];

        YFText[] text=new YFText[3];

        string[] strLabelName = new string[] {"姓名:","单位:","博客:"};

        public YFSelfInfo(string Title, int Left, int Top, int Width, int Height, YFWindowBase Parent): base(Title, Width, Height, Parent)

        {

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

            for(int i=0;i<3;i++)

            {

                label[i] = new YFLabel(strLabelName[i], 20, ClientRect.Top + 10+30*i,40, 20);

                Children.Add(label[i]);

                text[i] = new YFText("", 70, label[i].Top, 140, 20);

                text[i].Enter += new YFSoft.SPOT.Presentation.YFEventHandler(text_Enter);

                text[i].Leave += new YFSoft.SPOT.Presentation.YFEventHandler(text_Leave);

                Children.Add(text[i]);

            }

        }

        //获得输入焦点时显示输入面板

        void text_Leave(object sender, EventArgs e)

        {

            HideInputPanel();

            this.Height = SystemMetrics.ScreenHeight;

        }

        //失去焦点时隐藏输入面板

        void text_Enter(object sender, EventArgs e)

        {

            ShowInputPanel();

            this.Height = this.InputPanelTop + 1;

        }

        //主窗体鼠标信息

        public override void OnMouseClick(object sender, MouseEventArgs e)

        {

            text_Leave(null, null); //隐藏输入面板

            base.OnMouseClick(sender, e);

        }

}

用户程序是不是很简单?再看看我实现的一个记事本程序

正在输入界面

 

菜单功能支持

 

相关代码如下:

    //记事本

    public class YFNote : YFDialog

    {

        YFText text;

        public YFNote(string Title,int Left, int Top, int Width, int Height, YFWindowBase Parent)

            : base(Title, Width, Height, Parent)

        {

            text = new YFText("", ClientRect.Left, ClientRect.Top, ClientRect.Width, ClientRect.Height);

            text.BorderStyle = BorderStyle.None;

            text.Align = false;

            text.Enter += new YFSoft.SPOT.Presentation.YFEventHandler(text_Enter);

            text.Leave += new YFSoft.SPOT.Presentation.YFEventHandler(text_Leave);

            Children.Add(text);

            this.Left = Left;

            this.Top = Top;

            Menu.AddItem(new MenuItem("新建"));

            Menu.AddItem(new MenuItem("保存"));

            Menu.AddItem(new MenuItem("-"));

            Menu.AddItem(new MenuItem("退出"));               

        }

        //获得输入焦点时显示输入面板

        void text_Leave(object sender, EventArgs e)

        {

            HideInputPanel();

            this.Height = SystemMetrics.ScreenHeight;

            text.Height = ClientRect.Height;

        }

        //失去焦点时隐藏输入面板

        void text_Enter(object sender, EventArgs e)

        {

            ShowInputPanel();

            this.Height = this.InputPanelTop+1;

            text.Height = ClientRect.Height;

        }

        //主窗体鼠标信息

        public override void OnMouseClick(object sender, MouseEventArgs e)

        {

            text_Leave(null, null); //隐藏输入面板

            base.OnMouseClick(sender, e);

        }

        //菜单

        public override void OnMenuClick(MenuEventArgs e)

        {

            switch (e.Text)

            {

                case "新建":

                    text.Text = "";

                    break;

                case "保存":

                    MessageBox("不好意思,暂时没有保存功能","记事本", MessageBoxButtons.OK, MessageBoxIcon.Warning);

                    break;

                case "退出":

                    Close();

                    break;

            }

            base.OnMenuClick(e);

        }

 }

程序也超简单,但功能还是蛮强大的,我们下面看看虚拟键盘的相关代码,实现思路和鼠标功能一样,也是直接借助基类的虚拟函数,向指定的窗体和控件发送按键消息。

核心代码如下:

public void TransactKey(KeyState state, object sender, MouseEventArgs e)

    {

        //向控件发送按键消息

        if (this.Parent != null)

        {

            Keys key = Keys.None;

            int keyValue=0;

            char _char = (char)0;

 

            YFButton b = (YFButton)sender;

            if (b.Text == "" || b.Text=="En" || b.Text=="Cn") return;

 

            Button btn = Button.None;

            switch (b.Text)

            {

                case "Tab":

                    key = Keys.Tab;

                    break;

                case "Caps":

                    key = Keys.CapsLock;

                    break;

                case "Shift":

                    key = Keys.Select;

                    break;

                case "Ent":

                    key = Keys.Enter;

                    btn = Button.Select;

                    break;

                case "Esc":

                    key = Keys.Escape;

                    break;

                case "Ins":

                    key = Keys.Insert;

                    break;

                case "Del":

                    key = Keys.Delete;

                    break;

                case "Menu":

                    key = Keys.Menu;

                    btn = Button.Menu;

                    break;

                case "↑":

                    key = Keys.Up;

                    btn = Button.Up;

                    break;

                case "←":

                    key = Keys.Left;

                    btn = Button.Left;

                    break;

                case "↓":

                    key = Keys.Down;

                    btn = Button.Down;

                    break;

                case "→":

                    key = Keys.Right;

                    btn = Button.Right;

                    break;

                case "<-":

                    key = Keys.Back;

                    btn = Button.Back;

                    break;

                default:

                    _char = b.Text[0];

                    key = (Keys)b.Name[0];

                    break;

            }

            keyValue = (int)key;

 

            //向当前有输入焦点的窗口发送系统按键消息

            if (btn!= Button.None)

            {

                if ((state & KeyState.Down) > 0) Parent.GetFocus().OnButtonDownEx(new ButtonEventArgs(null, null, new TimeSpan(), btn));

                if ((state & KeyState.Up) > 0) Parent.GetFocus().OnButtonUpEx(new ButtonEventArgs(null, null, new TimeSpan(), btn));                   

            }

 

            //获得输入焦点的控件

            YFControl c = this.Parent.Children.GetFocus();

            if (c != null)

            {

                if ((state & KeyState.Down) > 0) c.OnKeyDown(sender, new KeyEventArgs(key, keyValue, button[41].Checked, button[28].Checked, button[55].Checked));

                if ((state & KeyState.Press) > 0 && _char != (char)0) c.OnKeyPress(sender, new KeyPressEventArgs(_char));

                if ((state & KeyState.Up) > 0) c.OnKeyUp(sender, new KeyEventArgs(key, keyValue, button[41].Checked, button[28].Checked, button[55].Checked));

            }

 

            //父窗体要求接收按键消息

            if (Parent.KeyPreview)

            {

                if ((state & KeyState.Down) > 0) Parent.OnKeyDown(Parent, new KeyEventArgs(key, keyValue, button[41].Checked, button[28].Checked, button[55].Checked));

                if ((state & KeyState.Press) > 0 && _char != (char)0) Parent.OnKeyPress(Parent, new KeyPressEventArgs(_char));

                if ((state & KeyState.Up) > 0) Parent.OnKeyUp(Parent, new KeyEventArgs(key, keyValue, button[41].Checked, button[28].Checked, button[55].Checked));

            }

        }

}

   以上仅仅实现的是英文输入,中文输入怎么做?似乎要困难的多,此外粘贴、复制功能要不要做?总之有很多很多的东西值得我们去探索去实现,这一切,似乎我们在走Microsoft的老路,要在MF平台上实现一个Micro Windows!说到这我想到一个笑话,有一个人给上帝进行打赌说他也能造人。上帝问他,你怎么做,他说,我先用泥土捏一个…,“等等,”上帝打断了他,“你要用你自己的泥土”。