文章目錄
原文見 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 部落格園 -- 精簡開發 無線生活