Project 1 - 自我介紹程式(4):活用「語法、邏輯、資料結構、型態函式庫」-確保正確的資料進到程式當中
https://ithelp.ithome.com.tw/articles/10213632
每次做任何處理資料前,檢查的有沒有資料
多語系看似是一個簡單的需求,單是實作的過程你會發現,網路上有十幾種解法,對於程式的初學者,在網路上找到其中真正符合你需要的過程無法精確的找到關鍵字的方向,往往需要耗費不少時間
以下是我找到兩個相對比較簡潔的解法資源:
http://limitedcode.blogspot.com/2016/09/c-globalization.html
https://stackoverflow.com/questions/32989100/how-to-make-multi-language-app-in-winforms
我想讓今天這支程式可以用來對英文語系國家的人自我介紹,可是又不想重新另外寫一個英文版的專案
剛進入程式,選擇語系
進入主畫面前
進入主畫面後
按下自我介紹後的結果
程式會依照當 前的語系設定,根據資源檔的語系取得對應的文字:
(1) 資源檔名稱.resx :預設語系對應的文字
(2) 資源檔名稱.語系.resx:其他語系對應的文字
設計選擇語言視窗的畫面與欄位 (LanguageSelectForm.cs)
修改專案的Program.cs,讓程式執行後,出現語言選擇的視窗
using System;
using System.Windows.Forms;
namespace IT_Day01
{
static class Program
{
/// <summary>
/// 應用程式的主要進入點。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// 讓程式一開始出現LanguageSelectForm 語言選擇畫面
Application.Run(new LanguageSelectForm());
}
}
}
A視窗 透過產生物件的建構子 傳遞 資料到 B視窗:
B視窗的類別 視窗物件變數名稱 = new B視窗的類別(將傳遞的資料傳到B視窗的建構子參數);
/// <summary>
/// 帶入選擇的語言到主視窗
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void selectBtn_Click(object sender, EventArgs e)
{
IntroductionForm introductionForm = new IntroductionForm(languageComboBox.SelectedIndex);
introductionForm.FormClosed += introductionForm_FormClosed;
introductionForm.Show();
this.Visible = false;
}
/// <summary>
/// 關閉自我介紹主畫面後,重新開啟語系選擇的視窗
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void introductionForm_FormClosed(object sender, FormClosedEventArgs e)
{
this.Visible = true;
}
分別在三個語系的資源檔當中,加入所有多語系的文字變數。
預設、中文語系:
英文語系:
B視窗 透過視窗類別的建構子參數 接收 A視窗的資料:
public B視窗類別建構子(透過參數接收A視窗傳遞過來的資料) {}
public IntroductionForm(int languageIndex)
{
string[] language = { "zh-TW", "en-US" };
// 在產生畫面前改變語系
Thread.CurrentThread.CurrentUICulture = new CultureInfo(language[languageIndex]);
InitializeComponent();
}
預設語系、中文語系
英文語系:
// 使用多語系變數的方式
// 資源檔名稱.變數名稱
LanguageResources.Name
// 校驗文字
string[] allTextBoxName = new string[]{LanguageResources.Name,
LanguageResources.HomeTown,
LanguageResources.Birthday_Year,
LanguageResources.Birthday_Month,
LanguageResources.Birthday_Day };
for (int i = 0; i < allTextBox.GetLength(0); i++)
{
if (string.IsNullOrEmpty(allTextBox[i].Text))
{
errorMsg.AppendLine(string.Format(LanguageResources.Message_PleaseInput, allTextBoxName[i]));
}
}
if (errorMsg.ToString() != "")
{
MessageBox.Show(errorMsg.ToString());
return;
}
if (!Regex.IsMatch(birthdate_YearBox.Text, @"\d") || !Regex.IsMatch(birthdate_MonthBox.Text, @"\d") || !Regex.IsMatch(birthdate_DayBox.Text, @"\d"))
{
MessageBox.Show(LanguageResources.Message_BirthdayNeedNum);
return;
}
// 自我介紹的文字
string introductionText = string.Format(LanguageResources.Message_IntrouductionText, name, homeTown, yearOld);
Program.cs 【最先被執行的程式檔】
using System;
using System.Windows.Forms;
namespace IT_Day01
{
static class Program
{
/// <summary>
/// 應用程式的主要進入點。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LanguageSelectForm());
}
}
}
LanguageSelectForm.cs 【選擇語系視窗】
using System;
using System.Windows.Forms;
namespace IT_Day01
{
public partial class LanguageSelectForm : Form
{
public LanguageSelectForm()
{
InitializeComponent();
}
/// <summary>
/// 視窗載入時,設定語言預設為中文
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void LanguageSelectForm_Load(object sender, EventArgs e)
{
languageComboBox.SelectedIndex = 0;
}
/// <summary>
/// 帶入選擇的語言到主視窗
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void selectBtn_Click(object sender, EventArgs e)
{
IntroductionForm introductionForm = new IntroductionForm(languageComboBox.SelectedIndex);
introductionForm.FormClosed += introductionForm_FormClosed;
introductionForm.Show();
this.Visible = false;
}
/// <summary>
/// 關閉視窗後,重新開啟語系選擇的視窗
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void introductionForm_FormClosed(object sender, FormClosedEventArgs e)
{
this.Visible = true;
}
}
}
IntroductionForm.cs 【自我介紹視窗】
using System;
using System.Drawing;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
namespace IT_Day01
{
public partial class IntroductionForm : Form
{
public IntroductionForm(int languageIndex)
{
string[] language = { "zh-TW", "en-US" };
Thread.CurrentThread.CurrentUICulture = new CultureInfo(language[languageIndex]);
InitializeComponent();
}
/// <summary>
/// 顯示邀請自我介紹的文字
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void IntroductionForm_Load(object sender, EventArgs e)
{
MessageBox.Show(LanguageResources.FormStart);
}
/// <summary>
/// 選擇相片
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void photoBox_DoubleClick(object sender, EventArgs e)
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
if (fileDialog.ShowDialog() == DialogResult.OK && fileDialog.FileName != "")
{
photoBox.Image = Image.FromFile(fileDialog.FileName);
}
}
/// <summary>
/// 自我介紹按鈕滑鼠偵聽事件:處理按下自我介紹按鈕後要做的事情
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void showIntroductionBtn_Click(object sender, EventArgs e)
{
// 校驗每個欄位是否輸入
TextBox[] allTextBox = new TextBox[] { nameTextBox, homeTownTextBox, birthdate_YearBox, birthdate_MonthBox, birthdate_DayBox };
string[] allTextBoxName = new string[]{LanguageResources.Name, LanguageResources.HomeTown,
LanguageResources.Birthday_Year, LanguageResources.Birthday_Month, LanguageResources.Birthday_Day };
StringBuilder errorMsg = new StringBuilder();
for (int i = 0; i < allTextBox.GetLength(0); i++)
{
if (string.IsNullOrEmpty(allTextBox[i].Text))
{
errorMsg.AppendLine(string.Format(LanguageResources.Message_PleaseInput, allTextBoxName[i]));
}
}
if (errorMsg.ToString() != "")
{
MessageBox.Show(errorMsg.ToString());
return;
}
// 校驗日期格式是否正確
if (!Regex.IsMatch(birthdate_YearBox.Text, @"\d") || !Regex.IsMatch(birthdate_MonthBox.Text, @"\d") || !Regex.IsMatch(birthdate_DayBox.Text, @"\d"))
{
MessageBox.Show(LanguageResources.Message_BirthdayNeedNum);
return;
}
// 取得使用者輸入的姓名和家鄉
string name = nameTextBox.Text;
string homeTown = homeTownTextBox.Text;
// 取得當下的日期
int today_Year = DateTime.Today.Year;
int today_Month = DateTime.Today.Month;
int today_Day = DateTime.Today.Day;
int yearOld;
// 計算年齡
int birthDate_Year = int.Parse(birthdate_YearBox.Text);
int birthDate_Month = int.Parse(birthdate_MonthBox.Text);
int birthDate_Day = int.Parse(birthdate_DayBox.Text);
yearOld = today_Year - int.Parse(birthdate_YearBox.Text);
if (today_Month < birthDate_Month || (today_Month == birthDate_Month && today_Day < birthDate_Day))
{
yearOld = yearOld - 1;
}
// 顯示自我介紹
string introductionText = string.Format(LanguageResources.Message_IntrouductionText, name, homeTown, yearOld);
MessageBox.Show(introductionText);
}
/// <summary>
/// 自訂函式:判斷是否為整數
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
private bool stringIsInt(string num)
{
int tryParse;
return int.TryParse(num, out tryParse);
}
/// <summary>
/// 生日欄位的鍵盤偵聽事件,讓使用者只能輸入數字
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void birthdate_YearBox_KeyPress(object sender, KeyPressEventArgs e)
{
char inputChar = e.KeyChar;
e.Handled = ! (char.IsDigit(inputChar) || char.IsControl(e.KeyChar));
}
}
}
當你嘗試Google 「C# multiple language」、「WinForm 多語系」 你會發現有上百種的解法,大約需要翻5~10個網頁才會找到幾個相對比較簡潔的做法,所以對於程式初學者來說,缺的不是資源,而是找到有用資料的方向
多語系在一個商務系統,也是常見的基本要求,另外也透過多語系的功能需求,展示C#在跨視窗的實際應用。
明天接著實作下一個變化:可以將每一次的自我介紹資料寫到一個檔案、儲存使用者選擇的照片檔,以方便每一次執行程式不需要重新輸入個人資訊和選擇照片。