Click here to Skip to main content
15,880,469 members
Articles / Desktop Programming / Windows Forms

Sticky notes with C# (Simple application)

Rate me:
Please Sign up or sign in to vote.
4.69/5 (6 votes)
29 Sep 2013CPOL5 min read 63.9K   3.7K   27   11
A simple program in C#.

Introduction

I am trying to study and understand the main principles of C# coding. This is my third program - a simple stick note. This is like Notepad - allows to quickly add some notes that are be visible at all times.

Background

The main idea of this program - an easy way to put notes that can always be viewed by the user. In the picture below you can see a sample of the program window. 

Image 1

On CodeProject the are a lot of similar programs, but I took just the idea and did it in my own way. 

I was looking for the possibility to use config files in programs. In this program, I have tried to realize some ways to use and store data (keys) in the App.exe.config file. Also how to do something, using hotKeys - as a result, I added this functionality to the app. 

Using the code

Structure of the program - just a few classes, described below: 

  • ConfManager - class for working with the config file
  • FormMain - class for working with main forms and some functions for the context menu
  • DateInfo - class for getting current time and date
  • FileOpenClose - open and save file with notes
  • Settings - class for working with storing settings in the config file
  • HotKeyForm  - class for working with storing and detecting key press (for HotKeys) 

Let's looking class by class most interesting things (as for my opinion).

So, first one - the ConfManager class that provides the possibility to work with the config file. Here we require a simple logic - just read or write a key value from a config file. For working with a config file first of all, you need to add a link to:

C#
System.Configuration; 

So, to get value from the config file, use ConfigurationManager, but first of all you must add startup configuration to your config file (if you want to use custom config file in your program - read this post). For additional information about how to configure config file, read here

C#
public int GetValue(String paramName)
{
   return Convert.ToInt32(ConfigurationManager.AppSettings[paramName]);
}

For storing keys into the config file - first of all we must say where the file is located, then choose the parameter name and save all the changes - see method below: 

C#
public void SetStringParam(String paramName, int value)
{
    Configuration config =
        ConfigurationManager.OpenExeConfiguration(System.Windows.Forms.Application.ExecutablePath);
    config.AppSettings.Settings[paramName].Value = value.ToString();
    config.Save(ConfigurationSaveMode.Modified);
}

Also, I put additional similar methods to this class, but only difference is the returned result - string or int. 

FormMain class

In this class I put some methods for working with the main form of my program - using keys, showing date and time, setting default values, using Hotkeys (on KeyDown event), and adding context menu.

As you can see on picture - there are a few fields on the main form - I used LayoutPanel for better controlling position of elements on the main form.

 Image 2

Simple things (like context menu, timers for clock, etc.) must be described. Describe methods for adding new form or open existing file - 

C#
private void OpenNew()
{
    if (Application.OpenForms.Cast<Form>().Count()
        < Convert.ToInt32(cm.GetValue("maxOpenNote")))
    {
        if (!checkBoxOpen.Checked)
        {
            FormMain fm = new FormMain();
            fm.Width = 300;
            fm.Show();
        }
        if (checkBoxOpen.Checked)
        {
            if (this.textBox1.Text.Length == 0)
            {
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    openFileDialog1.Title = "Open Note";
                    f.OpenFile(openFileDialog1.FileName.ToString(), this.textBox1);
                }
            }
            else
            {
                if (MessageBox.Show("Do you want to save current Note?", "Saving Note...",
                    MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning,
                    MessageBoxDefaultButton.Button1) == DialogResult.Yes)
                {
                    if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                    {
                        saveFileDialog1.Title = "Save note";
                        f.SaveFile(saveFileDialog1.FileName.ToString(), textBox1);
                    }
                }
                else
                {
                    if (openFileDialog1.ShowDialog() == DialogResult.OK)
                    {
                        openFileDialog1.Title = "Open Note";
                        f.OpenFile(openFileDialog1.FileName.ToString(), this.textBox1);
                    }
                }
            }
        }
    }
    else
    {
        MessageBox.Show("Maximum q-ty of Notes - " +
            Convert.ToInt32(cm.GetValue("maxOpenNote")) + " If you want more - please change settings",
            "Information");
    }
} 

Also in settings, user can define how many open windows can be opened at one time - for better controlling of the program. For counting opened windows, use code:

C#
Application.OpenForms.Cast<Form>().Count()
                < Convert.ToInt32(cm.GetValue("maxOpenNote"))

Where Form is the name of the form (in my program, I don't change it from default, so it's Form).

Another point - if the checkBox open is checked - then user must choose to save the current note to file or open file without saving the current note - it will be overwritten by data from the opened file.  

But one of the interesting points - it's storing the font type and color type in the config file as string. For this purpose I use TypeConverter. Below method is for storing font as a value to the key in the config file:

C#
public void FontDialogSet(TextBox textBox, FontDialog fontDialog)
{
    if (fontDialog.ShowDialog() == DialogResult.OK)
    {
        Font font = fontDialog.Font;
        textBox.Font = font;
        //save as default value
        TypeConverter converter = TypeDescriptor.GetConverter(typeof(Font));
        string fontString = converter.ConvertToString(font);
        cm.SetStringParam("fontStyle", fontString);
    }
}

For converting string to Font, use the code below:

C#
TypeConverter converter = TypeDescriptor.GetConverter(typeof(Font));
textBox1.Font = (Font)converter.ConvertFromString(cm.GetValueString("fontStyle").ToString()); 

Using such logic, create a method for storing color type as key value in the config file.

Another interesting thing - how to hide part of the form (simulate Show/Hide panel) - just change the size of the form: 

C#
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
    if (!checkBox1.Checked)
    {
        this.Width = 355;
        checkBox1.Text = "hide Panel";
    }
    if (checkBox1.Checked)
    {
        this.Width = 300;
        checkBox1.Text = "show Panel";
    }
} 

One more interesting point (for me as well) - how to detect required by user combination of hot keys. For this purpose we use class HotKeyForm, but some part of the detection implementation is in this class - the below part of the method is for detection of keypress combination.

C#
string[] keyValueTemp; //will be used for storing others setting 
TypeConverter converter = TypeDescriptor.GetConverter(typeof(Keys));

if (ht.statusCheckBoxOpen())
{
    keyValueTemp = cm.GetValueString("open").ToString().Split(',');
    Keys key = (Keys)converter.ConvertFromString(keyValueTemp[0]);
    // Keys key = (Keys)Enum.Parse(typeof(Keys), keyValueTemp[0], true); //alternative way
    Keys key2 = (Keys)converter.ConvertFromString(keyValueTemp[1]);
    if (e.Modifiers == key && e.KeyCode == key2)
    {
        OpenNew();
    }
}

In this code you can see two variants of how to stored to a string key. I also want to say, for this purpose we can use the event KeyPress, but KeyDown is preferred - because it happens just during pressing the key.

The next class - HotKeyForm class - it is pretty simple, but I want to mention one thing that took a big part of my time - How to allow or disable all elements in a form. For this purpose use the code below.

C#
private void EnableControls(Control.ControlCollection controls, bool status)
{
    foreach (Control c in controls)
    {   
        c.Enabled = status;         
        if (c is MenuStrip)
        {
            c.Enabled = true;
        }
        if (c.Controls.Count > 0)
        {
            EnableControls(c.Controls, status);
        }
    }
    tableLayoutPanel1.Enabled = true;
    checkBoxEnableHotKeys.Enabled = true;
}

Here you can see how we can enable or disable elements on a form.

Note, that all parent objects are disabled if the parent is disabled. So for enabling a checkbox that is placed into a TableLayoutPanel, I enable it - spent an hour finding the reason, but now Noted for myself. All others things in this class are simple and does not require any explanation.

The next class used in this program - DateInfo - has a single method for getting the date and time.

C#
public string GetCurrentDateTime()
{
    return (DateTime.Today).ToShortDateString()+" "+ String.Format("{0:HH:mm:ss}",DateTime.Now);
}

And the  last one - OpenCloseFile - here I put a method for storing/reading some notes in/out to/from a simple *.txt file if required. For this purpose I used StreamWriter/StreamReader; as a sample, below is a method for saving a file with a note: 

C#
public void SaveFile(string fileName, TextBox textBox)
{
    try
    {
        if (textBox.Text.Length > 0)
        {
            FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
            StreamWriter sw = new StreamWriter(fs);
            sw.Write(textBox.Text);
            sw.Close();
            MessageBox.Show("File saved", "Save");
        }
        else
        {
            MessageBox.Show("Nothing to save - note is empty", "Nothing to save",
                MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
    catch (Exception)
    {
    }
}

First of all - check if the note is not empty, if true - create a stream for storing it into the file, and show message about success; if there is nothing to save - another message. 

Thanks

I want to say thanks to all those who helped me with this program. Due to my studies, I had a lot of questions while working on it .

Points of interest 

  • Implementing Find function
  • Change TextBox to GridViewBox
  • To add some skins support for program
  • Add some reminders for events  

License

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


Written By
Engineer
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionWHY NOT LEARNING MVC Pin
Artur Mustafin10-Oct-13 20:33
Artur Mustafin10-Oct-13 20:33 
Hi, I whould like to see a great app, created from scratch, as an MVC pattern implementation, that whould save you a lot of time and shows up a beauty of coding using this idiom. I can help you with it, if you interested to learn some thchniques of coding, differs a way out of your coding culture, konwn as spagetti code.
3-step rule:


0) Layer all files as follows 2-3 folders, according to layering for your app: DL, BL, UX, Use a loosely coupled desighn, if possible (f.e. use a proxy patern, interface pattern, command pattern)

1) Desighn model

-You will code all entities of your virtual world for your great app.
Note, TaskManager
-Here you need to create unit tests for your model
Note -AddNote and to be shure, for example, that TaskManager recieves a new task, for exampl

2) Desighn presenter/controller
-Create classes skeletons
NotePresenter, NoteCommand
-Here you will create a tests as of TDD fan, one test set for each instance (tests will mock, because MVP/MVC is barely loosely coulped, and you probably will introduce IView, IModel, and use a mocking objects just to test NodePresenter class)

3) Desighn View
-Here comes usability integrational tests, which an be simple word document with drawings and description what happens, i.e. behaviors.

4) Use agile approach, I mean not to try to implement everething before you pass all unin tests, just a few, to make it (implement all using this is cycles of dev lifecycle - run, fing errors, write tests- fix tests, run again), and these are simple milestones:

-does it open/close?
-does it adds single note?
-does it shows a single note?
-does it write a single note to DB/whatever?
-does it reads a single note from DB?
-does it shedules note/timer actually works?
-does it adds group of notes?
-does it writes froup of notes?
-does it shows group of notes?

5) save commits to source code server, or locally, after achievig each milestone, which changes a minor version numer (next to lowest byte), and between milestones, which changes a buid or version number (lowes byte).

6) release a product, when it gains 80% quality in average (tests, usability goals, ets), f e it you got 100% code coverage, whu=ich shows up that totally 80%of tests is passes, it is ok, if you also comlete 4 of 5 usability goals. Also it is OK, if TDD shows 100% test pass but you implemented only 2 of 3 goals (60%), because (100% + 60% / 2 = 80%)

Just an advice to do everything as in big projects, but in smaller scale (I mean you do not need to install JIRA, for Notes app, you can succesfully use Notepad with Excel sheets for error traching & fixing Wink | ;)

Best wishes!
AnswerRe: WHY NOT LEARNING MVC Pin
Kirill__3-Nov-13 2:48
Kirill__3-Nov-13 2:48 
QuestionGood work Pin
bæltazor1-Oct-13 12:15
bæltazor1-Oct-13 12:15 
AnswerRe: Good work Pin
Kirill__1-Oct-13 23:32
Kirill__1-Oct-13 23:32 
QuestionNice small app. Pin
GregoryW29-Sep-13 20:18
GregoryW29-Sep-13 20:18 
AnswerRe: Nice small app. Pin
Kirill__30-Sep-13 6:47
Kirill__30-Sep-13 6:47 
GeneralRe: Nice small app. Pin
GregoryW30-Sep-13 7:03
GregoryW30-Sep-13 7:03 
GeneralRe: Nice small app. Pin
Kirill__30-Sep-13 7:10
Kirill__30-Sep-13 7:10 
GeneralRe: Nice small app. Pin
GregoryW30-Sep-13 7:16
GregoryW30-Sep-13 7:16 
GeneralRe: Nice small app. Pin
Kirill__30-Sep-13 8:12
Kirill__30-Sep-13 8:12 
GeneralRe: Nice small app. Pin
GregoryW30-Sep-13 8:15
GregoryW30-Sep-13 8:15 

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.