Click here to Skip to main content
15,888,461 members
Articles / Desktop Programming / Windows Forms

Personal Schedule Management Tool

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
24 Apr 2011CPOL1 min read 17.2K   23   4
Personal Schedule Management Tool

Time is always ticking no matter whether you care about it or not, everyone knows it including myself. To remind myself not to waste too much time on gaming, reading news or something else, I developed a little tool which I call it "Personal Schedule Management Tool" to achieve this simple goal.

Mechanism

I create an XML file to store a serial of [time stamp/task to do] pairs, the tool will start with Windows and load the XML file, a working timer behind it will periodically check whether there is a task that needs to be done at a defined time stamp. Once the condition is matched, the tool will:

  1. Shows Windows Balloon Tips with the task as content, see screenshot below:

    Balloon

  2. Invokes managed Microsoft Speech API: SpeechSynthesizer.Speak() to remind me even if I am not in front of my dev-box at that time.

Here is my XML to store schedule items:

XML
<?xml version="1.0" encoding="utf-8" ?>
<WayneScheduleItems>
  <ScheduleItem TriggerHour="18" TriggerMinute="20" 
  Content="Wayne, time to have your dinner." />
  <ScheduleItem TriggerHour="19" TriggerMinute="0" 
  Content="Wayne! It is time to learn technologies 
  and programming skills, i.e. CODING TIME!" />
  <ScheduleItem TriggerHour="20" TriggerMinute="30" 
  Content="OK, your eye and brain need rest, time to do some 
  body exercise - running, sit-ups, push-up, etc.  Enjoy:)" />
  <ScheduleItem TriggerHour="21" TriggerMinute="0" 
  Content="Well, sweat off your face and have a bath:)." />
  <ScheduleItem TriggerHour="21" TriggerMinute="30" 
  Content="All right, well come back, you know you should read some books!" />
  <ScheduleItem TriggerHour="23" TriggerMinute="0" 
  Content="Wayne, thanks for the hard work! Time to sleep, have a good night!" />
</WayneScheduleItems>

UI Implementation

The tool is a WinForm developed in C#, it has no Windows and starts in system tray. To achieve this, I set MainWindow’s FormBorderStyle = None, ShowIcon = False and ShowInTaskBar = False, see below.

WindowProperty

One more thing is drag two controls onto the form: System.Windows.Forms.NotifyIcon, System.Windows.Forms.ContextMenuStrip and name the instances as "systrayIcon" and "systrayMenu".

Controls

After that, I need to add menu items. Please see code snippet below:

C#
this.editScheduleItemsToolStripMenuItem.Name = "editScheduleItemsToolStripMenuItem";
this.editScheduleItemsToolStripMenuItem.Text = "Edit Schedule Items";
this.editScheduleItemsToolStripMenuItem.Click += 
   new System.EventHandler(this.editScheduleItemsToolStripMenuItem_Click);
this.systrayMenu.Items.Add(editScheduleItemsToolStripMenuItem);

All right, its appearance is like below:

SystrayMenu

Functionality Implementation

Timer

C#
// Initializes timer
    scheduleTimer = new System.Timers.Timer()
                    {
                        Interval = 1000d * 60 * 10, // 10 minutes
                        Enabled = true
                    };
    this.scheduleTimer.Start();
    this.scheduleTimer.Elapsed += new System.Timers.ElapsedEventHandler(scheduleTimer_Elapsed);

void scheduleTimer_Elapsed(object sender, ElapsedEventArgs e)
{
    DateTime currentTime = e.SignalTime;

    try
    {
        foreach (ScheduleItem scheduleItem in scheduleItems)
        {
            if (currentTime.Hour == scheduleItem.TriggerHour
            && currentTime.Minute == scheduleItem.TriggerMinute)
            {
                LogManager.WriteAsync(String.Format("{0}, notification occurred: {1}.{2}",
                    currentTime.ToLocalTime(), scheduleItem.Content, Environment.NewLine));

                // Trigger bubble/voice notification
                this.systrayIcon.ShowBalloonTip
                     (8000, Constants.BalloonTitle, scheduleItem.Content, ToolTipIcon.Info);
                SoundNotifier.Phonate(scheduleItem.Content);

                break; // Avoid redundant check
            }
        }
    }
    catch (Exception ex)
    {
        LogManager.WriteAsync(ex.Message);
    }

    LogManager.WriteAsync(String.Format("Schedule check at: {0}{1}", 
                          currentTime.ToLocalTime(), Environment.NewLine));
}

Load Schedule Items from XML using LINQ

C#
public static class ScheduleItemsReader
{
    private static readonly String ScheduleItemsXmlLocation = 
         Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ScheduleItems.xml");

    public static IEnumerable<ScheduleItem> Load()
    {
        IList<ScheduleItem> scheduleItems = new List<ScheduleItem>();

        IEnumerable<XElement> scheduleItemsCollection = 
          from scheduleItem in XElement.Load(ScheduleItemsXmlLocation).Descendants("ScheduleItem")
                                                        select scheduleItem;

        foreach (XElement ele in scheduleItemsCollection)
        {
            ScheduleItem scheduleItem = new ScheduleItem();
            scheduleItem.TriggerHour = ushort.Parse(ele.Attribute("TriggerHour").Value);
            scheduleItem.TriggerMinute = ushort.Parse(ele.Attribute("TriggerMinute").Value);
            scheduleItem.Content = ele.Attribute("Content").Value;

            scheduleItems.Add(scheduleItem);
        }

        return scheduleItems;
    }
}

Invoke Speech API

C#
public static class SoundNotifier
{
    public static void Phonate(String sentence)
    {
        using (SpeechSynthesizer speaker = 
          new SpeechSynthesizer())  // Dispose the its instance as soon as it spoke fnished
        {
            ReadOnlyCollection<InstalledVoice> installedVoices = speaker.GetInstalledVoices();

            CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-US");

            PromptBuilder pb = new PromptBuilder();
            pb.StartVoice(VoiceGender.Female, VoiceAge.Adult);
            pb.StartStyle(new PromptStyle(PromptVolume.Loud));

            pb.StartSentence();
            pb.AppendText(sentence, PromptEmphasis.Strong);
            pb.EndSentence();

            pb.EndStyle();
            pb.EndVoice();

            speaker.Speak(pb);
        }
    }
}

LogManager

C#
public static void WriteAsync(String content)
{
    FileStream fileStream = null;

    LogFilePath = String.Format(LogFilePath, DateTime.Now.ToString("MM-dd-yyyy"));
    if (File.Exists(LogFilePath))
        fileStream = File.OpenWrite(LogFilePath);
    else
        fileStream = File.Create(LogFilePath);
    FileInfo logFile = new FileInfo(LogFilePath);

    StringBuilder logBuilder = new StringBuilder();
    logBuilder.AppendFormat(
        "================================================================================={0}{1}{0}{0}",
        Environment.NewLine,
        content);

    byte[] data = Encoding.UTF8.GetBytes(logBuilder.ToString());
    fileStream.Position = logFile.Length; // Move to the end of the existing text file

    fileStream.BeginWrite(data, 0, data.Length, new AsyncCallback(r =>
    {
        AsyncState asyncState = r.AsyncState as AsyncState;

        asyncState.FStream.EndWrite(r);
        asyncState.FStream.Close();
    }), new AsyncState(fileStream, data, m_ManualResetEvent));

    m_ManualResetEvent.WaitOne(100, false);
}

You can download the source code here.

This article was originally posted at http://wayneye.com/Blog/Personal-Schedule-Management-Tool

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) SAP Labs Shanghai
China China
Wayne is a software developer, Tech Lead and also a geek. He has more than 6 years' experience in Web development(server: ASP.NET (MVC), Web Service, IIS; Client: HTML/CSS/JavaScript/jQuery/AJAX), Windows development (Winform, Windows Service, WPF/Silverlight, Win32 API and WMI) and SQL Server. Deep understanding of GOF Design Patterns, S.O.L.i.D principle, MVC, MVVM, Domain Driven Design, SOA, REST and AOP.

Wayne's Geek Life http://WayneYe.com

Infinite passion on programming!

Comments and Discussions

 
QuestionSource Code link not working Pin
Tim8w15-Dec-23 7:36
Tim8w15-Dec-23 7:36 
GeneralMy vote of 5 Pin
Mark Vinod Sinnathamby25-Apr-11 20:14
professionalMark Vinod Sinnathamby25-Apr-11 20:14 
Great little tool for our busy schedules. As i use a computer everyday, the schedules will popup right where i can see them anytime of the day.
GeneralVery interesting. Pin
Hezek1ah25-Apr-11 13:08
Hezek1ah25-Apr-11 13:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.