1. Trang chủ
  2. » Công Nghệ Thông Tin

Manning Windows Forms Programming (phần 7) docx

50 343 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Manning Windows Forms Programming (phần 7)
Trường học University of Example
Chuyên ngành Windows Forms Programming
Thể loại sách hướng dẫn
Năm xuất bản 2023
Thành phố Unknown
Định dạng
Số trang 50
Dung lượng 388,24 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

mod-Possible values for the Modifiers property Value C# equivalent Comments for Form inheritance Public public Any class, regardless of where and how it is defined, can modify the contr

Trang 1

This ensures that any new objects added to the project will be created with thisnamespace With this change in place, we can create our base form.

Here we will just create the form and its controls Later in this section we will ate some infrastructure that will be useful in our derived forms later in the chapter

cre-CREATE THE BASEEDITDLG FORM

2 Add a new Form to the MyPhotoAlbum

project called “BaseEditDlg.”

The new class appears in the Solution Explorer window and the BaseEditDlg.cs [Design] window is displayed.

3 Add the three buttons to the form Assign

their settings and position as shown.

4 Add a Panel to the top of the form.

Note: The Modifiers property used here establishes the accessibility level of the control The three buttons use the default setting of Private The Protected setting creates a protected control so that it can

be modified in subclasses.

Settings Button Property Value

DialogResult OK Text &OK Reset (Name) btnReset

Text &Reset Cancel (Name) btnCancel

DialogResult Cancel Text &Cancel

Settings Property Value

BorderStyle FixedSingle Modifiers Protected

Trang 2

The code generated here is similar to code we have seen for other forms in our cation The one exception is the panel1 control The three buttons are defined as

appli-private controls as have all the controls we created in earlier chapters The panel1

object is a protected control As we shall see, this will allow our child forms tomodify the settings of this panel, and in particular change its size to accommodate thedesired collection of controls

private System.Windows.Forms.Button btnOk;

private System.Windows.Forms.Button btnReset;

private System.Windows.Forms.Button btnCancel;

protected System.Windows.Forms.Panel panel1;

The cause of this change is the Modifiers property setting This is not an actualproperty in the C# sense, and does not appear in the documentation for the Button

class This setting appears in the Properties window within Visual Studio to allow theaccess level for a control to be set There are five possible values of this setting, asshown in the following table:

5 Set the properties for the BaseEditDlg

form to make it a dialog box.

CREATE THE BASEEDITDLG FORM (continued)

Settings Property Value

AcceptButton btnOk CancelButton btnCancel FormBorderStyle FixedDialog MaximizeBox False MinimizeBox False ShowInTaskBar False Size 300, 320

Trang 3

Based on the table, we could have used either the Protected or Protected nal setting here Since there is no reason to prevent derived forms in external assem-blies from modifying the Panel control, the Protected value will work just fine.Before we move on, notice that our subclasses will not be able to add Click han-dlers for our private buttons The OK and Cancel buttons have assigned actions due

Inter-to their DialogResult setting When either button is clicked, the dialog is vated and the appropriate value returned We will require a way to save our modifiedsettings when the OK button is clicked, and we need a way to perform an action whenthe Reset button is clicked

deacti-As a solution, let’s add two protected methods that child classes can implement

to handle these situations We will create a SaveSettings method to store the ified values, and a ResetSettings method to handle a click of the Reset button.This continues our previous steps

mod-Possible values for the Modifiers property

Value C# equivalent Comments for Form inheritance

Public public Any class, regardless of where and how it is defined, can modify

the control This is not typically used, since you do not normally want any object to modify the location, size, or other internal control settings of your form.

Protected protected Any subclass of the form, regardless of where it is defined, can

modify the control.

Protected

Internal

protected internal

Any subclass of the form that is defined in the same assembly can modify the control.

Internal internal Any class in the same assembly, regardless of how it is defined,

can modify the control This is safer than public access, since you typically have control over the classes common to an assembly.

Private private No subclass can modify the control This is the default setting.

CREATE OVERRIDABLE METHODS FOR OK AND RESET BUTTONS

6 Create a protected virtual method for

resetting the form.

protected virtual void ResetSettings() {

// Subclasses override to reset form }

7 Add a Click handler for the Reset

button to invoke this new method.

private void btnReset_Click (object sender, System.EventArgs e) {

ResetSettings();

}

8 Create a protected virtual method for

saving the dialog settings when a form is deactivated This should return whether the save was successful.

protected virtual bool SaveSettings() {

// Subclasses override to save form return true;

}

Trang 4

The ResetSettings and SaveSettings methods are now available to ourderived forms Compile your code to make the base form available for inheritance.Next, let’s create a derived form for editing a photograph’s settings The Base- EditDlg form will act as the parent of this new form.

A new form is derived from an existing form the same way that any new class is derivedfrom an existing class The base form is defined as the parent class of the new form. public class PhotoEditDlg : Manning.MyPhotoAlbum.BaseEditDlg

9 Override the OnClosing method for

the form to invoke this new method when the user clicks the OK button.

Note: This method is discussed in

detail in chapter 8 Note how the tings are saved only if a subclass has not cancelled the operation.

protected override void OnClosing (CancelEventArgs e)

{

if (!e.Cancel && (this.DialogResult == DialogResult.OK)) {

1 Open the Add New Item dialog to

add a new PhotoEditDlg form inherited from the existing

b Select Add Inherited Form…

from the Add menu.

c Enter the name “PhotoEditDlg.”

Trang 5

View the code generated in the PhotoEditDlg.cs file, an excerpt of which follows.You will note that the new class is based on the BaseEditDlg class, and does not yetcontain any controls of its own.

#region Designer generated code

2 Click the Open button to display the

Inheritance Picker dialog.

This window is shown in the next step.

3 Define BasedEditDlg as the base

class for the new form.

Note: If you get an error here, it

likely means that your Dlg form was never compiled

BaseEdit-Visual Studio looks for inheritable forms in the existing assembly, so you must compile before you can inherit.

4 Click the OK button in the

Inheritance Picker dialog to create the class file and add it to the MyPhotoAlbum project.

Settings

Set the Text property to

“PhotoEditDlg” to distinguish this window from our base form.

A new file PhotoEditDlg.cs is added to the project and the PhotoEditDlg.cs [Design] window is displayed.

Note: Notice the small graphic on the existing

controls here This graphic indicates that these controls are inherited by the form.

DERIVE THE PHOTOEDITDLG FORM FROM THE BASEEDITDLG FORM (continued)

Trang 6

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

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

We will leave the topic of inherited forms for now and move on to specific trols for our PhotoEditDlg form Before we do, it is worth realizing how powerfulthis feature really is For example, a standard form for a database table could be cre-ated Applications that use this table can customize the form for their specific needs,

con-or libraries that extend the existing database can build a new fcon-orm based on the con-inal In many cases, changes to the original database can be encoded in the base class

orig-in such a way that no changes are required orig-in the orig-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

In our MyPhotos application, we have already used the Label and TextBox classeswhile creating dialog boxes in chapter 8 Here we will look at these classes in a bitmore 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 followingfeatures will serve our purposes rather well:

Photo-•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 inchapter 11

Photographer—the person who took the photo For now, we will treat this

set-ting as a string Later in the book this setset-ting will be taken from a list of ble photographers

possi-•Notes—random notes or other comments about the photograph.

Trang 7

A dialog to support these new settings is shown in figure 9.2 This dialog will be structed and discussed over the next few sections In this section we will create theinfrastructure required in the Photograph class to support these new settings, addthe required controls to the dialog, and invoke the dialog from the main form of our

con-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

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 nal access

exter-Set the version number of the MyPhotoAlbum library to 9.2.

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

ADD NEW MEMBERS TO THE PHOTOGRAPH CLASS

1 In the Photograph.cs file, add

some variables to hold the new settings.

Note: The DateTime structure used here represents a spe- cific day and time.

private string _caption;

private DateTime _dateTaken;

private string _photographer;

private string _notes;

Trang 8

This code is similar to member fields and properties we have seen before, except forthe 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 maximumvalue 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 formore information on these types

With our fields and properties defined, we next need to store and retrieve thesevalues in the Save and Open methods of our PhotoAlbum class Since the Photo-graph 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 photointo 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 newversion 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

3 Add properties to set and

retrieve these values.

Note: A Caption property was added in chapter 8, and is not shown here.

public DateTime DateTaken {

get { return _dateTaken; } set { _dateTaken = value; } }

public string Photographer {

get { return _photographer; } set { _photographer = value; } }

public string Notes {

get { return _notes; } set { _notes = value; } }

ADD NEW MEMBERS TO THE PHOTOGRAPH CLASS (continued)

Trang 9

ADD READ AND WRITE METHODS TO THE PHOTOGRAPH CLASS

4 Create a public Write method in the

Photograph.cs file to store a

Photograph into a given file.

public void Write(StreamWriter sw) {

// First write the file and caption sw.WriteLine(this.FileName);

sw.WriteLine(this.Caption);

// Write the date and photographer sw.WriteLine(this.DateTaken.Ticks); sw.WriteLine(this.Photographer);

// Finally, write any notes sw.WriteLine(this.Notes.Length);

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

}

5 Create a ReadVersion66 and

ReadVersion83 method to read in the data in the existing formats.

Note: These methods are static

since they create a new Photograph

instance from the data provided by the given stream.

static public Photograph ReadVersion66(StreamReader sr) {

String name = sr.ReadLine();

if (name != null) return new Photograph(name);

else return null;

}

static public Photograph ReadVersion83(StreamReader sr) {

String name = sr.ReadLine();

if (name == null) return null;

Photograph p = new Photograph(name); p.Caption = sr.ReadLine();

Trang 10

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

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

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

encapsu-6 Create a static ReadVersion92

method to read in a Photograph for our new version 92 of an album file.

static public Photograph ReadVersion92(StreamReader sr) {

// Use ReadVer83 for file and caption Photograph p = ReadVersion83(sr);

if (p == null) return null;

// Read date (may throw FormatException) string data = sr.ReadLine();

long ticks = Convert.ToInt64(data); p.DateTaken = new DateTime(ticks);

// Read the photographer p.Photographer = sr.ReadLine();

// Read the notes size data = sr.ReadLine();

int len = Convert.ToInt32(data);

// Read the actual notes characters char[] notesArray = new char[len]; sr.Read(notesArray, 0, len);

p.Notes = new string(notesArray); sr.ReadLine();

return p;

}

7 Create a public delegate to use

when selecting the appropriate reader.

public delegate Photograph ReadDelegate(StreamReader sr);

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

con-c Read the photographer as a string.

d For the notes, read in the number

of characters and use this value to read an equivalent-sized array of characters This array can then be used to create a string.

e After the Notes property is set, a final ReadLine call is required to clear the final line in preparation for reading the next Photograph

object.

Trang 11

UPDATE THE SAVE AND OPEN METHODS IN PHOTOALBUM CLASS

8 In the PhotoAlbum.cs source code

window, set the current version constant to 92.

private const int CurrentVersion = 92;

9 Modify the Save method to use the

new Photograph.Write method.

Note: The initial part of this

method creates the FileStream

and StreamWriter objects This code does not change, and is not shown here.

Similarly, the code for the

finally clause is also not shown.

public void Save(string fileName) {

try { sw.WriteLine(

_CurrentVersion.ToString());

// Store each photo separately foreach (Photograph photo in this) {

photo.Write(sw);

}

this._fileName = fileName;

} finally }

10 Modify the Open method to use the

new ReadDelegate delegate.

public void Open(string fileName) {

try { Clear();

this._fileName = fileName;

Photograph.ReadDelegate ReadPhoto;

11 In the switch statement, select the

correct version of the Photograph

reader.

How-to

Use a new statement to instantiate

a new version of the delegate for each version.

switch (version) {

case 66:

ReadPhoto = new Photograph.ReadDelegate(

Photograph.ReadVersion66); break;

case 83:

ReadPhoto = new Photograph.ReadDelegate(

Photograph.ReadVersion83); break;

case 92:

ReadPhoto = new Photograph.ReadDelegate(

Photograph.ReadVersion92); break;

default:

// Unknown version or bad file throw (new IOException( .)); }

Trang 12

This neat little use of delegates makes our code much more readable A delegateinstance is declared just like any other variable, except that in this case the type is ourdelegate.

ReadPhoto = new Photograph.ReadDelegate(Photograph.ReadVersion92); break;

The delegate is then used like any other function call to invoke the assigned method. // Read each photograph in the album

9.2.2 C REATING THE P HOTO E DIT D LG PANEL AREA

Looking back at the PhotoEditDlg dialog we wish to create, let’s focus on the

Panel control at the top of the form In chapter 7 we made use of the Panel classfor its drawing and scrolling capabilities Here, we will use this class as a containerfor other controls to improve the overall appearance of our form While we will not

12 Use the reader delegate to load the

individual photographs.

Note: The code for the finally

clause remains the same and is not shown here.

// Read each photograph in the album Photograph p = ReadPhoto(sr);

while (p != null) {

this.Add(p);

p = ReadPhoto(sr);

} } finally }

UPDATE THE SAVE AND OPEN METHODS IN PHOTOALBUM CLASS (continued)

Trang 13

enable scrolling in our panel, realize that controls can be placed outside of the visibleportion of a panel and made accessible via the automated scroll bars discussed inchapter 7.

We have used the Label and TextBox controls previously in our program, solet’s update our panel before we talk about these classes in more detail As you recall,the Panel object is inherited from the base form, but is modifiable by our class since

it has a protected access level

CREATE THE PANEL AREA OF THE PHOTOEDITDLG FORM

1 In the PhotoEditDlg.cs [Design] window,

modify the Text property for the new dialog to be “Photo Properties.”

2 Add the four Label controls to the left

side of the panel, as shown in the graphic

Resize the panel control if necessary Set the properties for each label as shown.

Note: In this step you are placing the

con-trols inside the Panel , rather than inside the Form This is an important distinction

Settings Label Property Value

label1 Text Photo &File:

TextAlign MiddleRight label2 Text Cap&tion:

TextAlign MiddleRight label3 Text &Date Taken:

TextAlign MiddleRight label4 Text &Photographer:

TextAlign MiddleRight

Trang 14

Note that the labels and text boxes here are defined within the Panel control, ratherthan within the form In the InitializeComponent method, the controls areadded to the Panel object much like we have seen other controls added to the Form

class in previous chapters

this.panel1.Controls.AddRange(new System.Windows.Forms.Control[] { this.txtPhotographer,

3 Add the four TextBox controls to the right

side of the panel Position and size these controls as in the graphic, and use the following properties.

Note: The txtPhotoFile text box plays a gray background to indicate it is read-only.

dis-4 Set the tab order for these new controls.

How-to

In the tab order view of the page, click controls within the panel in order Press the Esc key when finished.

Note: As you can see in the graphic, the

controls within the panel are numbered to indicate both the tab index of the panel and of the specific control.

CREATE THE PANEL AREA OF THE PHOTOEDITDLG FORM

Settings TextBox Property Value

Photo File (Name) txtPhotoFile

ReadOnly True Text

Caption (Name) txtCaption

Text Date (Name) txtDate

Text Photographer (Name) txtPhotographer

Text

Trang 15

The setting of the tab order in the final step, which internally assigns the TabIndex

property for each control, is very important here We could have set these valuesexplicitly in steps 2 and 3, but the method in step 4 allowed us to set all controls atonce Since the Label and TextBox controls are located within the Panel object,the tab order defined applies only within the panel, so the TabIndex values for ourlabels and text boxes start at zero

While label controls do not participate in the tab order, their TabIndex setting

is still utilized When you tab to or activate a label, the next control in the tab orderwill receive focus This is the same behavior provided by the MFC CStatic class inVisual C++

.NET Table 9.1 Label class

The Label class is a control that displays a text string or image within a form This class is part of the of the System.Windows.Forms namespace, and inherits from the Control class

A Label object can be assigned a tab index, but when activated the next control in the tab order will always receive focus See NET Table 4.1 on page 104 for a list of members inher- ited from the Control class.

Public Properties

AutoSize Gets or sets whether the label should

automatically resize to display its contents BorderStyle Gets or sets the border for the label, taken from

the BorderStyle enumeration The default is

None FlatStyle Gets or sets the flat style for the label, using the

FlatStyle enumeration The default is

Standard Image Gets or sets the image to appear on the label ImageList Gets or sets an ImageList object to associate

with the label The ImageIndex property determines which image is displayed on the label.

PreferredHeight Gets the height of the control, in pixels,

assuming a single line of text is displayed PreferredWidth Gets the width of the control, in pixels, assuming

a single line of text is displayed.

TextAlign Gets or sets the text alignment to use for text in

the control.

UseMnemonic Gets or sets whether an ampersand (&) in the

Text property is interpreted as an access key prefix character.

Trang 16

This tab order behavior is especially relevant for the assigned access key, alsocalled a mnemonic For example, the ampersand character “&” in the Photo File labeldefines the ‘F’ character as the access key Typing the keystroke Alt+F sets the focus

to this label When you do this, the txtPhotoFile control actually receives thefocus Similarly, typing Alt+P for the Caption label will set the focus to the txtCap- tion control Such mnemonics are very useful for users, myself included, who prefer

to avoid the mouse and keep their fingers on the keyboard

Labels include other features as well, of course As we saw in chapter 8, they candisplay a border and define an alignment for displayed text These and other features

of the Label class are summarized in NET Table 9.1 The Label class is also theparent of the LinkLabel class, which adds the ability to perform an action when thetext on the label is clicked, similar to an HTML link in a web browser We will usethe LinkLabel class in chapter 18 while discussing how to include ActiveX controls

on a form

We will use Label objects again in future sections For now, let’s move on to cuss some of the features of our TextBox controls, and the TextBox class in general

The TextBox controls on our form are used to display various properties of the

Photograph object We have already created the text box controls within the panelarea In this section we create the text box for displaying the Photograph.Notes

property in our dialog, and implement the protected members we defined in our baseclass earlier in the chapter

As we saw in the previous section, text boxes can be editable or read-only In someways a read-only text box is similar to a Label object with a 3D border The majordifference is that a text box supports cut and paste operations, while a label does not.The existing CaptionDlg form in our application used a 3D label to illustrate thispoint, so you can verify this for yourself if you prefer

As a result, a read-only TextBox should be used when displaying text that a usermay wish to copy This, in fact, is why our PhotoEditDlg form uses a read-only

TextBox to display the photograph’s file name

The TextBox class is based on the TextBoxBase class, which provides much ofthe core functionality for text controls An overview of this base class appears in NETTable 9.2

Trang 17

As shown in the table, the TextBoxBase class provides a Multiline property thatindicates whether a derived control can accept multiple lines of text The bottom part

of our PhotoEditDlg form is designed to show off such a text box This control

.NET Table 9.2 TextBoxBase class

The TextBoxBase class is a control that displays editable text and can interact with the

Clipboard class to permit cut and paste operations This class is part of the of the tem.Windows.Forms namespace, and inherits from the Control class Both the TextBox

Sys-and RichTextBox classes are derived from this abstract class See NET Table 4.1 on page

104 for a list of members inherited from the Control class, and NET Table 9.3 on page 288 for an overview of the TextBox class.

Public Properties

AcceptsTab Gets or sets whether a multiline text box displays a Tab

character or moves focus to the next control when the Tab key is pressed.

CanUndo Gets or sets whether the user can undo the previous edit

performed in the text box.

Lines Gets or sets the array of strings representing the lines of

text in the control.

MaxLength Gets or sets the maximum number of characters the control

will accept.

Multiline Gets or sets whether this is a multiline text box.

ReadOnly Gets or sets whether the text is read-only.

SelectedText Gets or sets the currently selected text in the control The

SelectedStart property indicates the location of the first selected character.

WordWrap Gets or sets whether a multiline control automatically

wraps to the next line as required.

Public Methods

AppendText Appends a string to the existing text in the control.

Copy Copies the current text into the Clipboard Paste Replaces the current selection with the contents of the

Clipboard.

ScrollToCaret Ensures the current caret position is visible in a multiline

text box.

SelectAll Selects all text in the control The Select method can be

used to select a substring.

Undo Undoes the last edit operation in the text box.

Public Events

Changed

AcceptsTab-Occurs when the AcceptsTab property changes.

Changed

Multiline-Occurs when the Multiline property changes.

Trang 18

displays descriptive text about the photo, and automatically scrolls if the textbecomes too long The following steps add this control to our dialog:

Our form is now ready, except for the internal logic to process the user’s changes.Since our dialog is intended to edit a Photograph object within a PhotoAlbum

collection, we need a reference to the associated PhotoAlbum object within the log We should also implement the methods necessary to handle the OK and Resetbuttons, namely the ResetSettings and SaveSettings methods provided by the

dia-BaseEditDlg class

The following steps detail these changes:

ADD A MULTILINE T EXTBOX TO THE PHOTOEDITDLG FORM

1 Add the Notes label to the

PhotoEditDlg form in the PhotoEditDlg.cs [Design]

window

The AutoSize property causes the label to resize to exactly fit its Text value.

2 Add the multiline TextBox

control to the form.

Note: The Multiline property must be set to true

before the control can be resized to contain multiple lines

of text.

The AcceptsReturn property causes the control to treat an Enter key as a new line rather than allowing the parent form to invoke the OK button.

Settings

Property Value

AutoSize True TabIndex 4 Text Notes:

Settings Property Value

(Name) txtNotes AcceptsReturn True Multiline True ScrollBars Vertical TabIndex 5 Text

Trang 19

Our dialog is complete, at least for now Applications can use it to display and modifyinformation about a photograph The one exception is the date a photograph wastaken While it is certainly possible to convert a string provided by the user into a

DateTime structure, this is not really the best way to specify a date on a form Instead,the DateTimePicker control is provided especially for this purpose We will look atthis control in chapter 11, and simply ignore the value of txtDate for now

The next step is to use this new dialog in our main application This is the topic

of the next section

INTERACTING WITH THE PHOTOALBUM OBJECT

3 In the PhotoEditDlg.cs file add a

private PhotoAlbum variable to hold the album containing the photo to display.

private PhotoAlbum _album;

4 Modify the constructor to accept

a PhotoAlbum parameter.

public PhotoEditDlg(PhotoAlbum album)

{

5 Within the constructor, set the

album variable and call

ResetSettings to initialize the dialog’s controls.

// This call is required InitializeComponent();

// Initialize the dialog settings _album = album;

ResetSettings();

}

6 Implement the ResetSettings

method to set the controls to their corresponding settings in the current photograph.

protected override void ResetSettings() {

Photograph photo = _album.CurrentPhoto;

if (photo != null) {

txtPhotoFile.Text = photo.FileName;

txtCaption.Text = photo.Caption;

txtDate.Text = photo.DateTaken.ToString();

txtPhotographer.Text = photo.Photographer; this.txtNotes.Text = photo.Notes;

} }

7 Implement SaveSettings to

save the contents of the form to the current photograph.

Note: Here, the settings are

always stored successfully, so this method always returns

photo.Caption = txtCaption.Text;

// Ignore txtDate setting for now photo.Photographer = txtPhotographer.Text; photo.Notes = txtNotes.Text;

}

return true;

}

Trang 20

9.2.4 A DDING P HOTO E DIT D LG TO OUR MAIN FORM

Now that our new dialog is ready, we need to display it in our MyPhotos application.This section integrates the dialog into our application, much like we integrated the

CaptionDlg form in chapter 8

The CaptionDlg form does present a slight problem, in that it already allowsthe caption to be edited, just like our new PhotoEditDlg form We could keep thisdialog around and provide two ways to edit a photograph’s caption This might be alittle confusing to users, so we will instead remove CaptionDlg from our application.The step to remove this dialog follows We will integrate the PhotoEditDlg dia-log into our application in a moment

Set the version number of the MyPhotos application to 9.2.

With the caption dialog gone, our way is clear to display the PhotoEditDlg formfrom our main window We will reuse the menuCaption menu for this purpose,renamed and revamped by the following steps:

REMOVE THE CAPTIONDLG FORM

1 In the Solution Explorer window, delete

the CaptionDlg form.

Alternately

Click on the file and press the Delete key.

After clicking OK, the CaptionDlg.cs class is removed from the project and deleted from the file system.

How-to

a Right-click on the CaptionDlg.cs file.

b Select Delete from the popup menu.

c Click OK in the confirmation box.

Trang 21

Since the dialog itself handles the initialization and storage of any changes made by theuser, and the using statement disposes of the dialog when we are finished, there is notmuch work required by our handler When the user clicks OK, we mark that thealbum has changed and update the status bar with any new caption entered by the user.

DISPLAY THE PHOTOEDITDLG FORM FROM THE MAIN WINDOW

2 Double-click the MainForm.cs file in

the Solution Explorer window.

The Windows Forms Designer window appears for this form.

3 Modify the properties for the Caption

menu item under the Edit menu.

Note: We could elect to use this

menu under its previous name This could prove confusing in the future, so

we instead rename the control in line with its new purpose.

4 Rename the Click event for this

menu to menuPhotoProp_Click

5 Replace the old handler with an

implementation to display the

if (_album.CurrentPhoto == null) return;

using (PhotoEditDlg dlg = new PhotoEditDlg(_album)) {

if (dlg.ShowDialog() == DialogResult.OK) {

_bAlbumChanged = true;

sbpnlFileName.Text = _album.CurrentPhoto.Caption; statusBar1.Invalidate();

} } }

6 Update the Popup event handler for

the Edit menu to use the new menu.

private void menuEdit_Popup (object sender, System.EventArgs e) {

menuPhotoProp.Enabled

= (_album.Count > 0);

}

Settings Property Value

(Name) menuPhotoProp Text &Photo

Properties…

Trang 22

So let’s see if your code actually works Compile and run the application and open

a previously saved album file Display the Photo Properties dialog Note in particularthe following features:

The differences between the read-only and editable text boxes

Label text cannot be highlighted, while text within text boxes can, even whenread-only

Use the access key for a label and notice how the following text box receivesfocus

Press the Enter key while editing a single-line text box The dialog behaves as ifyou had clicked the OK button

Press the Enter key while editing within the Notes text box Since we set the

AcceptsReturn property to true, this adds a new line within the Notes boxand does not deactivate the window

Right-click on any text box The default context menu will appear This text menu contains various commands for editing text, and is shown infigure 9.3 The items in this menu correspond to methods in the TextBox- Base class, as shown in NET Table 9.2

con-While our form is working just fine, there are some features missing that might makeour dialog a little more friendly These are the subject of the next section

9.2.5 U SING T EXT B OX CONTROLS

So let’s add some interesting features to our text boxes Most of the events for Box controls are inherited from the Control and TextBoxBase classes Members

Text-Figure 9.3 The standard context menu for Text- Box controls, shown here for the Date Taken text box, disables commands that are not currently available.

Trang 23

specific to the TextBox class appear in NET Table 9.3 Here we will look moreclosely at the KeyPress event and the TextChanged event.

The keyboard events inherited from the Control class are especially interesting,and consist of the KeyDown, KeyPress, and KeyUp events These events are inheritedfrom the Control class, and occur when a key on the keyboard is pushed down andreleased while the control has focus The KeyDown event occurs when the key is firstpressed The KeyPress event activates while the key is held down and repeats whilethe key remains held down The KeyUp event occurs when the key is released Theseevents can be used to fine-tune your interfaces as the user types on the keyboard

We will look at the keyboard events in more detail in chapter 12, but let’s do a quickexample here Suppose we wanted the Caption property to only contain letters ornumbers No punctuation characters and no symbols The KeyPress event receiveskeyboard characters as they are typed, and allows the event handler to handle orignore them The KeyPressEventArgs class is used with this event, and provides a

KeyChar property to get the character pressed, and a Handled property to get or setwhether the character has been handled If Handled is set to true, then the controlwill not receive the character

The obvious, albeit incorrect, way to implement such a handler would be as follows: private void txtCaption_KeyPress(object sender, KeyPressEventArgs e) {

.NET Table 9.3 TextBox class

The TextBox class represents a TextBoxBase control that displays a single font This control

is part of the System.Windows.Forms namespace, and inherits from the TextBoxBase trol Through its parent class, text boxes can support single or multiple lines, and interact with the clipboard to cut, copy, or paste text.

con-Public Properties

AcceptsReturn Gets or sets whether the Enter key in a multiline

text box adds a new line of text or activates the default button for the form.

CharacterCasing Gets or sets how the control modifies the case

of entered characters This can be used to display all uppercase or lowercase letters in the text box.

PasswordChar Gets or sets the character used to mask the text

display in the control When this property is set, cutting or copying to the clipboard is disabled ScrollBars Gets or sets which scrollbars should appear in a

multiline text box.

TextAlign Gets or sets how displayed text is aligned within

the control.

Public Events TextAlignChanged Occurs when the TextAlign property has

changed.

Trang 24

// Ignore all non-alphanumerics – not our approach

e.Handled = !(Char.IsLetter(c) || Char.IsDigit(c));

}

This implementation uses members of the System.Char class to see if the category

of the character is a letter or number It may look good, but it also causes all othercharacters to be ignored by the control, such as spaces and backspaces Clearly, this isnot what we want

Instead, we will allow all control and white space characters past our event handler.This will permit the keyboard shortcuts to work, and also allows spaces in our captions

The caption text box will only receive letters, digits, white space, and all control acters This may or may not be a good idea, by the way, since a caption such as “one-way street” is now not permitted, since the dash ‘-’ is a punctuation character Feelfree to remove this handler if you do not want this behavior in your program.Another feature we could add to our dialog is to display the caption for the pho-tograph in the title bar Of course, this caption can be edited, and we would not wantthe text box and the title bar to display different values

char-The TextChanged event occurs as text is entered, and can be used here to updatethe title bar while the user is typing We could also implement this feature using the

KeyPress event we just saw, but would have to deal with the delete and backspacekeys as well as some text-editing controls The TextChanged approach is a bit morestraightforward

Let’s continue our previous steps and make this change

ADD KEYPRESS EVENT HANDLER FOR TXTCAPTION CONTROL

1 In the PhotoEditDlg.cs Design

window, add a KeyPress event for the txtCaption text box control.

private void txtCaption_KeyPress (object sender, KeyPressEventArgs e) {

2 Implement this handler to only

permit letters and numbers to appear in captions.

char c = e.KeyChar;

e.Handled = !(Char.IsLetterOrDigit(c) || Char.IsWhiteSpace(c)

|| Char.IsControl(c));

}

Trang 25

Compile and run your application to view these new changes Verify that the captioncan contain only letters and numbers, and that the title updates automatically as thecaption is modified.

TRY IT! As an exercise in using some of the methods available to TextBox controls,

see if you can create the standard context menu for text boxes manually andassign it to the Notes control You will need to add a ContextMenu ob-ject to the form and assign it to the txtNotes.ContextMenu property Assigning this property automatically disables the default context menu.Add the eight menu items to the menu, namely Undo, a separator, Copy,Cut, Paste, Delete, another separator, and Select All To make your menudifferent than the standard one, also add a Clear menu item at the end ofthe context menu to clear the text in the box

To process this menu, you will need a Popup event handler for themenu itself to enable or disable the menu items as appropriate You willneed to use the CanUndo, SelectedText, SelectionLength, and Se- lectionStart properties, and the Copy, Cut, Paste, SelectAll, and

Undo methods as part of your implementation

If you run into difficulties, visit the book’s web site and download thecode required for this change

This ends our discussion of Label and TextBox objects for now We will see theseobjects again in the next section and elsewhere in the book Our next topic will createthe Album Properties dialog box as a way to introduce the button classes in the NETFramework

So just what is a button, exactly? For graphical interfaces, a button is a control thatestablishes a specific state, typically some form of on or off Buttons are used to per-form immediate actions in an interface, define the behavior for a specific feature, or

UPDATE TITLE BAR DURING TXTCAPTION MODIFICATION

3 Add a TextChanged event

for the txtCaption text box control.

How-to

This is the default event for text boxes, so you can just double-click the control.

private void txtCaption_TextChanged (object sender, System.EventArgs e) {

4 Modify the title bar to

include the modified text from the control.

this.Text = String.Format(

"{0} - Photo Properties", txtCaption.Text);

}

Ngày đăng: 07/07/2014, 04:20

TỪ KHÓA LIÊN QUAN