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.
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 menuDateInfo
- 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:
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.
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:
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.
Simple things (like context menu, timers for clock, etc.) must be
described. Describe methods for adding new form or open existing file -
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:
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:
public void FontDialogSet(TextBox textBox, FontDialog fontDialog)
{
if (fontDialog.ShowDialog() == DialogResult.OK)
{
Font font = fontDialog.Font;
textBox.Font = font;
TypeConverter converter = TypeDescriptor.GetConverter(typeof(Font));
string fontString = converter.ConvertToString(font);
cm.SetStringParam("fontStyle", fontString);
}
}
For converting string to Font
, use the code below:
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:
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.
string[] keyValueTemp; TypeConverter converter = TypeDescriptor.GetConverter(typeof(Keys));
if (ht.statusCheckBoxOpen())
{
keyValueTemp = cm.GetValueString("open").ToString().Split(',');
Keys key = (Keys)converter.ConvertFromString(keyValueTemp[0]);
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.
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.
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:
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