時間になったら知らせてくれるタイマーは便利な存在です。普通のタイマーはひとつの時間しか設定できませんが、複数の時間を設定することができるタイマーをつくることにします。
Contents
マルチタイマーをつくる
ではさっそくつくってみましょう。
作成するもの
デザイナで以下のようなものをつくります。
Form1クラス
FormConfigクラス
TimeControlクラス
TimeMessageクラス
時間になったらメッセージを表示するので時間とメッセージを管理するためのクラスを作成します。作成するクラスの名前はTimeMessageとします。
1 2 3 4 5 6 |
public class TimeMessage { public int Hour = 0; public int Minute = 0; public string Message = ""; } |
FormConfigクラスとTimeControlクラス
設定のためのフォームFormConfigにはユーザーコントロールTimeControlを10個貼り付けています。
まずTimeControlクラスをみてみましょう。
データを設定するためのメソッドと取得するためのメソッドを定義しています。アップダウンコントロールとテキストボックスに入力された文字列・値をこれで管理します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class TimeControl : UserControl { public TimeControl() { InitializeComponent(); } public TimeMessage GetData() { TimeMessage timeMessage = new TimeMessage(); timeMessage.Hour = (int)hourUpDown.Value; timeMessage.Minute = (int)minuteUpDown.Value; timeMessage.Message = messageTextBox.Text; return timeMessage; } public void SetData(TimeMessage tm) { hourUpDown.Value = tm.Hour; minuteUpDown.Value = tm.Minute; messageTextBox.Text = tm.Message; } } |
つぎにFormConfigクラスをみてみましょう。
コンストラクタでは10個のTimeControlをリストにしています。FormConfigを表示するときには先にフィールド変数timeMessagesにデータをセットしておきます。
また[反映]ボタンが押されるとダイアログの[OK]ボタンが押されたときと同じ処理が行なわれるようにbutton1のDialogResultプロパティにDialogResult.OKを設定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class FormConfig : Form { List<TimeControl> timeControls = new List<TimeControl>(); public List<TimeMessage> timeMessages = new List<TimeMessage>(); public FormConfig() { InitializeComponent(); timeControls.Add(timeControl0); timeControls.Add(timeControl1); timeControls.Add(timeControl2); timeControls.Add(timeControl3); timeControls.Add(timeControl4); timeControls.Add(timeControl5); timeControls.Add(timeControl6); timeControls.Add(timeControl7); timeControls.Add(timeControl8); timeControls.Add(timeControl9); button1.DialogResult = DialogResult.OK; } } |
FormConfigが表示されるときにセットされているデータを表示させます。timeControls[i]に表示されるデータはtimeMessages[i]のデータになるようにfor文を使ってデータをセットしています。
1 2 3 4 5 6 7 8 9 |
public partial class FormConfig : Form { private void FormConfig_Load(object sender, EventArgs e) { int cnt = timeMessages.Count; for(int i=0; i<cnt; i++) timeControls[i].SetData(timeMessages[i]); } } |
[反映]ボタンをおすとそれぞれのTimeControlからデータを取得してtimeMessagesに格納しています。
1 2 3 4 5 6 7 8 9 |
public partial class FormConfig : Form { private void button1_Click(object sender, EventArgs e) { timeMessages.Clear(); foreach(TimeControl timeControl in timeControls) timeMessages.Add(timeControl.GetData()); } } |
Form1クラス
最後にメインになるForm1クラスについて。
コンストラクタでタイマーの設定を行なっています。10秒ごとにイベントが発生するようにしています。Tickイベントがおきたら時刻を調べてtimeMessagesに設定されているデータと照合してメッセージの表示が必要かどうかを判断しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public partial class Form1 : Form { List <TimeMessage> timeMessages = new List<TimeMessage>(); int DATA_COUNT = 10; public Form1() { InitializeComponent(); timer1.Interval = 10 * 1000; timer1.Start(); for(int i = 0; i< DATA_COUNT; i++) timeMessages.Add(new TimeMessage()); } } |
Tickイベントの処理は1分に1回でよいので現在時刻が何分か調べてそれをフィールド変数lastMinuteに格納しています。次にTickイベントがおきても同じ「分」であればなにもおきないようにしています。
timeMessagesに格納されているデータと現在時刻が同じかどうかを調べています。同じであればダイアログを表示させて設定時刻とメッセージを表示させています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public partial class Form1 : Form { int lastMinute = -1; private void timer1_Tick(object sender, EventArgs e) { DateTime dtNow = DateTime.Now; if(lastMinute == dtNow.Minute) return; lastMinute = dtNow.Minute; foreach(TimeMessage tm in timeMessages) { if(tm.Hour == dtNow.Hour && tm.Minute == dtNow.Minute) { FormMessage f = new FormMessage(); f.label1.Text = String.Format("{0} 時 {1:00}分です", tm.Hour, tm.Minute); f.label2.Text = tm.Message; f.Text = "メッセージ"; f.ShowDialog(); f.Dispose(); } } } } |
時刻を設定する処理も必要です。[設定]ボタンをクリックするとFormConfigが表示されます。そして[反映]ボタンが押されたときだけダイアログに入力されたデータを取得して、Form1のフィールド変数timeMessagesに保存しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class Form1 : Form { private void buttonConfig_Click(object sender, EventArgs e) { FormConfig f = new FormConfig(); f.timeMessages = timeMessages; f.Text = "設定"; DialogResult dr = f.ShowDialog(); if(dr == DialogResult.OK) { timeMessages = f.timeMessages; } f.Dispose(); } } |
設定を保存する
これだけだとアプリケーションを終了させるとまた設定をしなおさないといけません。そこで設定を保存できるようにします。
まずは設定を保存する場合の処理について。SaveConfigメソッドを作成し、そのなかで設定の保存をおこないます。SaveConfigメソッドが呼び出されるタイミングは新しい設定が完了したときでよいと思われます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class Form1 : Form { private void buttonConfig_Click(object sender, EventArgs e) { FormConfig f = new FormConfig(); f.timeMessages = timeMessages; f.Text = "設定"; DialogResult dr = f.ShowDialog(); if(dr == DialogResult.OK) { timeMessages = f.timeMessages; SaveConfig(); // これを追加 } f.Dispose(); } } |
次にSaveConfigメソッドの内容ですが、今後ほかにもファイルとして保存したいものができるかもしれないので、別クラスとしてDocクラスを作成します。Docクラスのインスタンスを生成してそこにtimeMessagesの内容を保存してからこれをファイルとして保存します。
保存されるファイルの名前はconfig.xmlとして場所は実行ファイルと同じフォルダにします。コンストラクタでフィールド変数configFilePathにconfig.xmlのパスを格納します。
1 2 3 4 |
public class Doc { public List<TimeMessage> timeMessages = new List<TimeMessage>(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System.Xml.Serialization; using System.IO; public partial class Form1 : Form { string configFilePath = ""; public Form1() { configFilePath = Application.StartupPath + "\\config.xml"; // その他の処理は省略 } void SaveConfig() { Doc doc = new Doc(); doc.timeMessages = timeMessages; XmlSerializer xml = new XmlSerializer(typeof(Doc)); StreamWriter sw = new StreamWriter(configFilePath); xml.Serialize(sw, doc); sw.Close(); } } |
これは設定をファイルから読み込むためのメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public partial class Form1 : Form { void LoadConfig() { if(!File.Exists(configFilePath)) return; XmlSerializer xml = new XmlSerializer(typeof(Doc)); StreamReader sr = new StreamReader(configFilePath); Doc doc = (Doc)xml.Deserialize(sr); sr.Close(); timeMessages = doc.timeMessages; } } |
マルチタイマーを起動するたびに自分で設定ファイルを読み込ませるのは不便ではないでしょうか? 実行されると自動で設定ファイルが読み込まれるように、コンストラクタ内で以下の処理をおこないます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); timer1.Interval = 10 * 1000; timer1.Start(); // 設定が保存されているファイルのパス configFilePath = Application.StartupPath + "\\config.xml"; for(int i = 0; i< DATA_COUNT; i++) timeMessages.Add(new TimeMessage()); Text = Application.ProductName; LoadConfig(); // 設定が保存されているファイルを読み込む } } |
また前回の時間を管理するアプリと同様
うっかり終了させてしまわないように、そして必要ないときはタスクトレイのなかに入れておくために以下のメソッドを定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public partial class Form1 : Form { bool isEnd = false; // ×ボタンをクリックしたら終了しないで非表示にする private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if(isEnd) { return; } e.Cancel = true; this.Visible = false; this.TopMost = false; } // 通知アイコンがクリックされたときにフォームを表示させる private void notifyIcon1_MouseClick(object sender, MouseEventArgs e) { this.Visible = true; } // 本当にアプリケーションを終了させたいときの処理 private void button1_Click(object sender, EventArgs e) { isEnd = true; Application.Exit(); } } |