Introduction
I don't know how many of you out there were MFC programmers, but if you were, I'm sure you remember the days of the Tip of the Day dialog. You know, those slightly annoying but seemingly helpful dialogs you added to your MFC application that popped up to aid the forlorn user in your ever-complex application. Yeah...that dialog. Well for those of you who miss the antiquated popup, here it is again in all its glory. Now you can give your user base that added comfort they missed from the olden days of Visual C++ in C# and .NET.
Design
The tip of the day dialog is a self contained .NET Window Form that reads the tips from a text file and the current tip index from a binary file. The class is shown in the UML diagram in figure 2. Initially, when the dialog is opened, the ReadTipsFile reads all the tips into the program and ReadTipIndex method reads the current tip number in the tip file. By persisting the tip index, we never read the same tip twice until all the other tips are exhausted. IncrementTipCount increments the count to the next tip. UpdateTip updates the dialog with current tip text from the tips file.
Figure 2 - TipOfTheDayDialog Class reverse engineered using the WithClass UML Tool
Reading in the Tips
Tips are read into the dialog using the ReadTipsFile method. The method uses a StreamReader to read all of the tips into a string. Since each tip is on a separate line on the file, the tips are then broken up into a string array by splitting the tips by line break as shown in listing 1.
Listing 1 - Reading in the Tips
void ReadTipsFile()
{
try
{
// read the entire tips file into a string
StreamReader reader = new StreamReader(_appPath + _tipFile);
string tipBlock = reader.ReadToEnd();
reader.Close();
// split the tips into an array of tips by linebreak
_tips = tipBlock.Split(new char[]{'\n'});
}
catch (Exception ex)
{
MessageBox.Show(String.Format("Could not open tips file - {0}", ex.Message.ToString()));
btnNextTip.Enabled = false;
return;
}
}
Reading and Writing a Binary File
The System.IO namespace is quite rich and we can persist any serializable type using this namespace. By using the FileStream, BinaryReader, and BinaryWriter, we can completely persist the current tip index in a file. We can also use the same file to persist whether or not we want the dialog to display at startup of the application with a boolean. Listing 2 shows us how we can read the current tip count file to get the current tip index and the startup flag:
Listing 2 - Reading the persistent TipOfTheDay Information
void ReadTipCountFile()
{
// open the tip count file stream for reading
FileStream file = new FileStream(_appPath + _tipCountFile, FileMode.Open, FileAccess.Read);
// use the binary reader to get the current tip index and the startup flag
BinaryReader br = new BinaryReader(file);
_tipCount = br.ReadInt32();
chkShowTipsOnStartup.Checked = br.ReadBoolean();
IncrementTipCount(); // increment the count for the next tip
br.Close(); // close the reader and the stream
file.Close();
}
When we are ready to close the dialog, we want to save our current tip index and our other preferences. Using the FileStream and the BinaryWriter, this is easily accomplished as shown in listing 3. The BinaryWriter is a nice tool, because it has many overrides to write the correct .NET type without the programmer having to worry about which type is being written.
Listing 3 - Writing the persistent TipOfTheDay Information
void WriteCurrentTipCount()
{
// Open the stream for writing over the existing tipcount file
FileStream file = new FileStream(_appPath + _tipCountFile, FileMode.Truncate,FileAccess.Write);
BinaryWriter bw = new BinaryWriter(file);
// write the current index
bw.Write(_tipCount); // increment count
// write the startup flag
bw.Write(chkShowTipsOnStartup.Checked);
// close the binary writer and the stream
bw.Close();
file.Close();
}
Using the TipOfTheDayDialog
Using the dialog is quite easy. You simply call the ShowDialog method when you want to show the tip of the day. All the mechanisms of the TipOfTheDayDialog are controlled internally. Well almost all of the mechanisms. When you want to decide whether or not to show the dialog on startup, you need to call the public static function IsShowTipsOnStartup to see if we should display the dialog on startup from our application. The IsShowTipsOnStartup method of the TipOfTheDayDialog reads the tipcount binary file and reads in the boolean startup flag. Listing 4 shows the startup code for our mini-application:
Listing 4 - Showing the Tip of the Day Dialog at Startup
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
// Check for showing tip of the day dialog from startup
if (TipOfTheDayDialog.IsShowTipsOnStartUp())
{
TipOfTheDayDialog dlg = new TipOfTheDayDialog();
dlg.ShowDialog();
}
}
Conclusion
The tip of the day dialog is a nice way to coach your user base on your application. Even if it bothers your user, they can always turn it off at startup. Anyway, sometimes a tip from the past can help you get your ideas across to your user base. This is made easy with the use of C# and .NET.