none
30 Days of .NET [Windows Mobile Applications] - Day 04: Mileage Tracker(里程耗油计算程序) RRS feed

  • 常规讨论

  • 原文见 Day 04: Mileage Tracker

    需求

    作者的好朋友Chris Reeder希望有一个使用SQL CE database的里程耗油计算程序。

    实现

    由于作者那天很忙,所以把需求简化了,去掉SqlCe的存储,国际单位的支持,状态图,多次里程比较等等需求。由于需求的简化,功能变得简便,只是需要输入几个参数,然后计算出结果。

    输入参数

    1.距离,作者使用了英里(Miles)作为单位,记得以前同事问我中国是否使用国际单位,我说中国在秦的时候就统一了单位,解放的时候就统一使用国际单位了。从作者的文章看很多人还是喜欢使用非国际单位,例如Miles和Gallon那些。
    2.油量,作者使用加伦(Gallon)。
    3.价格。
    4.油缸量。 

    输出

    1.Miles Per Gallon,一加伦能走多少英里,就是距离除以油量,由于程序没有进行单位转换,我们可以假设在输入的距离为公里,输入的油量为升,那么结果就是”公里每升“了。
    2.Gallons Per 100 Miles,每100英里耗多少加伦的油。
    3.Cost Per 100 Miles,每100英里花多少钱。
    4.Maximum Range,一整缸油能走多长路程。

    在实现的时候作者把所有的参数和计算封装到一个叫做Mileage的类进行处理。

    public void Calculate()
    {
        MilesPerGallon 
    = 0;
        GallonsPer100Miles 
    = 0;

        
    if(Fuel != 0)
            MilesPerGallon 
    = Distance/Fuel;

        
    if (MilesPerGallon != 0)
            GallonsPer100Miles 
    = 100/MilesPerGallon;

        CostPer100Miles 
    = GallonsPer100Miles*Price;

        MaximumRange 
    = Tank*MilesPerGallon;
    }

    计算方法就是简单的四则运算。需要注意到地方是,所有数字变量使用decimal而不是float和double,做过会计软件的人会知道float和double做乘除法的时候经常出错。在现实的时候使用.ToString("0.00")进行格式化,使用StringBuilder进行合并字符串操作,提高效率。

    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.AppendFormat(
    "Miles Per Gallon: {0} Mpg", mileage.MilesPerGallon.ToString("0.00")).AppendLine().AppendLine();
    stringBuilder.AppendFormat(
    "{0} Gallons Per 100 Miles", mileage.GallonsPer100Miles.ToString("0.00")).AppendLine().AppendLine();
    stringBuilder.AppendFormat(
    "${0} Per 100 Miles", mileage.CostPer100Miles.ToString("0.00")).AppendLine().AppendLine();
    stringBuilder.AppendFormat(
    "Maximum Range: {0} Miles", mileage.MaximumRange.ToString("0.00"));

    textBoxResults.Text 
    = stringBuilder.ToString();

     

    界面处理

    由于Compact framework不直接支持透明控件,作者使用了Alex Yakhnin - Transparent labels 的透明标签控件。
    使用该透明标签控件,需要使用一个PictureBox保存一个图形对象,Label放在这个PictureBox,并设置为不可见,由DrawLabel方法来显示,DrawLabel方法的调用是通过PictureBox的Paint事件触发。

    数字输入控件, 作者使用了MS的NuericTextBox,可以参考How to: Create a Numeric Text Box ,这篇文章讲述如何通过继承TextBox而生成自定义用户控件。

    // Restricts the entry of characters to digits (including hex), the negative sign,
    // the decimal point, and editing keystrokes (backspace).
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        
    base.OnKeyPress(e);

        NumberFormatInfo numberFormatInfo 
    = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
        
    string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
        
    string groupSeparator = numberFormatInfo.NumberGroupSeparator;
        
    string negativeSign = numberFormatInfo.NegativeSign;

        
    string keyInput = e.KeyChar.ToString();

        
    if (Char.IsDigit(e.KeyChar))
        {
            
    // Digits are OK
        }
        
    else if (keyInput.Equals(decimalSeparator) || keyInput.Equals(groupSeparator) ||
         keyInput.Equals(negativeSign))
        {
            
    // Decimal separator is OK
        }
        
    else if (e.KeyChar == '\b')
        {
            
    // Backspace key is OK
        }
        
    //    else if ((ModifierKeys & (Keys.Control | Keys.Alt)) != 0)
        
    //    {
        
    //     // Let the edit control handle control and alt key combinations
        
    //    }
        else if (this.allowSpace && e.KeyChar == ' ')
        {

        }
        
    else
        {
            
    // Consume this invalid key and beep
            e.Handled = true;
            
    //    MessageBeep();
        }
    }

    这个类的关键是重载OnKeyPress事件,控制输入只能为数值类型。

    安装程序: mileageTracker.cab

    源代码: milesageTracker.zip
     

    .NET Compact Framework, WinCE, Windows Mobile开发系列

    Jake's Blog in 博客园 -- 精简开发 无线生活

    2009年5月31日 9:38