A C# application written entirely in Notepad

In this blog post I am going to present a C# application that I wrote. This application is pretty basic, but it is also a breakthrough. I will explain why it is a breakthrough in due course. But, believe me, before this blog post is over, you will have understood the breakthrough that I made.

Ok, let’s take things from the beginning. I have always wanted to write applications using nothing but Notepad. My favorite development environment is Notepad. This may sound like a joke to most people, especially because Visual Studio is so advanced.

But I do not want to use Visual Studio. It is not because I do not like it; I like it. It is is because I want to program using nothing but Notepad. And I insist to have to right to write programs using nothing but Notepad. This is the only way I want to write programs.

I have blogged before about the talk in CNN in which they presented the dangers of HIV to a group of men and explained the importance of using protection during sex. In this talk, a gentleman said: “we feel we are not functioning as men if there is something in between”. Of course, protection during sex is paramount, but I want to rephrase the gentleman’s statement. I say: “I feel I am not functioning as a programmer if there is something in between.”

Visual Studio is in between. And I prefer to program without it. People have long complained that programming is not what was used to be. For me, if I can write programs using just Notepad, is a great first step to bring beauty and excitement back to programming. For others, this beauty and excitement is brought by Visual Studio. As they code, all sorts of contextual help like syntax, failure of unit tests, code whereabouts and so on make Visual Studio incredibly helpful. The paradigm shift from Notepad to Visual Studio is overwhelming. Visual Studio is incredible. Still, I want to program using nothing but Notepad. Why? I already answered: I feel I am not functioning as a programmer if there is something in between.

Someone might argue that it does not matter what editor one uses, be it Notepad or the bult-in Visual Studio editor, even though the latter is way more powerful. But what I particularly do not like are prebuilt files that you have to add your code along with the prebuilt code. This technique, which I dislike, is made possible with Visual Studio. Visual Studio offers prebuilt templates that are comprised of many files which already contain code. And you are expected to input your own code into these (already filled with code) files. I dislike this approach. If I can have my way, I want to create each and every file myself and write the code each file has from scratch. And the least amount of files my solution has, the better.

I wrote that my favorite development environment is Notepad. Well, I could go as far as say that my favorite development environment is a binary editor, in which I create byte-by-byte the PE file of the executable I want to produce.

Ok, now that I have cleared those matters, I want to say that I have always wanted to write a C# application that lived in the system tray. Again, of course, write it using nothing but Notepad. Also, I wanted this application to be just an icon in the system tray; if it would exhibit any windows or not, that should be an afterthought. The main application should function without the need of any windows whatsoever.

These types of applications are very useful. They sit in the system tray, minding their own business and do not annoy the user, until, of course, there is a valid reason to annoy the user. They are like a companion, sitting along, waiting and watching for a chance to prove useful to the user.

Ok, let me take a short break from speaking about me and let me tell you about a friend of mine. My friend always wanted an application that would remind him of stuff. He wanted to have the application to remind him to do something at some point in time. When that point in time would arrive, the application would remind him of that thing. Then, he could just dismiss the reminder, or reschedule the reminder for a point in time in the future.

Simple enough, huh? Calendars do it, but my friend wanted an application that did exactly this thing and not anything else. My friend did not want a calendar. I should think that there are many applications that do that sort of thing, but we did not find any that matched exactly what my friend wanted. Actually, we found one, at some point, but it only allowed us to specify the time of the reminder, not the date. It was like an alarm clock. But my friend wanted to specify reminders for any day and time in the future.

So, I decided to write my own “Reminders” application, which I called “Reminders”. No surprise here.

As I promised earlier, I wrote the application in Notepad. The language I used was C# and .NET framework 2.0. The application lives in the system tray. It begins by displaying its icon in the system tray and notifies the user if and when a reminder is due.

About the icon: I cheated here. I created the icon using IcoFX, which is a great icon editor. But other than that, I created the rest of the application in Notepad.

This is how I worked: I first created a folder somewhere. In this folder I created a text file named Reminders.cs with all the code. In this folder I also put the icon I created, Reminders.ico. In this folder I also created a batch file in order to compile the application into the executable Reminders.exe. The batch file is the following:

del Reminders.exe

%systemroot%\Microsoft.NET\Framework\v2.0.50727\csc /target:winexe /win32icon:Reminders.ico Reminders.cs

pause

This batch file produces Reminders.exe, which is the only file we need to deploy the application. You can copy Reminders.exe to your system and run it once. That’s it. If you want  it to run after each log on, put it or a shortcut of it in your start up folder.

So, there are two ways to deploy Reminders.exe. If you are in a hurry, just copy Reminders.exe to your start up folder. Then you can optionally run it, or it will run after the next logon. The most professional way to deploy Reminders.exe is to create a folder in your Program Files named “Reminders” and put the Reminders.exe in this folder. Then create a shortcut to this exe in your start up folder. Then you can optionally run it, or it will run after the next log on.

As an application, Reminders is hopelessly minimal. Minimal here being a euphemish for incomplete. There is a form that displays all reminders, but there is no toolbar on even a menu with a command to add and delete reminders. Well, while this form is displayed, you can press the Insert key to insert a new reminder and press the Delete key to delete the selected reminder, but good luck discovering that on your own. This is against all Microsoft best practices. Certainly, this application needs improvment. It is, as I just wrote, minimal 🙂 Nevertheless, a user that is not very fussy can go a long way using this application.

Below, I exhibit the whole of the code. It exists in the file Reminders.cs.

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using System.Reflection;

[assembly: AssemblyTitle("Reminders application")]
[assembly: AssemblyDescription("Reminders application")]
[assembly: AssemblyConfiguration("Private")]
[assembly: AssemblyCompany("Dimitrios Kalemis")]
[assembly: AssemblyProduct("Reminders application")]
[assembly: AssemblyCopyright("Dimitrios Kalemis 2013")]
[assembly: AssemblyVersion("1.0.0.0")]

class Reminders
{
   static Mutex myMutex;
   static bool exitFlag;
   static string myDirectory;
   static string myFile;
   static NotifyIcon notifyIcon;

   public class ShowRemindersForm: Form
   {

      private ListBox myListBox;

      public ShowRemindersForm()
      {
         Text = "Show Reminders";
         ClientSize = new Size(300, 300);
         FormBorderStyle = FormBorderStyle.FixedDialog;
         MaximizeBox = false;
         StartPosition = FormStartPosition.CenterScreen;

         myListBox = new ListBox();
         myListBox.Location = new Point(10, 10);
         myListBox.Size = new Size(280,280);
         myListBox.HorizontalScrollbar = true;
         myListBox.KeyUp += new KeyEventHandler(myListBox_KeyUp);

         try
         {
            using (StreamReader infile = new StreamReader(myFile))
            {
               string myInputString = "";
               while ((myInputString = infile.ReadLine()) != null)
               {
                  myListBox.Items.Add(myInputString);
               }
            }
         }
         catch (Exception exep)
         {
            MessageBox.Show(exep.Message);
         }

         Controls.Add(myListBox);
      }

      public void myRefresh()
      {
         myListBox.Items.Clear();

         try
         {
            using (StreamReader infile = new StreamReader(myFile))
            {
               string myInputString = "";
               while ((myInputString = infile.ReadLine()) != null)
               {
                  myListBox.Items.Add(myInputString);
               }
            }
         }
         catch (Exception exep)
         {
            MessageBox.Show(exep.Message);
         }
      }

      private void myListBox_KeyUp(object sender, KeyEventArgs e)
      {
         if (e.KeyCode == Keys.Insert)
         {
            HandlerForAddReminder();
         }
         else if (e.KeyCode == Keys.Delete)
         {
            int mySelectedIndex = myListBox.SelectedIndex;

            if (mySelectedIndex >= 0)
            {
               string mySelectedItem = myListBox.SelectedItem.ToString();

               if (MessageBox.Show("Are you sure you want to delete the " + mySelectedItem + " reminder?", "Delete question", MessageBoxButtons.YesNo) == DialogResult.Yes)
               {
                  try
                  {
                     List oldLines = new List();
                     List newLines = new List();
                     int myLineCounter = 0;
                     bool proceed = false;

                     using (StreamReader infile = new StreamReader(myFile))
                     {
                        string myInputString = "";
                        while ((myInputString = infile.ReadLine()) != null)
                        {
                           oldLines.Add(myInputString);
                        }
                     }

                     foreach (string myLine in oldLines)
                     {
                         if (myLineCounter == mySelectedIndex)
                         {
                            if (myLine == mySelectedItem)
                            {
                               proceed = true;
                            }
                            else
                            {
                               break;
                            }
                         }
                         else
                         {
                            newLines.Add(myLine);
                         }

                         myLineCounter = myLineCounter + 1;
                     }

                     if (proceed)
                     {
                        using (StreamWriter outfile = new StreamWriter(myFile))
                        {
                           foreach (string myLine in newLines)
                           {
                             outfile.WriteLine(myLine);
                           }
                        }

                        myListBox.Items.RemoveAt(mySelectedIndex);
                     }
                     else
                     {
                        MessageBox.Show("The reminder was not deleted because the data file was changed during this operation by another operation. Please try again.");
                     }
                  }
                  catch (Exception exep)
                  {
                     MessageBox.Show("The reminder was not deleted because of the following error:\n\n" + exep.Message + "\n\n" + "Please try again.");
                  }
               }
            }
         }
      }
   }

   public class AddReminderForm: Form
   {

      private MonthCalendar myMonthCalendar;
      private Label myLabelHour;
      private Label myLabelMinute;
      private ComboBox myComboBoxHour;
      private ComboBox myComboBoxMinute;
      private Label myLabelTextBox;

      public TextBox myTextBox;

      private Button myButtonOK;
      private Button myButtonCancel;

      public AddReminderForm()
      {
         Text = "Add Reminder";
         ClientSize = new Size(260, 360);
         FormBorderStyle = FormBorderStyle.FixedDialog;
         MaximizeBox = false;
         StartPosition = FormStartPosition.CenterScreen;

         myMonthCalendar = new MonthCalendar();
         myMonthCalendar.Location = new Point(12,10);
         myMonthCalendar.ShowToday = false;
         myMonthCalendar.ShowTodayCircle = false;
         myMonthCalendar.MaxSelectionCount = 1;

         myLabelHour = new Label();
         myLabelHour.Location = new Point(70, 180);
         myLabelHour.Size = new Size(50,20);
         myLabelHour.Text = "Hour";

         myLabelMinute = new Label();
         myLabelMinute.Location = new Point(150, 180);
         myLabelMinute.Size = new Size(50,20);
         myLabelMinute.Text = "Minute";

         myComboBoxHour = new ComboBox();
         myComboBoxHour.Location = new Point(70,200);
         myComboBoxHour.Size = new Size(40,10);
         myComboBoxHour.DropDownStyle = ComboBoxStyle.DropDownList;
         myComboBoxHour.Items.Add("00");
         myComboBoxHour.Items.Add("01");
         myComboBoxHour.Items.Add("02");
         myComboBoxHour.Items.Add("03");
         myComboBoxHour.Items.Add("04");
         myComboBoxHour.Items.Add("05");
         myComboBoxHour.Items.Add("06");
         myComboBoxHour.Items.Add("07");
         myComboBoxHour.Items.Add("08");
         myComboBoxHour.Items.Add("09");
         myComboBoxHour.Items.Add("10");
         myComboBoxHour.Items.Add("11");
         myComboBoxHour.Items.Add("12");
         myComboBoxHour.Items.Add("13");
         myComboBoxHour.Items.Add("14");
         myComboBoxHour.Items.Add("15");
         myComboBoxHour.Items.Add("16");
         myComboBoxHour.Items.Add("17");
         myComboBoxHour.Items.Add("18");
         myComboBoxHour.Items.Add("19");
         myComboBoxHour.Items.Add("20");
         myComboBoxHour.Items.Add("21");
         myComboBoxHour.Items.Add("22");
         myComboBoxHour.Items.Add("23");

         myComboBoxMinute = new ComboBox();
         myComboBoxMinute.Location = new Point(150,200);
         myComboBoxMinute.Size = new Size(40,10);
         myComboBoxMinute.DropDownStyle = ComboBoxStyle.DropDownList;
         myComboBoxMinute.Items.Add("00");
         myComboBoxMinute.Items.Add("01");
         myComboBoxMinute.Items.Add("02");
         myComboBoxMinute.Items.Add("03");
         myComboBoxMinute.Items.Add("04");
         myComboBoxMinute.Items.Add("05");
         myComboBoxMinute.Items.Add("06");
         myComboBoxMinute.Items.Add("07");
         myComboBoxMinute.Items.Add("08");
         myComboBoxMinute.Items.Add("09");
         myComboBoxMinute.Items.Add("10");
         myComboBoxMinute.Items.Add("11");
         myComboBoxMinute.Items.Add("12");
         myComboBoxMinute.Items.Add("13");
         myComboBoxMinute.Items.Add("14");
         myComboBoxMinute.Items.Add("15");
         myComboBoxMinute.Items.Add("16");
         myComboBoxMinute.Items.Add("17");
         myComboBoxMinute.Items.Add("18");
         myComboBoxMinute.Items.Add("19");
         myComboBoxMinute.Items.Add("20");
         myComboBoxMinute.Items.Add("21");
         myComboBoxMinute.Items.Add("22");
         myComboBoxMinute.Items.Add("23");
         myComboBoxMinute.Items.Add("24");
         myComboBoxMinute.Items.Add("25");
         myComboBoxMinute.Items.Add("26");
         myComboBoxMinute.Items.Add("27");
         myComboBoxMinute.Items.Add("28");
         myComboBoxMinute.Items.Add("29");
         myComboBoxMinute.Items.Add("30");
         myComboBoxMinute.Items.Add("31");
         myComboBoxMinute.Items.Add("32");
         myComboBoxMinute.Items.Add("33");
         myComboBoxMinute.Items.Add("34");
         myComboBoxMinute.Items.Add("35");
         myComboBoxMinute.Items.Add("36");
         myComboBoxMinute.Items.Add("37");
         myComboBoxMinute.Items.Add("38");
         myComboBoxMinute.Items.Add("39");
         myComboBoxMinute.Items.Add("40");
         myComboBoxMinute.Items.Add("41");
         myComboBoxMinute.Items.Add("42");
         myComboBoxMinute.Items.Add("43");
         myComboBoxMinute.Items.Add("44");
         myComboBoxMinute.Items.Add("45");
         myComboBoxMinute.Items.Add("46");
         myComboBoxMinute.Items.Add("47");
         myComboBoxMinute.Items.Add("48");
         myComboBoxMinute.Items.Add("49");
         myComboBoxMinute.Items.Add("50");
         myComboBoxMinute.Items.Add("51");
         myComboBoxMinute.Items.Add("52");
         myComboBoxMinute.Items.Add("53");
         myComboBoxMinute.Items.Add("54");
         myComboBoxMinute.Items.Add("55");
         myComboBoxMinute.Items.Add("56");
         myComboBoxMinute.Items.Add("57");
         myComboBoxMinute.Items.Add("58");
         myComboBoxMinute.Items.Add("59");

         myLabelTextBox = new Label();
         myLabelTextBox.Location = new Point(10, 240);
         myLabelTextBox.Size = new Size(230,20);
         myLabelTextBox.Text = "Write here what you want to be reminded of";

         myTextBox = new TextBox();
         myTextBox.Location = new Point(10,260);
         myTextBox.Size = new Size(240,20);

         myButtonOK = new Button();
         myButtonOK.Location = new Point(10, 300);
         myButtonOK.Size = new Size(100, 40);
         myButtonOK.Text = "Add reminder";
         myButtonOK.Click += new EventHandler(myButtonOK_Click);

         myButtonCancel = new Button();
         myButtonCancel.Location = new Point(150, 300);
         myButtonCancel.Size = new Size(100, 40);
         myButtonCancel.Text = "Cancel form";
         myButtonCancel.Click += new EventHandler(myButtonCancel_Click);

         Controls.Add(myMonthCalendar);
         Controls.Add(myLabelHour);
         Controls.Add(myLabelMinute);
         Controls.Add(myComboBoxHour);
         Controls.Add(myComboBoxMinute);
         Controls.Add(myLabelTextBox);
         Controls.Add(myTextBox);
         Controls.Add(myButtonOK);
         Controls.Add(myButtonCancel);
      }

      private void myButtonOK_Click(object sender, EventArgs e)
      {

         if (myComboBoxHour.Text == "")
         {
            MessageBox.Show("Please specify an hour.");
            return;
         }

         if (myComboBoxMinute.Text == "")
         {
            MessageBox.Show("Please specify a minute.");
            return;
         }

         if (myTextBox.Text == "")
         {
            MessageBox.Show("Please specify what you want to be reminded of,\nby entering some text in the textbox.");
            return;
         }

         DateTime myDate;
         string myYear;
         string myMonth;
         string myDay;
         string myReminderString;

         myDate = myMonthCalendar.SelectionRange.Start;

         myYear = myDate.Year.ToString();
         if (myYear.Length != 4)
         {
            MessageBox.Show("Please specify a valid year.\nValid years have 4 numbers.");
            return;
         }

         myMonth = myDate.Month.ToString();
         if (myMonth.Length == 1)
         {
            myMonth = "0" + myMonth;
         }

         myDay = myDate.Day.ToString();
         if (myDay.Length == 1)
         {
            myDay = "0" + myDay;
         }

         myReminderString = myYear + "-" + myMonth + "-" + myDay + " " + myComboBoxHour.Text + ":" + myComboBoxMinute.Text + " " + myTextBox.Text;

         try
         {
            using (StreamWriter outfile = File.AppendText(myFile))
            {
               outfile.WriteLine(myReminderString);

               MessageBox.Show("The following reminder was added:\n\n" + myReminderString);
            }
         }
         catch (Exception exep)
         {
            MessageBox.Show("The reminder was not entered because of the following error:\n\n" + exep.Message);
         }

         foreach (Form myOpenForm in Application.OpenForms)
         {
            if (myOpenForm.Text == "Show Reminders")
            {
               ((ShowRemindersForm)myOpenForm).myRefresh();
            }
         }

         Close();
      }

      private void myButtonCancel_Click(object sender, EventArgs e)
      {
         Close();
      }
   }

   public class ReminderForm: Form
   {
      private string myReminder;
      private Label myLabelInfo;
      private Label myLabelTextBox;
      private TextBox myTextBox;
      private Button myButtonOK;
      private Button myButtonCancel;

      public ReminderForm(string myReminderParameter)
      {
         Text = "Reminder";
         ClientSize = new Size(260, 360);
         StartPosition = FormStartPosition.WindowsDefaultLocation;
         FormBorderStyle = FormBorderStyle.FixedDialog;
         MaximizeBox = false;

         myReminder = myReminderParameter;
         string myFirstPartOfReminder = myReminder.Substring(0,16);
         string mySecondPartOfReminder = myReminder.Substring(17);

         myLabelInfo = new Label();
         myLabelInfo.Location = new Point(10, 10);
         myLabelInfo.Size = new Size(220, 220);
         myLabelInfo.Text = "\n\n\nAttention, please!\n\n\nThis is a reminder.\n\n\nIts date and time is:\n\n\n" + myFirstPartOfReminder + ".";

         myLabelTextBox = new Label();
         myLabelTextBox.Location = new Point(10, 240);
         myLabelTextBox.Size = new Size(230,20);
         myLabelTextBox.Text = "The text you asked to be reminded of";

         myTextBox = new TextBox();
         myTextBox.Location = new Point(10,260);
         myTextBox.Size = new Size(240,20);
         myTextBox.Text = mySecondPartOfReminder;
         myTextBox.SelectionStart = 0;
         myTextBox.ReadOnly = true;

         myButtonOK = new Button();
         myButtonOK.Location = new Point(10, 300);
         myButtonOK.Size = new Size(100, 40);
         myButtonOK.Text = "Reschedule";
         myButtonOK.Click += new EventHandler(myButtonOK_Click);

         myButtonCancel = new Button();
         myButtonCancel.Location = new Point(150, 300);
         myButtonCancel.Size = new Size(100, 40);
         myButtonCancel.Text = "Discard";
         myButtonCancel.Click += new EventHandler(myButtonCancel_Click);

         Controls.Add(myLabelInfo);
         Controls.Add(myLabelTextBox);
         Controls.Add(myTextBox);
         Controls.Add(myButtonOK);
         Controls.Add(myButtonCancel);
      }

      private void myButtonOK_Click(object sender, EventArgs e)
      {

         AddReminderForm aForm = new AddReminderForm();
         aForm.myTextBox.Text = myTextBox.Text;
         aForm.Show();
         aForm.Activate();

         Close();
      }

      private void myButtonCancel_Click(object sender, EventArgs e)
      {
         Close();
      }
   }

   [STAThread]
   public static void Main()
   {
      bool firstInstance;

      myMutex = new Mutex(false, @"Local\RemindersMutex", out firstInstance);
      // If firstInstance is now true, we're the first instance of the application;
      // otherwise another instance is running.
      if (!firstInstance)
      {
         return;
      }

      exitFlag = false;

      myDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).ToString() + @"\" +"Reminders";
      myFile = myDirectory + @"\" + "Reminders.txt";

      if (!Directory.Exists(myDirectory))
      {
         Directory.CreateDirectory(myDirectory);
      }

      if (!File.Exists(myFile))
      {
         File.Create(myFile).Dispose();
      }

      ContextMenu notifyMenu;

      notifyMenu = new ContextMenu();
      notifyMenu.MenuItems.Add("Show Remiders", OnShowReminders);
      notifyMenu.MenuItems.Add("Add Reminder", OnAddReminder);
      notifyMenu.MenuItems.Add("Exit", OnExit);

      notifyIcon = new NotifyIcon();
      notifyIcon.Icon = System.Drawing.Icon.ExtractAssociatedIcon(System.Reflection.Assembly.GetExecutingAssembly().Location);
      notifyIcon.Text = "Reminders";
      notifyIcon.ContextMenu = notifyMenu;
      notifyIcon.MouseDoubleClick += new MouseEventHandler(OnMouseDoubleClick);
      notifyIcon.Visible = true;

      while (true)
      {
         Thread.Sleep(50);
         Application.DoEvents();
         CheckForCurrentReminders();
         if (exitFlag)
         {
            break;
         }
      }
   }

   private static void OnShowReminders(object sender, EventArgs e)
   {
      HandlerForShowReminders();
   }

   private static void OnAddReminder(object sender, EventArgs e)
   {
      HandlerForAddReminder();
   }

   private static void OnExit(object sender, EventArgs e)
   {
      if (MessageBox.Show("If you close the Reminders application,\nyou will not be notified about any future reminders\nyou might have set up.\n\n\nAre you sure you want to close the Reminders application?", "Exit question", MessageBoxButtons.YesNo) == DialogResult.Yes)
      {
         exitFlag = true;
         notifyIcon.Dispose();
      }
   }

   private static void OnMouseDoubleClick(object sender, EventArgs e)
   {
      HandlerForShowReminders();
   }

   private static void HandlerForShowReminders()
   {
      bool itExists;

      itExists = false;

      foreach (Form myOpenForm in Application.OpenForms)
      {
         if (myOpenForm.Text == "Show Reminders")
         {
            itExists = true;
         }
      }

      if (!itExists)
      {
         ShowRemindersForm aForm = new ShowRemindersForm();
         aForm.Show();
         aForm.Activate();
      }
   }

   private static void HandlerForAddReminder()
   {
      bool itExists;

      itExists = false;

      foreach (Form myOpenForm in Application.OpenForms)
      {
         if (myOpenForm.Text == "Add Reminder")
         {
            itExists = true;
         }
      }

      if (!itExists)
      {
         AddReminderForm aForm = new AddReminderForm();
         aForm.Show();
         aForm.Activate();
      }
   }

   private static void CheckForCurrentReminders()
   {

      bool success = true;

      List myLines = new List();

      try
      {
         using (StreamReader infile = new StreamReader(myFile))
         {
            string myInputString = "";
            while ((myInputString = infile.ReadLine()) != null)
            {
               myLines.Add(myInputString);
            }
         }
      }
      catch (Exception exep)
      {
         MessageBox.Show(exep.Message);
         success = false;
      }

      if (success)
      {
         DateTime myDateTime = DateTime.Now;
         string myYear;
         string myMonth;
         string myDay;
         string myHour;
         string myMinute;
         string myDateTimeString;
         string myReminderDateTime;
         int resultOfStringCompare;
         List newLines = new List();
         bool haschanged = false;

         myYear = myDateTime.Year.ToString();

         myMonth = myDateTime.Month.ToString();
         if (myMonth.Length == 1)
         {
            myMonth = "0" + myMonth;
         }

         myDay = myDateTime.Day.ToString();
         if (myDay.Length == 1)
         {
            myDay = "0" + myDay;
         }

         myHour = myDateTime.Hour.ToString();
         if (myHour.Length == 1)
         {
            myHour = "0" + myHour;
         }

         myMinute = myDateTime.Minute.ToString();
         if (myMinute.Length == 1)
         {
            myMinute = "0" + myMinute;
         }

         myDateTimeString = myYear + "-" + myMonth + "-" + myDay + " " + myHour + ":" + myMinute;

         foreach (string myLine in myLines)
         {
            myReminderDateTime = myLine.Substring(0,16);
            resultOfStringCompare = myReminderDateTime.CompareTo(myDateTimeString);
            if (resultOfStringCompare <= 0)
            {
               haschanged = true;
               ReminderForm aForm = new ReminderForm(myLine);
               aForm.Show();
               aForm.Activate();
            }
            else
            {
               newLines.Add(myLine);
            }
         }

         if (haschanged)
         {
            try
            {
               using (StreamWriter outfile = new StreamWriter(myFile))
               {
                  foreach (string myLine in newLines)
                  {
                     outfile.WriteLine(myLine);
                  }
               }
            }
            catch (Exception exep)
            {
               MessageBox.Show(exep.Message);
            }

            foreach (Form myOpenForm in Application.OpenForms)
            {
               if (myOpenForm.Text == "Show Reminders")
               {
                  ((ShowRemindersForm)myOpenForm).myRefresh();
               }
            }

         }
      }
   }

}

I may have exhibited the whole of the code and the batch file that compiles it, but I have not yet given you the icon file named Reminders.ico. I am not sure how to go about in order to give you an ico file via WordPress.com, so I will do something better. I will provide you with a zip file that contains the ico, the cs file, the batch file as well as the executable that is produced. The link to the all encompassing zip file is here: Reminders Version 1.0.0.0.zip. It contains all four files.

Ok, you have the whole code, but how do you go on about reading it? Well, you should start from “public static void Main() “. Before that code, there is the code for three windows forms: ShowRemindersForm, AddReminderForm and ReminderForm.

Now that you have the C# code from the Reminders.cs file presented to you, I can explain the breakthrough that I made with this application. The code contains an all-encompassing class named “Reminders”. This class contains some static declarations, the static Main() method, three classes for windows forms, event handlers for the  system tray icon and some helper functions.

But no class is instantiated. The code starts from Main() which is static and Main() instatiates a ContextMenu and a NotifyIcon, but in no place in Main() are any classes instatiated.

This is a breakthrough. In all examples of applications that are provided from Microsoft and others, inside Main() there is instatiation of the encompassing class. For example, in our case, the Reminders class would have be instatiated. But I instatiate nothing. This is why the declarations in the beginning of the Reminders class are all static. They have to be. Since there is never any instatiation of the Reminders class, we can have only static memebrs. But this is not a problem. Instead, to have no instatiation is not only desirable, it is a breakthrough. I have never seen this kind of coding before.

Of course, when windows forms are needed , they are instatiated and used. When I write that no instatiation is used, I refer to the class Reminders. All other examples for Microsoft and others have to have a windows form class instatiated in order to use its messsage loop, etc.

What I like best about this application is that no instatiation of windows forms is needed. No windows forms are needed. Well, they are needed if they are goimg to be displayed, but they are not vital for the program to run. In all other examples from Microsoft and others, you first have to start from a windows form, instatiate it and then continue. This program does not function this way. It creates a ContextMenu and a NotifyIcon and ties this menu to the icon. From then on, the program runs without needing any windows forms. Forms are added later by me, as an afterthought, as funcionality is needed. Windows forms are an afterthough and not vital structural part of the application. The application happily runs in the system tray without instatiating any windows form.

Let me be honest. If someone else have provided such an application, made entirely with Notepad, in a single text file, using no instatiation, compiled with a single command, producing a single all encompassing executable easily distributable, living in the system tray and with no real structural need for windows forms, then I would have made this person my God. It just so happens that I am the one that provided this application, so now I consider myself to be my own God. I constantly pat myslef in the back for my accomplishment.

Ok, but what about my friend? Did he like the application. Well, for various reasons, he did not like it so much. He would like it to be more advanced; he wanted more features, like the ability to change a reminder. As the application is now, you can only delete a reminder and insert a new one. You cannot update a reminder. My friend wanted that. Also, now my friend wants more funcionality, like the ability to be notified even if his PC is off, which can only be done by a web service. Still, it was a nice exercise to develop the Reminders application. I learned and discovered quite a few things and all these discoveries and solutions are there in the code I provide.

Advertisements

About Dimitrios Kalemis

I am a systems engineer specializing in Microsoft products and technologies. I am also an author. Please visit my blog to see the blog posts I have written, the books I have written and the applications I have created. I definitely recommend my blog posts under the category "Management", all my books and all my applications. I believe that you will find them interesting and useful. I am in the process of writing more blog posts and books, so please visit my blog from time to time to see what I come up with next. I am also active on other sites; links to those you can find in the "About me" page of my blog.
This entry was posted in Development. Bookmark the permalink.