Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
(ebook) Visual Studio .NET Mastering Visual Basic.pdf
Скачиваний:
120
Добавлен:
17.08.2013
Размер:
15.38 Mб
Скачать

860 Chapter 19 THE MULTIPLE DOCUMENT INTERFACE

Even if the user closes the MDI form, the Closing event for each child form will be fired, and the same handler will take care of the closing of all documents.

A Scrollable PictureBox

One of the shortcomings of earlier versions of Visual Basic was that you couldn’t attach scroll bars to large forms. This is no longer a problem because the new Windows Form Designer automatically attaches scroll bars when the form is resized below a minimum size. Many developers were wishing the PictureBox had its own scroll bars to handle large images, but this is not the case. The PictureBox control can’t be scrolled. In this section, we’re going to build a scrollable PictureBox control using the techniques discussed so far.

The scrollable PictureBox isn’t a new control; it’s not even a PictureBox with its own scroll bars. It’s a child form filled with a PictureBox control. The size of the PictureBox is determined by the user at runtime, but if it gets smaller than the size of the image, the scroll bars will be attached automatically. This is a feature of the Form object, and child forms support it, because they inherit the Windows.Forms.Form class. Figure 19.11 shows a child form with an image and the appropriate scroll bars attached to it. From a user’s point of view, it looks just like a PictureBox with scroll bars.

Figure 19.11

Using an MDI form to simulate a scrolling PictureBox control

The form shown in Figure 19.11 belongs to the ScrollingPictureBox project, which you’ll find in this chapter’s folder on the CD. This project is an MDI application that uses child forms to display images. To implement the scrolling form, follow these steps:

1. Start a new project.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

A SCROLLABLE PICTUREBOX 861

2.Rename the form to MDIImage and set its IsMdiContainer property to True.

3.Add a child form to the project with the Project Add Windows Form command. Set the child form’s Name property to ImageForm and its caption (property Text) to “Untitled.”

4.Add an instance of the MainMenu control to the parent form and create the menu structure shown in Table 19.4.

5.Switch to the child form, add an instance of the MainMenu control to this form as well, and create the menu structure shown in Table 19.5.

Table 19.4: The Captions and Names of the Parent Form’s Menu

Caption

Name

File

FileMenu

New Image

FileNew

Exit

FileExit

Window

WindowMenu

Title Horizontally

WindowTileH

Tile Vertically

WindowTileV

Cascade

WindowCascade

Arrange Icons

WindowArrange

 

 

Table 19.5: The Captions and Names of the Child Form’s Menu

Caption

Name

File

FileMenu

Load

FileLoad

Close

FileClose

-

 

Zoom

ZoomMenu

Auto

ZoomAuto

200%

Zoom200

100%

Zoom100

75%

Zoom75

50%

Zoom50

25%

Zoom25

Continued on next page

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

862 Chapter 19 THE MULTIPLE DOCUMENT INTERFACE

Table 19.5: The Captions and Names of the Child Form’s Menu (continued)

Caption

Name

Image

ImageMenu

Rotate Left

ImageRotateLeft

Rotate Right

ImageRotateRight

Flip Horizontal

ImageFlipH

Flip Vertical

ImageFlipV

6.Enter the following code behind the New command of the parent form’s menu. This command creates a new child form and displays it on the MDI form, but doesn’t load an image.

Private Sub FileNew_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles FileNew.Click Dim childForm As New Form3()

childForm.MDIParent = Me childForm.show()

End Sub

This code opens another child form. Initially, the child form is empty, and it has the initial size of the child form you specified at design time. Your next step is to add the code behind the Load command, which loads an image to the active child form.

7.Add an instance of the OpenFileDialog control on the main form, and enter the statements shown in Listing 19.16 to the handler of the Click event of the Load command.

Listing 19.16: Loading a New Image

Private Sub FileLoad_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles FileLoad.Click Dim imgFile As String

OpenFileDialog1.Filter = “Images|*.jpg;*.tif” OpenFileDialog1.ShowDialog()

imgFile = OpenFileDialog1.FileName PictureBox1.Image = Image.FromFile(imgFile) PictureBox1.Width = PictureBox1.Image.Width PictureBox1.Height = PictureBox1.Image.Height Me.ZoomMenu.Enabled = True Me.ProcessMenu.Enabled = True Me.PrintMenu.Enabled = True

End Sub

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

A SCROLLABLE PICTUREBOX 863

The code resizes the PictureBox control to fit the size of the image it contains in actual size. The child form that hosts the PictureBox isn’t resized, but the proper scroll bars are attached automatically. The user can then change the current magnification with one of the commands of the Zoom menu. Even without the Zoom or the Image menu, you have a functional application that displays multiple images in scrolling PictureBoxes. Each image is displayed in its own window, and all windows are hosted in MDI form.

The project’s code on the CD contains a few more statements that I’ve omitted from Listing 19.16. Each child form contains an invisible ListBox control, where we store information about the image displayed on the form, such as the name and dimensions of the image. Not that you can’t read the dimensions directly from the Image object, but I wanted to demonstrate how to maintain information about each open document. In an SDI application, you’d probably use global variables to store this information. The situation is different with MDI applications, because you must maintain the same information for multiple documents, and an invisible control on the child form is the simplest method. The last command of the Image menu, the Image Properties command, displays the properties stored in the ListBox control in a message box.

To make the application more useful, let’s add the code behind the other menu commands. The Zoom menu contains various zooming factors supported by the application. It’s really trivial to add more factors or prompt the user to supply a value for the image’s magnification level. Every time an option in the Zoom menu is clicked, we must make sure that the selected option is checked (and all other options cleared) and resize the active child form to the specified zooming factor.

All the items of the Zoom menu are serviced by the same procedure, the ZoomImage() subroutine, which is shown in Listing 19.17.

Listing 19.17: The ZoomImage Subroutine

Sub ZoomImage(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles Zoom100.Click, Zoom200.Click, Zoom75.Click, _

Zoom50.Click, Zoom25.Click

UncheckZoomMenu()

Me.PictureBox1.Width = PictureBox1.Image.Width * _ Val(CType(sender, MenuItem).Text) / 100

Me.PictureBox1.Height = PictureBox1.Image.Height * _ Val(CType(sender, MenuItem).Text) / 100

ImageInfo.Items.Item(3) = Val(sender.text) / 100 CType(sender, MenuItem).Checked = True

End Sub

Notice that the ZoomImage() subroutine handles multiple menu items. To find out which command was selected, the code picks up the caption of the item that was clicked with the Sender.Text expression, retrieves its numeric value (50 for 50 percent, 25 for 25 percent, and so on), and uses the value to resize the image on the child form. For more information on writing event handlers for multiple menu items see Chapter 5.

The Auto option is the most interesting part of the application. This command resizes the PictureBox on the current child form so that the image will fit exactly on it. One of the dimensions of the

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

864 Chapter 19 THE MULTIPLE DOCUMENT INTERFACE

control remains the same, while the other one is resized according to the image’s aspect ratio. The dimension that remains unchanged is the dimension that corresponds to the smaller of the image’s width and height. If the image is taller than it is wide, the width of the image is resized. Otherwise, the code resizes the height of the control. In effect, the image is fit into the child window as best as possible, without introducing any distortion. Before you select the Auto command of the Zoom menu, resize the child form to a comfortable size for the available area. After the execution of the Zoom Auto command, the image will fill either the horizontal or the vertical dimension of the form. You can then change the other dimension with the mouse to view the entire image. Listing 19.18 contains the code behind the Zoom Auto command:

Listing 19.18: The Zoom Auto Command

Private Sub ZoomAuto_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles ZoomAuto.Click If PictureBox1.Image.Width > PictureBox1.Image.Height Then

PictureBox1.Height = Me.Height PictureBox1.Width = PictureBox1.Height * _

(PictureBox1.Image.Width / PictureBox1.Image.Height)

Else

PictureBox1.Height = PictureBox1.Width * _ (PictureBox1.Image.Height / PictureBox1.Image.Width)

End If End Sub

For more information on printing bitmaps, as well as how to resize images and maintain their aspect ratio, see Chapter 15.

The Process menu contains a few simple commands for rotating and flipping the image. All event handlers use the RotateFlip method of the Image object, passing as argument one of the members of the RotateFlipType enumeration. After the image has been rotated, we must also swap the width and height of the corresponding PictureBox control. Listing 19.19 demonstrates the implementations of the Rotate Right and Flip Vertical commands.

Listing 19.19: The Rotate Right and Flip Vertical Commands

Private Sub RotateRight_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles RotateRight.Click

PictureBox1.Image.RotateFlip(RotateFlipType.Rotate90FlipNone)

PictureBox1.Invalidate()

End Sub

Private Sub FlipVertical_Click(ByVal sender As Object, _

ByVal e As System.EventArgs) Handles FlipVertical.Click

PictureBox1.Image.RotateFlip(RotateFlipType.Rotate180FlipX)

PictureBox1.Invalidate()

End Sub

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com