カウントダウンタイマー祭りへのエントリー(保険版)
本当はもっと変なところに力を入れたやつを作成中なんだけど、期限に間に合うかとても不安なので、テスト用に作ったやつを先に載せておきます。
面倒だったので Visual Studio を使わずに全部秀丸で書いちゃいました。
一応、 C# 3.0 向け。
- CountdownTimerLite.cs
using System; using System.Collections; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; using System.Runtime.InteropServices; namespace Jp.Mkns.Products.CountdownTimerLite { class TimerSetting { public int ID { get; set; } public string Text { get; set; } public int Hours { get; set; } public int Minutes { get; set; } public int Seconds { get; set; } } class HotKey { public int ID { get; set; } public int Key { get; set; } public int SpecialKeys { get; set; } public Action Execute { get; set; } } class TimerViewer : Form { private Label label; private Timer timer; private ContextMenuStrip contextMenu; private ToolStripMenuItem controlMenuItem; private ToolStripMenuItem settingMenuItem; private ToolStripMenuItem settingPlus4SecondsMenuItem; private ToolStripMenuItem exitMenuItem; private ToolStripMenuItem controlStartMenuItem; private ToolStripMenuItem controlPauseMenuItem; private ToolStripMenuItem controlClearMenuItem; private List<TimerSetting> timerSetting; private List<HotKey> hotkeys; private DateTime targetDate; private DateTime pauseDate; private bool? isActive; public TimerViewer() { this.InitializeComponent(); this.timerSetting = new List<TimerSetting>() { new TimerSetting() { ID = 5, Text = "5 分", Hours = 0, Minutes = 5, Seconds = 0 }, new TimerSetting() { ID = 10, Text = "10 分", Hours = 0, Minutes = 10, Seconds = 0 }, new TimerSetting() { ID = 15, Text = "15 分", Hours = 0, Minutes = 15, Seconds = 0 }, new TimerSetting() { ID = 20, Text = "20 分", Hours = 0, Minutes = 20, Seconds = 0 }, new TimerSetting() { ID = 30, Text = "30 分", Hours = 0, Minutes = 30, Seconds = 0 }, new TimerSetting() { ID = 50, Text = "50 分", Hours = 0, Minutes = 50, Seconds = 0 }, new TimerSetting() { ID = 60, Text = "60 分", Hours = 1, Minutes = 0, Seconds = 0 }, new TimerSetting() { ID = 70, Text = "70 分", Hours = 1, Minutes = 10, Seconds = 0 }, new TimerSetting() { ID = 75, Text = "75 分", Hours = 1, Minutes = 15, Seconds = 0 }, new TimerSetting() { ID = 90, Text = "90 分", Hours = 1, Minutes = 30, Seconds = 0 }, new TimerSetting() { ID = 120, Text = "120 分", Hours = 2, Minutes = 0, Seconds = 0 } }; this.RegistTimerSetting(); this.hotkeys = new List<HotKey>() { new HotKey() { ID = 0x0101, Key = (int)Keys.S, SpecialKeys = MOD_CONTROL | MOD_SHIFT, Execute = this.StartTimer }, new HotKey() { ID = 0x0102, Key = (int)Keys.L, SpecialKeys = MOD_CONTROL | MOD_SHIFT, Execute = this.PauseTimer }, new HotKey() { ID = 0x0103, Key = (int)Keys.C, SpecialKeys = MOD_CONTROL | MOD_SHIFT, Execute = this.ClearTimer }, new HotKey() { ID = 0x0109, Key = (int)Keys.Q, SpecialKeys = MOD_CONTROL | MOD_SHIFT, Execute = this.Close } }; this.RegistHotKey(); this.isActive = null; } protected override void WndProc(ref Message m) { int param; base.WndProc(ref m); if (m.Msg == WM_HOTKEY) { param = (int) m.WParam; var target = from data in this.hotkeys where data.ID == param select data; foreach (var hotKey in target) { hotKey.Execute(); } } } private void InitializeComponent() { this.label = new Label(); this.contextMenu = new ContextMenuStrip(); this.controlMenuItem = new ToolStripMenuItem(); this.settingMenuItem = new ToolStripMenuItem(); this.settingPlus4SecondsMenuItem = new ToolStripMenuItem(); this.exitMenuItem = new ToolStripMenuItem(); this.controlStartMenuItem = new ToolStripMenuItem(); this.controlPauseMenuItem = new ToolStripMenuItem(); this.controlClearMenuItem = new ToolStripMenuItem(); this.label.Location = new Point(0, 0); this.label.AutoSize = false; this.label.Size = new Size(121, 31); this.label.Font = new System.Drawing.Font("メイリオ", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(128))); this.label.TextAlign = ContentAlignment.MiddleCenter; this.label.Text = @"00:00:00"; this.label.KeyDown += (sender, e) => MessageBox.Show("Label KeyDown"); this.label.MouseDoubleClick += (sender, e) => this.Close(); this.label.ContextMenuStrip = this.contextMenu; this.controlMenuItem.Text = "タイマー(&T)"; this.settingMenuItem.Text = "時間(&C)"; this.settingPlus4SecondsMenuItem.Text = "5秒前からカウント開始する(&P)"; this.settingPlus4SecondsMenuItem.Checked = true; this.settingPlus4SecondsMenuItem.Click += (sender, e) => this.settingPlus4SecondsMenuItem.Checked = !this.settingPlus4SecondsMenuItem.Checked; this.exitMenuItem.Text = "終了(&Q)"; this.exitMenuItem.Click += (sender, e) => this.Close(); this.controlStartMenuItem.Text = "開始(&S)"; this.controlStartMenuItem.Click += (sender, e) => this.StartTimer(); this.controlStartMenuItem.Enabled = true; this.controlPauseMenuItem.Text = "一時停止(&P)"; this.controlPauseMenuItem.Click += (sender, e) => this.PauseTimer(); this.controlPauseMenuItem.Enabled = false; this.controlClearMenuItem.Text = "クリア(&C)"; this.controlClearMenuItem.Click += (sender, e) => this.ClearTimer(); this.controlClearMenuItem.Enabled = false; this.contextMenu.Items.AddRange( new ToolStripMenuItem[] { this.controlMenuItem, this.settingMenuItem, this.settingPlus4SecondsMenuItem, this.exitMenuItem }); this.controlMenuItem.DropDownItems.AddRange( new ToolStripMenuItem[] { this.controlStartMenuItem, this.controlPauseMenuItem, this.controlClearMenuItem }); this.Location = new Point(0, 0); this.Size = new Size(121, 31); this.FormBorderStyle = FormBorderStyle.None; this.Text = "タイマー"; this.TransparencyKey = this.BackColor; this.Opacity = 1; this.StartPosition = FormStartPosition.Manual; this.ShowInTaskbar = false; this.TopMost = true; this.Activated += (sender, e) => this.Opacity = 1; this.Deactivate += (sender, e) => this.Opacity = 0.6; this.MouseDoubleClick += (sender, e) => this.Close(); this.Closed += (sender, e) => this.UnregistHotKey(); this.Controls.Add(this.label); this.timer = new Timer(); this.timer.Interval = 50; this.timer.Tick += (sender, e) => this.Timer_Tick(); } private void RegistTimerSetting() { ToolStripMenuItem item; this.settingMenuItem.DropDownItems.Clear(); foreach (TimerSetting setting in this.timerSetting) { item = new ToolStripMenuItem(); item.Text = setting.Text; item.Checked = false; item.Click += (sender, e) => this.ChangeTimer((ToolStripMenuItem)sender); item.Tag = setting.ID; this.settingMenuItem.DropDownItems.Add(item); } ((ToolStripMenuItem)this.settingMenuItem.DropDownItems[0]).Checked = true; } private void RegistHotKey() { foreach (var hotKey in this.hotkeys) { RegisterHotKey(this.Handle, hotKey.ID, hotKey.SpecialKeys, hotKey.Key); } } private void UnregistHotKey() { foreach (var hotKey in this.hotkeys) { UnregisterHotKey(this.Handle, hotKey.ID); } } private void StartTimer() { TimeSpan pause; DateTime nowDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second); int targetId = 0; if (this.isActive == null) { this.targetDate = nowDate; this.pauseDate = nowDate; foreach (ToolStripMenuItem item in this.settingMenuItem.DropDownItems) { if (item.Checked) { targetId = (int)item.Tag; break; } } if (targetId == 0) { return; } var target = from data in this.timerSetting where data.ID == targetId select data; var targetCollection = target.ToArray(); this.targetDate = this.targetDate.AddHours(targetCollection[0].Hours).AddMinutes(targetCollection[0].Minutes).AddSeconds(targetCollection[0].Seconds); if (this.settingPlus4SecondsMenuItem.Checked) { this.targetDate = this.targetDate.AddSeconds(5); } this.label.ForeColor = Color.Black; } else if (this.isActive == true) { return; } else { pause = this.targetDate - pauseDate; this.targetDate = nowDate.AddTicks(pause.Ticks); } this.timer.Start(); this.isActive = true; this.ChangeControlMenu(); } private void PauseTimer() { if (this.isActive == false) { return; } this.pauseDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second); this.timer.Stop(); this.isActive = false; this.ChangeControlMenu(); } private void ClearTimer() { if (this.isActive == true) { return; } this.label.Text = "00:00:00"; this.label.ForeColor = Color.Black; this.isActive = null; this.ChangeControlMenu(); } private void ChangeTimer(ToolStripMenuItem target) { if (this.isActive != null) { this.PauseTimer(); this.ClearTimer(); } foreach (ToolStripMenuItem item in this.settingMenuItem.DropDownItems) { item.Checked = false; } target.Checked = true; } private void ChangeControlMenu() { if (this.isActive == null) { this.controlStartMenuItem.Enabled = true; this.controlPauseMenuItem.Enabled = false; this.controlClearMenuItem.Enabled = false; } else if (this.isActive == true) { this.controlStartMenuItem.Enabled = false; this.controlPauseMenuItem.Enabled = true; this.controlClearMenuItem.Enabled = false; } else { this.controlStartMenuItem.Enabled = true; this.controlPauseMenuItem.Enabled = false; this.controlClearMenuItem.Enabled = true; } } private void Timer_Tick() { DateTime nowDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second); TimeSpan span = this.targetDate - nowDate; if (span.Ticks <= 0) { this.label.ForeColor = Color.Red; span = span.Duration(); } this.label.Text = String.Format("{0:00}:{1:00}:{2:00}", span.Hours, span.Minutes, span.Seconds); } static void Main() { Application.Run(new TimerViewer()); } #region win32 DLL import const int MOD_ALT = 0x0001; const int MOD_CONTROL = 0x0002; const int MOD_SHIFT = 0x0004; const int WM_HOTKEY = 0x0312; [DllImport("user32.dll")] extern static int RegisterHotKey(IntPtr HWnd, int ID, int MOD_KEY, int KEY); [DllImport("user32.dll")] extern static int UnregisterHotKey(IntPtr HWnd, int ID); #endregion } }
> csc.exe /t:winexe CountdownTimerLite.cs > CountdownTimer.exe
で左上に「 00:00:00 」な表示が出ます。
後は、ホットキーを登録しているので、
- Ctrl + Shift + S
- カウントダウン開始
- Ctrl + Shift + L
- 一時停止
- Ctrl + Shift + C
- 一時停止状態のときにタイマークリア
- Ctrl + Shift + Q
- 終了
って感じでいけます。
ちなみに、数値上で右クリックするとメニューが出るので、そっちからも操作も可能。
カウントダウンする時間もメニューで選択可能です。
(面倒なのでスクリーンショットは省略。あくまでも「保険」用なので悪しからず。)