天天看點

Windows Mobile 5.0程式設計—奧運場館速查

雖然前不久買了一個HP基于windows Mobile 5.0的PDA,由于工作太為繁忙,并沒有為之開發相應的程式。沒想到微軟最近開展了酷炫應用争霸賽,征集“奧運”相關的作品,我忙裡偷閑,用VS2005開發了一個關于奧運場館的小程式,時值2008北京奧運前夕,也算是為奧運做了“貢獻”:-)

雖然說是小程式,其實需要的知識不少,下面我簡要介紹一下。

Windows Mobile 5.0程式設計—奧運場館速查

一、功能特色

該軟體最大的特色就是,可以用手寫筆或手指撥動相應的圖檔索引,撥動的速度越快,則圖檔翻轉的越快,有點像快速翻書的感覺。記得蘋果公司出的一款産品,在浏覽圖檔(浏覽通信錄?記不清了)的時候,就是采用該方式。

其次,采用了XML檔案儲存必要的文字資料,這樣在不改變代碼的情況下,通過修改XML檔案和添加必要的圖檔,就能增添奧運場館資料了。目前共包括了13個場館的詳細資料和圖檔(費了我不少時間來加工和制作圖檔),還是值得一看的。

二、使用簡介

Windows Mobile 5.0程式設計—奧運場館速查

使用很簡單,如上圖,用手寫筆、手指或按鍵選擇一個奧運場館,單擊或按回車按鈕(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);
            if (rect.Contains(e.X, e.Y))
            {
                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、動畫移動

雖然主界面最多顯示三個圖像索引,其實移動起來至少要有四個圖形同時在移動效果才好。在這裡就用到了數學的知識(有興趣的朋友可以看看這篇文章:

http://news.csdn.net/n/20071106/110350.html

),不過隻需簡單的數學知識,我想有個國小國中的水準就夠了,就是簡單計算一下圖形移動時,圖像坐标變化的規律。别說,在做這部分的時候,我還是花費了不少時間,并在草紙上畫了幾個圖,才明白左移和右移坐标和圖形變化的規律。

這部分的代碼就不貼出了(請下載下傳程式,自行看看源碼)。

5、XML反序列化

原先我是把圖檔添加到ImageList元件裡的,沒有想到圖檔一多,不光VS2005 IDE在調試加載資源時報錯(其實VS2005在加載資源的時候很不穩定,不知道VS2008是否進行了改善),程式運作到我PPC上的時候,十幾兆的記憶體一下子就沒有了。是以最後還是采用了XML序列化技術儲存資料,同時圖檔也單獨以檔案方式存放,XML檔案僅儲存路徑資訊。(其實XML檔案也可以儲存圖檔資料,隻是我覺得這樣,XML檔案會很大,反序列化時會很慢,影響使用者的體驗)。

解析一個複雜的XML檔案是很麻煩的事,是以我一般都采用XML序列化技術。是以我建構了兩個類來完成該功能。

值得說明的是,List類在序列化和反序列化時會出問題(除非把string再封裝到一個類裡),是以我采用string數組儲存資料,并适當的時候轉換為List模式。

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;
        //資訊索引
        [XmlIgnore]
        public int Index = 0;
        //圖檔說明
        public string[] mlstTitle = null;
        [XmlIgnore]
        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;
        [XmlIgnore]
        public List<string> lstInfo
        {
            set { mlstInfo = value.ToArray(); }
            get
            {
                List<string> mmlstInfo = new List<string>();
                if (mlstInfo != null)
                {
                    foreach (string str in mlstInfo)
                    {
                        mmlstInfo.Add(str);
                    }
                }
                return mmlstInfo;
            }
        }
        //圖檔路徑
        public string[] mlstImagePath = null;
        [XmlIgnore]
        public List<string> lstImagePath
        {
            set { mlstImagePath = value.ToArray(); }
            get
            {
                List<string> mmlstImagePath = new List<string>();
                if (mlstImagePath != null)
                {
                    foreach (string str in mlstImagePath)
                    {
                        mmlstImagePath.Add(str);
                    }
                }
                return mmlstImagePath;
            }
        }
 
        //圖檔
        [XmlIgnore]
        public List<Image> lstBmp = new List<Image>();
        //索引圖檔路徑
        public string bmpPath = "";
        //索引圖檔
        [XmlIgnore]
        public Image bmp = null;     
 }           

四、下載下傳安裝

該程式用VS2005開發,語言采用了C#,需要.net精簡架構集2.0的支援(可以從下面的連結下載下傳:

http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=aea55f2f-07b5-4a8c-8a44-b4e1b196d5c0

)。

程式下載下傳連結(包含程式全部的源代碼):

http://microsoft.csdn.net/mobile/dev_contest/demon-detail_1.aspx?pointid=47

下載下傳後直接把安裝包裡的檔案和檔案夾直接拷貝到PPC模拟器或PDA中即可。

Windows Mobile 5.0程式設計—奧運場館速查