Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C# ПІДРУЧНИКИ / c# / Manning - Windows.forms.programming.with.c#.pdf
Скачиваний:
108
Добавлен:
12.02.2016
Размер:
14.98 Mб
Скачать
Photo-

///<summary>

///Required method for Designer support - do not modify

///the contents of this method with the code editor.

///</summary>

private void InitializeComponent()

{

components = new System.ComponentModel.Container();

. . .

}

#endregion

. . .

}

}

Take a look at the properties for the PhotoEditDlg object. The form has inherited all of the settings from our BaseEditDlg form to make it into a dialog box. The buttons and panel from the base class appear on the form as well, and you can examine the properties for the individual buttons. Note in particular that the OK, Reset, and Cancel buttons are private and cannot be modified, while the protected Panel can.

We will leave the topic of inherited forms for now and move on to specific controls for our PhotoEditDlg form. Before we do, it is worth realizing how powerful this feature really is. For example, a standard form for a database table could be created. Applications that use this table can customize the form for their specific needs, or libraries that extend the existing database can build a new form based on the original. In many cases, changes to the original database can be encoded in the base class in such a way that no changes are required in the inherited forms.

When you need a set of forms in your application based on a common concept or theme, consider creating a base form from which other forms can be derived.

9.2LABELS AND TEXT BOXES

In our MyPhotos application, we have already used the Label and TextBox classes while creating dialog boxes in chapter 8. Here we will look at these classes in a bit more detail as we place them on our PhotoEditDlg form.

To do this, we need to come up with some reasonable properties in our

graph class that will facilitate the creation of these and other controls. The following features will serve our purposes rather well:

Caption—a caption for the photo. We created this property in chapter 8.

Date—the date the photograph was taken. We will present this as a string on our form here, and convert our dialog to use the DateTimePicker control in chapter 11.

Photographer—the person who took the photo. For now, we will treat this setting as a string. Later in the book this setting will be taken from a list of possible photographers.

Notes—random notes or other comments about the photograph.

LABELS AND TEXT BOXES

271

A dialog to support these new settings is shown in figure 9.2. This dialog will be constructed and discussed over the next few sections. In this section we will create the infrastructure required in the Photograph class to support these new settings, add the required controls to the dialog, and invoke the dialog from the main form of our MyPhotos class. We also look at some of the settings and events provided by the TextBox class for modifying the behavior or appearance of the control.

We will start with the changes required in our Photograph class.

Figure 9.2

Our Photo Properties dialog adds Label and Textbox controls to our inherited form.

9.2.1EXPANDING THE PHOTOGRAPH CLASS

In order to support the date, photograph, and notes settings in our photos, we need to make a few changes. This section adds these features to our Photograph object, as well as the ability to read and write photographs, and update the Save and Open methods in our PhotoAlbum class.

We begin with some variables to hold these values and properties to provide external access.

Set the version number of the MyPhotoAlbum library to 9.2.

ADD NEW MEMBERS TO THE PHOTOGRAPH CLASS

 

Action

Result

 

 

 

1

In the Photograph.cs file, add

. . .

 

some variables to hold the new

private string _caption;

 

settings.

private DateTime _dateTaken;

 

private string _photographer;

 

 

 

Note: The DateTime structure

private string _notes;

 

used here represents a spe-

 

 

cific day and time.

 

 

 

 

272

CHAPTER 9 BASIC CONTROLS

ADD NEW MEMBERS TO THE PHOTOGRAPH CLASS (continued)

 

Action

Result

 

 

 

2

Initialize these new settings in

public Photograph(string fileName)

 

the constructor.

{

 

 

_fileName = fileName;

 

 

_bitmap = null;

 

 

_caption = Path.

 

 

GetFileNameWithoutExtension(fileName);

 

 

_dateTaken = DateTime.Now;

 

 

_photographer = "unknown";

 

 

_notes = "no notes provided";

 

 

}

 

 

 

3

Add properties to set and

public DateTime DateTaken

 

retrieve these values.

{

 

Note: A Caption property was

get { return _dateTaken; }

 

set { _dateTaken = value; }

 

added in chapter 8, and is not

}

 

shown here.

public string Photographer

 

 

 

 

{

 

 

get { return _photographer; }

 

 

set { _photographer = value; }

 

 

}

 

 

public string Notes

 

 

{

 

 

get { return _notes; }

 

 

set { _notes = value; }

 

 

}

 

 

 

This code is similar to member fields and properties we have seen before, except for the DateTime structure. This structure represents an instant in time measured in 100 nanosecond units since 12:00:00 AM on January 1, 0001, with a maximum value of 11:59:59 PM on December 31, 9999. Each nanosecond unit of time is called a tick. Members of this structure allow you to add, subtract, format, and otherwise manipulate date and time values. A related TimeSpan structure represents an interval of time. You can look up these structures in the .NET Framework documentation for more information on these types.

With our fields and properties defined, we next need to store and retrieve these values in the Save and Open methods of our PhotoAlbum class. Since the Photograph class is becoming a bit more complex, we will create Read and Write methods in this class to encapsulate the logic required. The Write method will store a photo into an open StreamWriter object, while various Read methods will accept an open

StreamReader and return a Photograph object.

In our PhotoAlbum class, we will use these new methods to save and load a new version of our album file. It will be version 92, to match the current section of the book.

Let's continue our previous steps and create Read and Write methods in our

Photograph class.

LABELS AND TEXT BOXES

273

ADD READ AND WRITE METHODS TO THE PHOTOGRAPH CLASS

 

Action

Result

 

 

 

4

Create a public Write method in the

public void Write(StreamWriter sw)

 

Photograph.cs file to store a

{

 

Photograph into a given file.

// First write the file and caption.

 

sw.WriteLine(this.FileName);

 

 

 

How-to

sw.WriteLine(this.Caption);

 

 

 

a. Store the file name, caption, and

// Write the date and photographer

 

photographer as a string.

sw.WriteLine(this.DateTaken.Ticks);

 

b. Convert the DateTime to a num-

sw.WriteLine(this.Photographer);

 

 

 

ber of ticks and store this value.

// Finally, write any notes

 

c. Since the notes may span multiple

sw.WriteLine(this.Notes.Length);

 

lines, store the length of this string

sw.Write(this.Notes.ToCharArray());

 

sw.WriteLine();

 

and write its value as an array of

 

}

 

characters.

 

 

 

 

5

Create a ReadVersion66 and

static public Photograph

 

ReadVersion83 method to read in

ReadVersion66(StreamReader sr)

 

the data in the existing formats.

{

 

String name = sr.ReadLine();

 

 

 

Note: These methods are static

if (name != null)

 

since they create a new Photograph

return new Photograph(name);

 

else

 

instance from the data provided by

 

return null;

 

the given stream.

}

 

 

static public Photograph

 

 

ReadVersion83(StreamReader sr)

 

 

{

 

 

String name = sr.ReadLine();

 

 

if (name == null)

 

 

return null;

 

 

Photograph p = new Photograph(name);

 

 

p.Caption = sr.ReadLine();

 

 

return p;

 

 

}

 

 

 

274

CHAPTER 9 BASIC CONTROLS

ADD READ AND WRITE METHODS TO THE PHOTOGRAPH CLASS (continued)

 

Action

Result

 

 

 

6

Create a static ReadVersion92

static public Photograph

 

method to read in a Photograph for

ReadVersion92(StreamReader sr)

 

our new version 92 of an album file.

{

 

// Use ReadVer83 for file and caption

 

 

 

How-to

Photograph p = ReadVersion83(sr);

 

if (p == null)

 

a. Load the file name and caption

 

return null;

 

using the ReadVersion83

 

 

method.

// Read date (may throw FormatException)

 

b. Read the date as a string and con-

string data = sr.ReadLine();

 

long ticks = Convert.ToInt64(data);

 

vert it to a long integer to instanti-

p.DateTaken = new DateTime(ticks);

 

ate a DateTime object.

// Read the photographer

 

c. Read the photographer as a string.

 

p.Photographer = sr.ReadLine();

 

d. For the notes, read in the number

// Read the notes size

 

of characters and use this value to

 

data = sr.ReadLine();

 

read an equivalent-sized array of

 

int len = Convert.ToInt32(data);

 

characters. This array can then be

 

 

used to create a string.

// Read the actual notes characters

 

e. After the Notes property is set, a

char[] notesArray = new char[len];

 

sr.Read(notesArray, 0, len);

 

final ReadLine call is required to

p.Notes = new string(notesArray);

 

clear the final line in preparation for

sr.ReadLine();

 

reading the next Photograph

return p;

 

object.

 

}

 

 

 

7

Create a public delegate to use

public delegate Photograph

 

when selecting the appropriate

ReadDelegate(StreamReader sr);

 

reader.

 

 

 

 

Before we update the Save and Open methods in the PhotoAlbum class, a short discussion of our sudden use of the delegate keyword is in order.

We briefly mentioned in chapter 1 that a delegate acts much like a function pointer in C++. It identifies the signature for a method without actually defining a method. The advantage of C# delegates is that they are type safe. It is impossible to assign a nonconforming method to a delegate.

In our code, we create a delegate called ReadDelegate. This delegate encapsulates methods that accept a single StreamReader parameter and return a Photograph object. It just so happens that this matches the signature of the three read methods we created in the prior steps. This delegate can be used to great advantage when opening an album. Let’s see how this looks.

LABELS AND TEXT BOXES

275

Соседние файлы в папке c#