Using Dialog Boxes to Enhance Your Programs

As programmers started developing GUI software, it quickly became apparent that certain kinds of complex tasks are needed again and again. For example, allowing the user to choose a file is a potentially risky operation because the programmer doesn’t know anything about the user’s file structure (how many drives are on the computer, what the drive names are, and so on). Also, allowing the user to type in a file name is simple to program but leads to many errors. Soon standards began to appear. If you think about most programs you use, a standard form appears when you start to save or load a program. This form takes control of the program until the user makes a choice. Forms like this are called dialog boxes because they facilitate a dialog with the user. As a user, the dialog box that appears when you save or load files seems to be much the same no matter what program you are using. This leads to shorter learning time (because the dialog box is already familiar to you) and fewer mistakes (because you already know how to get around in the dialog box). In the early days of GUI programming, developers had to be able to build file dialog boxes by hand. The same thing was true of color-choosing dialogs, print dialogs, and font selection dialogs. These dialog boxes were tedious to create by hand, and ensuring that they work exactly as users expect was challenging.

Fortunately, the .NET framework offers prebuilt, standard dialog boxes to help you include the more common dialogs used by programmers. Each of these dialogs is a class with properties, methods, and events. You can use the dialogs to greatly simplify your interactions with the user.

Exploring the Dialog Demo Program

The Dialog Demo program extends the text editor built in the File IO program. It replaces the command buttons with menus and adds access to several standard dialog boxes to change the program's appearance and behavior. Figure 9.14 shows the Dialog Demo.

Figure 9.14. When the user chooses Open from the File menu, a familiar-looking dialog appears.


The file dialog makes your job as a programmer much easier because you don’t have to worry much about how it works (isn’t encapsulation grand?). All you have to do is drop it on the form, set a few properties, and respond to its events.

Notice that the dialog box is preset to display only text files (the file names end with .txt). You can set up a filter to display any kind of file you want. You can also determine a default directory, a default file name, and other interesting characteristics.

You can also change the font visible in the text editor with another custom editor. Figure 9.15 shows the font dialog.

Figure 9.15. The font dialog allows the user to set the font, including typeface, size, and style.


The font dialog is an especially welcome tool because fonts have a long history of causing trouble for programmers. Each user can install whatever fonts he or she wants on his own computer. However, the programmer has no way of knowing directly which fonts are on the client machines because each user’s machine has a different set of fonts installed. The font dialog sidesteps this problem by letting the user choose directly from the fonts installed on the user’s computer.

The Dialog Demo program also allows the user to change the foreground and background colors of the text editor. Figure 9.16 shows this process. Like files and fonts, color can be a challenging attribute for the programmer to control. The color dialog gives a simple mechanism for allowing the user to choose a color. The color dialog is more sophisticated than it seems at first glance. The Custom Colors option allows the user to generate a color using RGB and HSL (hue, saturation, luminance) models.

Figure 9.16. The user can independently set the foreground and background colors of the text editor.


Adding Standard Dialogs to Your Form

Although the standard dialogs seem to be a very diverse group of objects, they all work the same way from the programmer’s point of view. Each dialog is a control you can drop on the form. All are available in the Toolbox to the left of the IDE window. As you drop the dialogs on your form, you see them added in the offscreen space at the bottom of the form, where timers and image lists go. Like these other controls, the dialog boxes don’t have a physical presence on the screen; they appear at opportune moments under program control. Figure 9.17 shows the text editor with the dialog boxes added.

Figure 9.17. The dialogs are added to the bottom of the form. Notice the menu structure as well.


The dialog controls usually appear towards the bottom of the Toolbox list, so they aren’t immediately apparent in the IDE. You have to scroll down the Toolbox to see the dialog controls.

Like any other control, a dialog has properties that affect its appearance and behavior. Also, each dialog has at least one event it can trigger. The properties and events are associated with specific types of dialogs, so they are described separately in the sections that follow.

Using the File Dialog Controls

The OpenFileDialog and SaveFileDialog controls are almost identical. It’s important to understand that the dialogs don’t actually save and load files! As a user, you expect these dialogs to save and load files, but that isn’t the case from the programmer’s point of view. The real purpose of the file dialogs is to let the user choose a file name. It’s up to the programmer to save or load the file. Although this might seem like a burden, it isn’t, because the hardest part of saving and loading files is usually getting the file name from the user. Many other tools (such as the StreamReader and StreamWriter classes you learned about earlier in this chapter) help with the actual file manipulation. Dialogs are all about communication with the user. The file dialog controls have properties that simplify and direct this communication.

InitialDirectory

The InitialDirectory property lets you determine where in the user’s directory structure the dialog will display at first. You can set this to whatever you want, but it’s possible that the user’s directory structure will be unknown to you. The safest alternatives are in a directory your program has created (using the System.IO.Directory class) or in the program’s current working directory (denoted with a single period [.]). The default directory is wherever the program’s binary files are installed on the user’s machine. If you will be saving many files on the user’s machine, you might want to make a directory off the default directory and instruct dialog boxes to open in this directory.

The initial directory is just a starting place. The user is still free to navigate the entire drive system (and perhaps even the network) to save and load files.

Initial directories are especially important if you are writing programs for beginning users. Beginners often ignore the entire directory structure and save their files wherever the dialog first points them. This can lead to disaster if your load dialog doesn’t point to the same initial directory as the save dialog.

Filter

The Filter property allows the programmer to determine which files will appear by default. The filter is useful because it limits the displayed files to those types of files the program is expecting. Typically, you either use a recognized standard file extension (such as .txt for plain text) or create your own extension for special-purpose file types. In either case, you should also add a filter to allow for all files, because often users still want to see every file in the directory. The file filter consists of a file description followed by the pipe symbol (|) and a pattern that returns the description. For example, this pattern

Text files (*.txt)|*.txt

places the value Text files (*.txt) in the Files of Type list box and displays all files that end with .txt in the directory listing. A filter can consist of multiple patterns. For example, both the DialogDemo file dialogs use the following pattern:

Text files (*.txt)|*.txt|All files (*.*)|*.*

Be very careful with the patterns. If you put a space immediately after the pipe symbol, like this,

Text files (*.txt)| *.txt

the program will think that you are looking for files that begin with a space and end in .txt. Likewise, trailing spaces in a filter can cause the same kinds of problems. Test your filters carefully to ensure that they display exactly the types of files you’re expecting.

Responding to File Dialog Events

The file dialog objects generate events just like most other components. The FileOK event occurs when the user clicks the OK button after choosing a file. You can write code in the default event handler to deal with saving or loading the file. To retrieve the file name requested by the user, use the Filename property of the OpenFileDialog or SaveFileDialog control (whichever one you were using). Here’s the event handler code relating to the file dialogs in the Dialog Demo program:

 
private void mnuSaveAs_Click(object sender, System.EventArgs e) 
  {fileSaver.ShowDialog();
} 
private void fileSaver_FileOk(object sender,
         System.ComponentModel.CancelEventArgs e) {
  StreamWriter sw = new StreamWriter(fileSaver.FileName);
  sw.Write(txtEdit.Text);
  sw.Close();
}

private void mnuOpen_Click(object sender, System.EventArgs e) {
  fileGetter.ShowDialog();
}

private void fileGetter_FileOk(object sender,
         System.ComponentModel.CancelEventArgs e) {
  StreamReader sr = new StreamReader(fileGetter.FileName);
  txtEdit.Text = sr.ReadToEnd();
  sr.Close();
}

The mnuSaveAs_Click() method shows the fileSaver dialog box with the ShowDialog() method. The dialog then takes control of program flow until the user clicks OK or Cancel. If the user chooses Cancel, nothing further happens and the dialog closes down. If the user chooses OK, the fileSaver_FileOK() method leaps into action. It generates a stream writer based on the user’s choice of a file name. The user’s file name is stored in the FileName property of fileSaver, which is a SaveFileDialog. The method then writes the text to the stream writer and closes the stream.

The code for opening a file is very similar. A menu item click event–in this case, mnuOpen_Click()–shows the fileGetter, which is an OpenFileDialog. The fileGetter_FileOK() method triggers when the user clicks the OK button. This causes the creation of a StreamReader based on the user’s choice. The program reads the contents of the stream and copies the data to the text box. Finally, the method closes the StreamReader.

Using the Font Dialog Control

The FontDialog control works much like the file dialogs. It doesn’t change a font but asks the user to interactively choose a font, and that font is available as a property of the dialog for the programmer’s use. You add a font dialog to a form in the same way you add a file dialog. Drag it onto the form, and it moves to the off-screen area. Generally, it isn’t necessary to modify any of the font dialog’s properties, but you can preset the font to a font that will work well for your program. Although font dialogs also generate events, it makes more sense to work with the font information in the same code that calls the dialog. The code for the font menu item illustrates how this can be done:

private void mnuFont_Click(object sender, System.EventArgs e) {
  if (fontDialog1.ShowDialog() != DialogResult.Cancel){
    txtEdit.Font = fontDialog1.Font;
  } // end if
} // end mnuFont

The font dialog is displayed in the click event of the mnuFont object. However, this code takes advantage of the fact that the ShowDialog() method returns a value of type DialogResult. (As usual, I knew this only because I looked it up in the online help.) The program simultaneously displays the dialog and examines the result. If the result is not equal to DialogResult.Cancel, the program copies the Font property of the dialog to the Font property of the text box. The logic works like this: There are only two ways to get out of the dialog box–by clicking OK or Cancel. If the user clicks the Cancel button (indicated by a DialogResult.Cancel value), the program should simply move on. If the user chooses anything else (so that the result of the dialog is anything but DialogResult.Cancel), the program should proceed with the font-changing process.

If you like, you can use this approach of accessing the result of the ShowDialog() method to write your file access code without using the file dialog’s methods. I will soon show you this second technique of file dialog access in the section “Storing Entire Objects with Object Serialization.”

Using the Color Dialog Control

The code for the color-changing menu items is very similar to the code for changing the font:

private void mnuForeground_Click(object sender,
         System.EventArgs e) {
  if (colorDialog1.ShowDialog() != DialogResult.Cancel){
    txtEdit.ForeColor = colorDialog1.Color;
  } // end if
}  
private void mnuBackground_Click(object sender,
        System.EventArgs e) {
  if (colorDialog1.ShowDialog() != DialogResult.Cancel){
        txtEdit.BackColor = colorDialog1.Color;
  } // end if
} // end

The event handlers are strikingly similar. Both display colorDialog1 and copy the Color property from that dialog to the text box if the user didn’t cancel. However, the mnuForeground event copies the color to the text box’s ForeColor property, and the mnuBackground event copies the color to the BackColor property of the text box.

If I had insisted on using the event technique with the color dialog, I would have a problem because two different methods need access to the same dialog. Either I would need two color dialogs (which would be wasteful of system resources), or I would have to determine in the event code which method called the dialog (which is possible with the sender parameter, but somewhat clumsy). The approach described in this section seems more appropriate for this particular situation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.233.43