天天看点

Windows Mobile 5.0编程—奥运场馆速查

虽然前不久买了一个HP基于windows Mobile 5.0的PDA,由于工作太为繁忙,并没有为之开发相应的程序。没想到微软最近开展了酷炫应用争霸赛,征集“奥运”相关的作品,我忙里偷闲,用VS2005开发了一个关于奥运场馆的小程序,时值2008北京奥运前夕,也算是为奥运做了“贡献”:-)

虽然说是小程序,其实需要的知识不少,下面我简要介绍一下。

一、功能特色

该软件最大的特色就是,可以用手写笔或手指拨动相应的图片索引,拨动的速度越快,则图片翻转的越快,有点像快速翻书的感觉。记得苹果公司出的一款产品,在浏览图片(浏览通信录?记不清了)的时候,就是采用该方式。

其次,采用了XML文件保存必要的文字数据,这样在不改变代码的情况下,通过修改XML文件和添加必要的图片,就能增添奥运场馆数据了。目前共包括了13个场馆的详细资料和图片(费了我不少时间来加工和制作图片),还是值得一看的。

二、使用简介

使用很简单,如上图,用手写笔、手指或按键选择一个奥运场馆,单击或按回车按钮(Enter键)就进入到下一界面,不同的场馆内容有多有少,可以通过工具条按钮进行切换。

三、技术要点

1、图形双缓存技术

多个图片快速移动的时候,如果不采用图形双缓存技术,图片在移动时,会非常闪烁。

该实现还是沿用了我开发嵌入式组态的时方法:

第一:重载OnPaintBackground函数,不要让系统自动绘背景。

//避免闪烁,不绘制背景

        protected override void OnPaintBackground(PaintEventArgs paintg)

        {

            //不绘制背景

    }

  第二:创建位图场景

      bitmap = new Bitmap(this.Width, this.Height);

   graphics = Graphics.FromImage((System.Drawing.Image)bitmap);

     //绘图

       private void frmMain_Paint(object sender, PaintEventArgs e)

       {

           //绘背景

         graphics.Clear(Color.White);

//实际绘图代码

……          

           //绘图

           e.Graphics.DrawImage(bitmap, 0, 0);

      }

2、获取毫秒值

在.net精简框架集下,是无法通过现成的命令获得毫秒值的,一般最小时刻单位为秒。这对我获取手写笔移动的快慢是远远不够的,一次手写笔快速从屏蔽划过,一般也就十几毫秒,用秒来衡量就区分不出快慢了。

要想获取毫秒值,必须用API函数,不过要有相应的硬件支持才行。幸好在模拟器和我的PPC上都支持。

[DllImport("//windows//coredll.dll", EntryPoint = "GetTickCount")]

    public static extern int GetTickCount();

这样当鼠标按下时记下当时的位置和时刻值,直到鼠标抬起时,算出位移值,然后在除以时间就是手写笔移动的速度了。

3、区分单击和移动

在PC机上是很容易区分单击和移动的,但是用手写笔则不然。我的思路是鼠标按下和抬起的位移值小于一定值,我就认为是单击,否则就是移动。

//鼠标按下

        private void frmMain_MouseDown(object sender, MouseEventArgs e)

            Rectangle rect = new Rectangle(0, 50, 240, 72);

            if (rect.Contains(e.X, e.Y))

            {

                MouseFlag = true;

                fStartX = e.X;

                fTime = GetTickCount();

            }

            rect = new Rectangle(75, 50, 90, 72);

                MouseClickFlag = true;

                bSelectDown = true;

                this.Refresh();

        }

        //鼠标抬起

        private void frmMain_MouseUp(object sender, MouseEventArgs e)

            if (MouseFlag)

                MouseFlag = false;

                fWidth = e.X - fStartX;

                bWay = (fWidth > 0);

                fWidth = Math.Abs(fWidth);

                if (fWidth > intMoveSpace)

                {

                    //计算鼠标移动的速度

                    fTime=GetTickCount() - fTime;

                    fMoveSpeed = fWidth / fTime;

                    if (fMoveSpeed < 0.5) fMoveSpeed = (float)0.6;

                    //启动时钟函数,图片开始滚动                  

                    tmrMove.Interval = (int)(20 /(fMoveSpeed-0.5));

                    tmrMove.Enabled = true;

                }

                else

                    //鼠标单击事件发生

                    if (MouseClickFlag)

                    {

                        MouseClickFlag = false;

                        bSelectDown = false;                

                        ShowInfoBar();

                    }

4、动画移动

这部分的代码就不贴出了(请下载程序,自行看看源码)。

5、XML反序列化

原先我是把图片添加到ImageList组件里的,没有想到图片一多,不光VS2005 IDE在调试加载资源时报错(其实VS2005在加载资源的时候很不稳定,不知道VS2008是否进行了改善),程序运行到我PPC上的时候,十几兆的内存一下子就没有了。所以最后还是采用了XML序列化技术保存数据,同时图片也单独以文件方式存放,XML文件仅保存路径信息。(其实XML文件也可以保存图片数据,只是我觉得这样,XML文件会很大,反序列化时会很慢,影响用户的体验)。

解析一个复杂的XML文件是很麻烦的事,所以我一般都采用XML序列化技术。所以我构建了两个类来完成该功能。

值得说明的是,List<string>类在序列化和反序列化时会出问题(除非把string再封装到一个类里),所以我采用string数组保存数据,并适当的时候转换为List<string>模式。

public class DataInfos

    {

        //主背景图片的路径

        public string strBackBmpPath = "";

        //主背景图片

        [XmlIgnore]

        public Image bmpBack = null;

        //场馆数据

        public List<DataInfo> Data = new List<DataInfo>();

        //反序列化

        public static DataInfos XMLDeserialize(string XmlFile)

            try

                Type[] mtype = new Type[1];

                mtype[0] = typeof(DataInfo);

                DataInfos XmlData = new DataInfos();

                Stream sf = new FileStream(XmlFile, FileMode.Open, FileAccess.Read, FileShare.None);

                XmlSerializer xmls = new XmlSerializer(typeof(DataInfos), mtype);

                XmlData = (DataInfos)xmls.Deserialize(sf);

                sf.Close();

                return XmlData;

            catch (Exception e)

                MessageBox.Show("反序列化失败:" + XmlFile + "<" + e.Message + ">", "叶帆软件");

                return null;

    public class DataInfo

        //场馆名称

        public string Text = "";

        //信息个数

        public int Count = 0;

        //信息索引

        public int Index = 0;

        //图片说明

        public string[] mlstTitle = null;

        public List<string> lstTitle

            set { mlstTitle = value.ToArray(); }

            get

                List<string> mmlstTitle = new List<string>();

                if (mlstTitle != null)

                    foreach (string str in mlstTitle)

                    {

                        mmlstTitle.Add(str);

                return mmlstTitle;

        //信息说明

        public string[] mlstInfo = null;

        public List<string> lstInfo

            set { mlstInfo = value.ToArray(); }

                List<string> mmlstInfo = new List<string>();

                if (mlstInfo != null)

                    foreach (string str in mlstInfo)

                        mmlstInfo.Add(str);

                return mmlstInfo;

        //图片路径

        public string[] mlstImagePath = null;

        public List<string> lstImagePath

            set { mlstImagePath = value.ToArray(); }

                List<string> mmlstImagePath = new List<string>();

                if (mlstImagePath != null)

                {

                    foreach (string str in mlstImagePath)

                        mmlstImagePath.Add(str);

                return mmlstImagePath;

        //图片

        public List<Image> lstBmp = new List<Image>();

        //索引图片路径

        public string bmpPath = "";

        //索引图片

        public Image bmp = null;     

 }

四、下载安装

下载后直接把安装包里的文件和文件夹直接拷贝到PPC模拟器或PDA中即可。