http://www.codeproject.com/KB/cs/timeralarm.aspx
timerForm.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Timers;
using System.IO;
using System.Reflection;
namespace timerAlarm
{
public class TimerForm : System.Windows.Forms.Form
{
private WaveLib.WaveOutPlayer m_Player;
private WaveLib.WaveFormat m_Format;
private Stream m_AudioStream;
private System.Windows.Forms.MenuItem menuItemReset;
private System.Windows.Forms.MenuItem menuItemOpen;
private System.Windows.Forms.TextBox timerInput;
private System.Windows.Forms.Button StartButton;
private System.Windows.Forms.Button ResetButton;
private System.Windows.Forms.NotifyIcon notifyIcon;
private System.Windows.Forms.ContextMenu notifyMenu;
private System.ComponentModel.IContainer components;
private System.Timers.Timer timerClock = new System.Timers.Timer();
private int clockTime = 0;
private int alarmTime = 0;
public TimerForm()
{
InitializeComponent();
InitializeTimer();
InitializeSound();
InitializeNotifyMenu();
}
protected override void Dispose( bool disposing )
{
CloseSound();
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(TimerForm));
this.timerInput = new System.Windows.Forms.TextBox();
this.StartButton = new System.Windows.Forms.Button();
this.ResetButton = new System.Windows.Forms.Button();
this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
this.notifyMenu = new System.Windows.Forms.ContextMenu();
this.SuspendLayout();
//
// timerInput
//
this.timerInput.Location = new System.Drawing.Point(12, 13);
this.timerInput.Name = "timerInput";
this.timerInput.Size = new System.Drawing.Size(50, 20);
this.timerInput.TabIndex = 0;
this.timerInput.Text = "00:00:00";
//
// StartButton
//
this.StartButton.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.StartButton.Location = new System.Drawing.Point(75, 11);
this.StartButton.Name = "StartButton";
this.StartButton.TabIndex = 1;
this.StartButton.Text = "Start";
this.StartButton.Click += new System.EventHandler(this.StartButton_Click);
//
// ResetButton
//
this.ResetButton.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.ResetButton.Location = new System.Drawing.Point(161, 11);
this.ResetButton.Name = "ResetButton";
this.ResetButton.TabIndex = 2;
this.ResetButton.Text = "Reset";
this.ResetButton.Click += new System.EventHandler(this.ResetButton_Click);
//
// notifyIcon
//
this.notifyIcon.ContextMenu = this.notifyMenu;
this.notifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon.Icon")));
this.notifyIcon.Text = "Alarm Timer";
this.notifyIcon.Visible = true;
this.notifyIcon.DoubleClick += new System.EventHandler(this.menuItemOpen_Click);
//
// TimerForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(247, 46);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.ResetButton,
this.StartButton,
this.timerInput});
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.Name = "TimerForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Alarm Timer";
this.Resize += new System.EventHandler(this.TimerForm_Resized);
this.ResumeLayout(false);
}
#endregion
public void InitializeTimer()
{
this.timerClock.Elapsed += new ElapsedEventHandler(OnTimer);
this.timerClock.Interval = 1000;
this.timerClock.Enabled = true;
}
private void InitializeSound()
{
try
{
// get a reference to the current assembly
Assembly a = Assembly.GetExecutingAssembly();
WaveLib.WaveStream S = new WaveLib.WaveStream( a.GetManifestResourceStream( "timerAlarm.alarm.wav" ) );
if (S.Length <= 0)
throw new Exception("Invalid WAV file");
m_Format = S.Format;
if (m_Format.wFormatTag != (short)WaveLib.WaveFormats.Pcm && m_Format.wFormatTag != (short)WaveLib.WaveFormats.Float)
throw new Exception("Olny PCM files are supported");
m_AudioStream = S;
}
catch(Exception e)
{
CloseSound();
MessageBox.Show("InitializeSound(): " + e.Message );
}
}
private void InitializeNotifyMenu()
{
try
{
this.menuItemReset = new MenuItem("Reset Alarm");
menuItemReset.Click += new System.EventHandler(this.menuItemReset_Click);
this.menuItemOpen = new MenuItem("Open Alarm Timer");
menuItemOpen.Click += new System.EventHandler(this.menuItemOpen_Click);
this.notifyMenu.MenuItems.Clear();
this.notifyMenu.MenuItems.Add( this.menuItemOpen );
this.notifyMenu.MenuItems.Add( this.menuItemReset );
}
catch(Exception e)
{
MessageBox.Show("InitializeNotifyMenu(): " + e.Message );
}
}
[STAThread]
static void Main()
{
Application.Run(new TimerForm());
}
private void TimerForm_Resized(object sender, System.EventArgs e)
{
if( this.WindowState == FormWindowState.Minimized )
{
this.Hide();
}
}
private void menuItemReset_Click(object sender, System.EventArgs e)
{
ResetButton_Click( null, null );
}
private void menuItemOpen_Click(object sender, System.EventArgs e)
{
this.Show();
this.WindowState = FormWindowState.Normal;
}
private void StartButton_Click(object sender, System.EventArgs e)
{
this.clockTime = 0;
inputToSeconds( this.timerInput.Text );
}
private void ResetButton_Click(object sender, System.EventArgs e)
{
try
{
this.clockTime = 0;
this.alarmTime = 0;
this.timerInput.Text = "00:00:00";
StopSound();
}
catch( Exception ex )
{
MessageBox.Show("ResetButton_Click(): " + ex.Message );
}
}
public void OnTimer(Object source, ElapsedEventArgs e)
{
try
{
this.clockTime++;
int countdown = this.alarmTime - this.clockTime ;
if( this.alarmTime != 0 )
{
this.timerInput.Text = secondsToTime(countdown);
}
//Sound Alarm
if( this.clockTime == this.alarmTime )
{
PlaySound();
}
}
catch( Exception ex )
{
MessageBox.Show("OnTimer(): " + ex.Message );
}
}
private void inputToSeconds( string timerInput )
{
try
{
string[] timeArray = new string[3];
int minutes = 0;
int hours = 0;
int seconds = 0;
int occurence = 0;
int length = 0;
occurence = timerInput.LastIndexOf(":");
length = timerInput.Length;
//Check for invalid input
if( occurence == -1 || length != 8 )
{
MessageBox.Show("Invalid Time Format.");
ResetButton_Click( null, null );
}
else
{
timeArray = timerInput.Split(':');
seconds = Convert.ToInt32( timeArray[2] );
minutes = Convert.ToInt32( timeArray[1] );
hours = Convert.ToInt32( timeArray[0] );
this.alarmTime += seconds;
this.alarmTime += minutes*60;
this.alarmTime += (hours*60)*60;
}
}
catch( Exception e )
{
MessageBox.Show("inputToSeconds(): " + e.Message );
}
}
public string secondsToTime( int seconds )
{
int minutes = 0;
int hours = 0;
while( seconds >= 60 )
{
minutes += 1;
seconds -= 60;
}
while( minutes >= 60 )
{
hours += 1;
minutes -= 60;
}
string strHours = hours.ToString();
string strMinutes = minutes.ToString();
string strSeconds = seconds.ToString();
if( strHours.Length < 2 ) strHours = "0" + strHours;
if( strMinutes.Length < 2 ) strMinutes = "0" + strMinutes;
if( strSeconds.Length < 2 ) strSeconds = "0" + strSeconds;
return strHours + ":" + strMinutes + ":" + strSeconds;
}
private void CloseSound()
{
this.StopSound();
if (m_AudioStream != null)
try
{
m_AudioStream.Close();
}
finally
{
m_AudioStream = null;
}
}
private void StopSound()
{
if (m_Player != null)
try
{
m_Player.Dispose();
}
finally
{
m_Player = null;
}
}
private void PlaySound()
{
this.StopSound();
if (m_AudioStream != null)
{
m_AudioStream.Position = 0;
m_Player = new WaveLib.WaveOutPlayer(-1, m_Format, 16384, 3, new WaveLib.BufferFillEventHandler(Filler));
}
}
private void Filler(IntPtr data, int size)
{
byte[] b = new byte[size];
if (m_AudioStream != null)
{
int pos = 0;
while (pos < size)
{
int toget = size - pos;
int got = m_AudioStream.Read(b, pos, toget);
if (got < toget)
m_AudioStream.Position = 0; // loop if the file ends
pos += got;
}
}
else
{
for (int i = 0; i < b.Length; i++)
b[i] = 0;
}
System.Runtime.InteropServices.Marshal.Copy(b, 0, data, size);
}
}
}
=================================
WaveNative.cs
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// This material may not be duplicated in whole or in part, except for
// personal use, without the express written consent of the author.
//
// Email:
[email protected]
//
// Copyright (C) 1999-2003 Ianier Munoz. All Rights Reserved.
using System;
using System.Runtime.InteropServices;
namespace WaveLib
{
public enum WaveFormats
{
Pcm = 1,
Float = 3
}
[StructLayout(LayoutKind.Sequential)]
public class WaveFormat
{
public short wFormatTag;
public short nChannels;
public int nSamplesPerSec;
public int nAvgBytesPerSec;
public short nBlockAlign;
public short wBitsPerSample;
public short cbSize;
public WaveFormat(int rate, int bits, int channels)
{
wFormatTag = (short)WaveFormats.Pcm;
nChannels = (short)channels;
nSamplesPerSec = rate;
wBitsPerSample = (short)bits;
cbSize = 0;
nBlockAlign = (short)(channels * (bits / 8));
nAvgBytesPerSec = nSamplesPerSec * nBlockAlign;
}
}
internal class WaveNative
{
// consts
public const int MMSYSERR_NOERROR = 0; // no error
public const int MM_WOM_OPEN = 0x3BB;
public const int MM_WOM_CLOSE = 0x3BC;
public const int MM_WOM_DONE = 0x3BD;
public const int CALLBACK_FUNCTION = 0x00030000; // dwCallback is a FARPROC
public const int TIME_MS = 0x0001; // time in milliseconds
public const int TIME_SAMPLES = 0x0002; // number of wave samples
public const int TIME_BYTES = 0x0004; // current byte offset
// callbacks
public delegate void WaveDelegate(IntPtr hdrvr, int uMsg, int dwUser, ref WaveHdr wavhdr, int dwParam2);
// structs
[StructLayout(LayoutKind.Sequential)] public struct WaveHdr
{
public IntPtr lpData; // pointer to locked data buffer
public int dwBufferLength; // length of data buffer
public int dwBytesRecorded; // used for input only
public IntPtr dwUser; // for client's use
public int dwFlags; // assorted flags (see defines)
public int dwLoops; // loop control counter
public IntPtr lpNext; // PWaveHdr, reserved for driver
public int reserved; // reserved for driver
}
private const string mmdll = "winmm.dll";
// native calls
[DllImport(mmdll)]
public static extern int waveOutGetNumDevs();
[DllImport(mmdll)]
public static extern int waveOutPrepareHeader(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize);
[DllImport(mmdll)]
public static extern int waveOutUnprepareHeader(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize);
[DllImport(mmdll)]
public static extern int waveOutWrite(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize);
[DllImport(mmdll)]
public static extern int waveOutOpen(out IntPtr hWaveOut, int uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback, int dwInstance, int dwFlags);
[DllImport(mmdll)]
public static extern int waveOutReset(IntPtr hWaveOut);
[DllImport(mmdll)]
public static extern int waveOutClose(IntPtr hWaveOut);
[DllImport(mmdll)]
public static extern int waveOutPause(IntPtr hWaveOut);
[DllImport(mmdll)]
public static extern int waveOutRestart(IntPtr hWaveOut);
[DllImport(mmdll)]
public static extern int waveOutGetPosition(IntPtr hWaveOut, out int lpInfo, int uSize);
[DllImport(mmdll)]
public static extern int waveOutSetVolume(IntPtr hWaveOut, int dwVolume);
[DllImport(mmdll)]
public static extern int waveOutGetVolume(IntPtr hWaveOut, out int dwVolume);
}
}
===================
WaveOut.cs
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// This material may not be duplicated in whole or in part, except for
// personal use, without the express written consent of the author.
//
// Email:
[email protected]
//
// Copyright (C) 1999-2003 Ianier Munoz. All Rights Reserved.
using System;
using System.Threading;
using System.Runtime.InteropServices;
namespace WaveLib
{
internal class WaveOutHelper
{
public static void Try(int err)
{
if (err != WaveNative.MMSYSERR_NOERROR)
throw new Exception(err.ToString());
}
}
public delegate void BufferFillEventHandler(IntPtr data, int size);
internal class WaveOutBuffer : IDisposable
{
public WaveOutBuffer NextBuffer;
private AutoResetEvent m_PlayEvent = new AutoResetEvent(false);
private IntPtr m_WaveOut;
private WaveNative.WaveHdr m_Header;
private byte[] m_HeaderData;
private GCHandle m_HeaderHandle;
private GCHandle m_HeaderDataHandle;
private bool m_Playing;
internal static void WaveOutProc(IntPtr hdrvr, int uMsg, int dwUser, ref WaveNative.WaveHdr wavhdr, int dwParam2)
{
if (uMsg == WaveNative.MM_WOM_DONE)
{
try
{
GCHandle h = (GCHandle)wavhdr.dwUser;
WaveOutBuffer buf = (WaveOutBuffer)h.Target;
buf.OnCompleted();
}
catch
{
}
}
}
public WaveOutBuffer(IntPtr waveOutHandle, int size)
{
m_WaveOut = waveOutHandle;
m_HeaderHandle = GCHandle.Alloc(m_Header, GCHandleType.Pinned);
m_Header.dwUser = (IntPtr)GCHandle.Alloc(this);
m_HeaderData = new byte[size];
m_HeaderDataHandle = GCHandle.Alloc(m_HeaderData, GCHandleType.Pinned);
m_Header.lpData = m_HeaderDataHandle.AddrOfPinnedObject();
m_Header.dwBufferLength = size;
WaveOutHelper.Try(WaveNative.waveOutPrepareHeader(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header)));
}
~WaveOutBuffer()
{
Dispose();
}
public void Dispose()
{
if (m_Header.lpData != IntPtr.Zero)
{
WaveNative.waveOutUnprepareHeader(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header));
m_HeaderHandle.Free();
m_Header.lpData = IntPtr.Zero;
}
m_PlayEvent.Close();
if (m_HeaderDataHandle.IsAllocated)
m_HeaderDataHandle.Free();
GC.SuppressFinalize(this);
}
public int Size
{
get { return m_Header.dwBufferLength; }
}
public IntPtr Data
{
get { return m_Header.lpData; }
}
public bool Play()
{
lock(this)
{
m_PlayEvent.Reset();
m_Playing = WaveNative.waveOutWrite(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header)) == WaveNative.MMSYSERR_NOERROR;
return m_Playing;
}
}
public void WaitFor()
{
if (m_Playing)
{
m_Playing = m_PlayEvent.WaitOne();
}
else
{
Thread.Sleep(0);
}
}
public void OnCompleted()
{
m_PlayEvent.Set();
m_Playing = false;
}
}
public class WaveOutPlayer : IDisposable
{
private IntPtr m_WaveOut;
private WaveOutBuffer m_Buffers; // linked list
private WaveOutBuffer m_CurrentBuffer;
private Thread m_Thread;
private BufferFillEventHandler m_FillProc;
private bool m_Finished;
private byte m_zero;
private WaveNative.WaveDelegate m_BufferProc = new WaveNative.WaveDelegate(WaveOutBuffer.WaveOutProc);
public static int DeviceCount
{
get { return WaveNative.waveOutGetNumDevs(); }
}
public WaveOutPlayer(int device, WaveFormat format, int bufferSize, int bufferCount, BufferFillEventHandler fillProc)
{
m_zero = format.wBitsPerSample == 8 ? (byte)128 : (byte)0;
m_FillProc = fillProc;
WaveOutHelper.Try(WaveNative.waveOutOpen(out m_WaveOut, device, format, m_BufferProc, 0, WaveNative.CALLBACK_FUNCTION));
AllocateBuffers(bufferSize, bufferCount);
m_Thread = new Thread(new ThreadStart(ThreadProc));
m_Thread.Start();
}
~WaveOutPlayer()
{
Dispose();
}
public void Dispose()
{
if (m_Thread != null)
try
{
m_Finished = true;
if (m_WaveOut != IntPtr.Zero)
WaveNative.waveOutReset(m_WaveOut);
m_Thread.Join();
m_FillProc = null;
FreeBuffers();
if (m_WaveOut != IntPtr.Zero)
WaveNative.waveOutClose(m_WaveOut);
}
finally
{
m_Thread = null;
m_WaveOut = IntPtr.Zero;
}
GC.SuppressFinalize(this);
}
private void ThreadProc()
{
while (!m_Finished)
{
Advance();
if (m_FillProc != null && !m_Finished)
m_FillProc(m_CurrentBuffer.Data, m_CurrentBuffer.Size);
else
{
// zero out buffer
byte v = m_zero;
byte[] b = new byte[m_CurrentBuffer.Size];
for (int i = 0; i < b.Length; i++)
b[i] = v;
Marshal.Copy(b, 0, m_CurrentBuffer.Data, b.Length);
}
m_CurrentBuffer.Play();
}
WaitForAllBuffers();
}
private void AllocateBuffers(int bufferSize, int bufferCount)
{
FreeBuffers();
if (bufferCount > 0)
{
m_Buffers = new WaveOutBuffer(m_WaveOut, bufferSize);
WaveOutBuffer Prev = m_Buffers;
try
{
for (int i = 1; i < bufferCount; i++)
{
WaveOutBuffer Buf = new WaveOutBuffer(m_WaveOut, bufferSize);
Prev.NextBuffer = Buf;
Prev = Buf;
}
}
finally
{
Prev.NextBuffer = m_Buffers;
}
}
}
private void FreeBuffers()
{
m_CurrentBuffer = null;
if (m_Buffers != null)
{
WaveOutBuffer First = m_Buffers;
m_Buffers = null;
WaveOutBuffer Current = First;
do
{
WaveOutBuffer Next = Current.NextBuffer;
Current.Dispose();
Current = Next;
} while(Current != First);
}
}
private void Advance()
{
m_CurrentBuffer = m_CurrentBuffer == null ? m_Buffers : m_CurrentBuffer.NextBuffer;
m_CurrentBuffer.WaitFor();
}
private void WaitForAllBuffers()
{
WaveOutBuffer Buf = m_Buffers;
while (Buf.NextBuffer != m_Buffers)
{
Buf.WaitFor();
Buf = Buf.NextBuffer;
}
}
}
}
===============
WaveStream.cs
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// This material may not be duplicated in whole or in part, except for
// personal use, without the express written consent of the author.
//
// Email:
[email protected]
//
// Copyright (C) 1999-2003 Ianier Munoz. All Rights Reserved.
using System;
using System.IO;
namespace WaveLib
{
public class WaveStream : Stream, IDisposable
{
private Stream m_Stream;
private long m_DataPos;
private long m_Length;
private WaveFormat m_Format;
public WaveFormat Format
{
get { return m_Format; }
}
private string ReadChunk(BinaryReader reader)
{
byte[] ch = new byte[4];
reader.Read(ch, 0, ch.Length);
return System.Text.Encoding.ASCII.GetString(ch);
}
private void ReadHeader()
{
if (m_Stream == null)
throw new Exception("Null filestream.");
BinaryReader Reader = new BinaryReader(m_Stream);
if (ReadChunk(Reader) != "RIFF")
throw new Exception("Invalid file format");
Reader.ReadInt32(); // File length minus first 8 bytes of RIFF description, we don't use it
if (ReadChunk(Reader) != "WAVE")
throw new Exception("Invalid file format");
if (ReadChunk(Reader) != "fmt ")
throw new Exception("Invalid file format");
if (Reader.ReadInt32() != 16) // bad format chunk length
throw new Exception("Invalid file format");
m_Format = new WaveFormat(22050, 16, 2); // initialize to any format
m_Format.wFormatTag = Reader.ReadInt16();
m_Format.nChannels = Reader.ReadInt16();
m_Format.nSamplesPerSec = Reader.ReadInt32();
m_Format.nAvgBytesPerSec = Reader.ReadInt32();
m_Format.nBlockAlign = Reader.ReadInt16();
m_Format.wBitsPerSample = Reader.ReadInt16();
// assume the data chunk is aligned
while(m_Stream.Position < m_Stream.Length && ReadChunk(Reader) != "data")
;
if (m_Stream.Position >= m_Stream.Length)
throw new Exception("Invalid file format");
m_Length = Reader.ReadInt32();
m_DataPos = m_Stream.Position;
Position = 0;
}
public WaveStream(string fileName) : this( new FileStream(fileName,FileMode.Open) )
{
}
public WaveStream(Stream S)
{
m_Stream = S;
ReadHeader();
}
~WaveStream()
{
Dispose();
}
public void Dispose()
{
if (m_Stream != null)
m_Stream.Close();
GC.SuppressFinalize(this);
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override bool CanWrite
{
get { return false; }
}
public override long Length
{
get { return m_Length; }
}
public override long Position
{
get { return m_Stream.Position - m_DataPos; }
set { Seek(value, SeekOrigin.Begin); }
}
public override void Close()
{
Dispose();
}
public override void Flush()
{
}
public override void SetLength(long len)
{
throw new InvalidOperationException();
}
public override long Seek(long pos, SeekOrigin o)
{
switch(o)
{
case SeekOrigin.Begin:
m_Stream.Position = pos + m_DataPos;
break;
case SeekOrigin.Current:
m_Stream.Seek(pos, SeekOrigin.Current);
break;
case SeekOrigin.End:
m_Stream.Position = m_DataPos + m_Length - pos;
break;
}
return this.Position;
}
public override int Read(byte[] buf, int ofs, int count)
{
int toread = (int)Math.Min(count, m_Length - Position);
return m_Stream.Read(buf, ofs, toread);
}
public override void Write(byte[] buf, int ofs, int count)
{
throw new InvalidOperationException();
}
}
}
============
timerForm.resx
text/microsoft-resx
1.3
System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
17, 17
AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAQAMAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAACnp6ccHBwUFBSgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAADS0tLGxsbH
x8fGxsazs7MgICADAwMDAwMgICC0tLTNzc3X19fU1NTNzc0AAAAAAAAHBwcDAwcHBw0JCQ8DAwkFBQoI
CA4DAwkGBgwDAwkEBAoHBg0GBgwMDA0AAAAAAAAkJCQyMWs3N6c3N6c2Nqc3N6c3N6c3N6c3N6c3N6c3
N6c3N6gyMYIPDxIAAAAAAAB2dnYfHjw7O7M7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q7O7QqKFQ8PD0A
AAAAAAC7u7sfHyxAP5w7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q9PKUWFiuUlJQAAAAAAAAAAABSUlQr
KU47OrE7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q6OrIlJWI9PUHe3t4AAAAAAAAAAAC+vr4bGyItLXs7O7Q7O7Q7
O7Q7O7Q7O7Q7O7QnJ3MfHyetra4AAAAAAAAAAAAAAAAAAAB6enocHEM9Pa87O7Q7O7Q7O7Q7O7Q7O54e
HTCOjo4AAAAAAAAAAAAAAAAAAAAAAAC1tbUZGCQ4OJk7O7Q7O7Q7O7Q7O7QyMpAUFBkAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAUFBkxMY47O7Q7O7Q7O7Q7O7QtLYkWFhkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAXFxwxMY47O7Q7O7Q7O7Q7O7Q2NYohISUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhISU2NoY7O7Q7
O7Q7O7Q7O7Q4N3EyMjIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABtbW0kJEBAQK87O7Q7O7RBQK4iITt5
eXkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzMw7Oz8eHTc3NmM4N2UdHTU5OT3Ly8sAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAADPz897e3tAQEA+Pj59fX3Q0NAAAAAAAAAAAAAAAAAAAAD8PwAAgAEAAIAB
AACAAQAAgAEAAIABAADAAQAAwAMAAOAHAADgDwAA8A8AAPAPAADwDwAA8A8AAPAPAAD4HwAA
123, 17
TimerForm
False
AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAQAMAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAACnp6ccHBwUFBSgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAADS0tLGxsbH
x8fGxsazs7MgICADAwMDAwMgICC0tLTNzc3X19fU1NTNzc0AAAAAAAAHBwcDAwcHBw0JCQ8DAwkFBQoI
CA4DAwkGBgwDAwkEBAoHBg0GBgwMDA0AAAAAAAAkJCQyMWs3N6c3N6c2Nqc3N6c3N6c3N6c3N6c3N6c3
N6c3N6gyMYIPDxIAAAAAAAB2dnYfHjw7O7M7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q7O7QqKFQ8PD0A
AAAAAAC7u7sfHyxAP5w7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q9PKUWFiuUlJQAAAAAAAAAAABSUlQr
KU47OrE7O7Q7O7Q7O7Q7O7Q7O7Q7O7Q6OrIlJWI9PUHe3t4AAAAAAAAAAAC+vr4bGyItLXs7O7Q7O7Q7
O7Q7O7Q7O7Q7O7QnJ3MfHyetra4AAAAAAAAAAAAAAAAAAAB6enocHEM9Pa87O7Q7O7Q7O7Q7O7Q7O54e
HTCOjo4AAAAAAAAAAAAAAAAAAAAAAAC1tbUZGCQ4OJk7O7Q7O7Q7O7Q7O7QyMpAUFBkAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAUFBkxMY47O7Q7O7Q7O7Q7O7QtLYkWFhkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAXFxwxMY47O7Q7O7Q7O7Q7O7Q2NYohISUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhISU2NoY7O7Q7
O7Q7O7Q7O7Q4N3EyMjIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABtbW0kJEBAQK87O7Q7O7RBQK4iITt5
eXkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzMw7Oz8eHTc3NmM4N2UdHTU5OT3Ly8sAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAADPz897e3tAQEA+Pj59fX3Q0NAAAAAAAAAAAAAAAAAAAAD8PwAAgAEAAIAB
AACAAQAAgAEAAIABAADAAQAAwAMAAOAHAADgDwAA8A8AAPAPAADwDwAA8A8AAPAPAAD4HwAA