- •Using Your Sybex Electronic Book
- •Acknowledgments
- •Contents at a Glance
- •Introduction
- •Who Should Read This Book?
- •How About the Advanced Topics?
- •The Structure of the Book
- •How to Reach the Author
- •The Integrated Development Environment
- •The Start Page
- •Project Types
- •Your First VB Application
- •Making the Application More Robust
- •Making the Application More User-Friendly
- •The IDE Components
- •The IDE Menu
- •The Toolbox Window
- •The Solution Explorer
- •The Properties Window
- •The Output Window
- •The Command Window
- •The Task List Window
- •Environment Options
- •A Few Common Properties
- •A Few Common Events
- •A Few Common Methods
- •Building a Console Application
- •Summary
- •Building a Loan Calculator
- •How the Loan Application Works
- •Designing the User Interface
- •Programming the Loan Application
- •Validating the Data
- •Building a Math Calculator
- •Designing the User Interface
- •Programming the MathCalculator App
- •Adding More Features
- •Exception Handling
- •Taking the LoanCalculator to the Web
- •Working with Multiple Forms
- •Working with Multiple Projects
- •Executable Files
- •Distributing an Application
- •VB.NET at Work: Creating a Windows Installer
- •Finishing the Windows Installer
- •Running the Windows Installer
- •Verifying the Installation
- •Summary
- •Variables
- •Declaring Variables
- •Types of Variables
- •Converting Variable Types
- •User-Defined Data Types
- •Examining Variable Types
- •Why Declare Variables?
- •A Variable’s Scope
- •The Lifetime of a Variable
- •Constants
- •Arrays
- •Declaring Arrays
- •Initializing Arrays
- •Array Limits
- •Multidimensional Arrays
- •Dynamic Arrays
- •Arrays of Arrays
- •Variables as Objects
- •So, What’s an Object?
- •Formatting Numbers
- •Formatting Dates
- •Flow-Control Statements
- •Test Structures
- •Loop Structures
- •Nested Control Structures
- •The Exit Statement
- •Summary
- •Modular Coding
- •Subroutines
- •Functions
- •Arguments
- •Argument-Passing Mechanisms
- •Event-Handler Arguments
- •Passing an Unknown Number of Arguments
- •Named Arguments
- •More Types of Function Return Values
- •Overloading Functions
- •Summary
- •The Appearance of Forms
- •Properties of the Form Control
- •Placing Controls on Forms
- •Setting the TabOrder
- •VB.NET at Work: The Contacts Project
- •Anchoring and Docking
- •Loading and Showing Forms
- •The Startup Form
- •Controlling One Form from within Another
- •Forms vs. Dialog Boxes
- •VB.NET at Work: The MultipleForms Project
- •Designing Menus
- •The Menu Editor
- •Manipulating Menus at Runtime
- •Building Dynamic Forms at Runtime
- •The Form.Controls Collection
- •VB.NET at Work: The DynamicForm Project
- •Creating Event Handlers at Runtime
- •Summary
- •The TextBox Control
- •Basic Properties
- •Text-Manipulation Properties
- •Text-Selection Properties
- •Text-Selection Methods
- •Undoing Edits
- •VB.NET at Work: The TextPad Project
- •Capturing Keystrokes
- •The ListBox, CheckedListBox, and ComboBox Controls
- •Basic Properties
- •The Items Collection
- •VB.NET at Work: The ListDemo Project
- •Searching
- •The ComboBox Control
- •The ScrollBar and TrackBar Controls
- •The ScrollBar Control
- •The TrackBar Control
- •Summary
- •The Common Dialog Controls
- •Using the Common Dialog Controls
- •The Color Dialog Box
- •The Font Dialog Box
- •The Open and Save As Dialog Boxes
- •The Print Dialog Box
- •The RichTextBox Control
- •The RTF Language
- •Methods
- •Advanced Editing Features
- •Cutting and Pasting
- •Searching in a RichTextBox Control
- •Formatting URLs
- •VB.NET at Work: The RTFPad Project
- •Summary
- •What Is a Class?
- •Building the Minimal Class
- •Adding Code to the Minimal Class
- •Property Procedures
- •Customizing Default Members
- •Custom Enumerations
- •Using the SimpleClass in Other Projects
- •Firing Events
- •Shared Properties
- •Parsing a Filename String
- •Reusing the StringTools Class
- •Encapsulation and Abstraction
- •Inheritance
- •Inheriting Existing Classes
- •Polymorphism
- •The Shape Class
- •Object Constructors and Destructors
- •Instance and Shared Methods
- •Who Can Inherit What?
- •Parent Class Keywords
- •Derived Class Keyword
- •Parent Class Member Keywords
- •Derived Class Member Keyword
- •MyBase and MyClass
- •Summary
- •On Designing Windows Controls
- •Enhancing Existing Controls
- •Building the FocusedTextBox Control
- •Building Compound Controls
- •VB.NET at Work: The ColorEdit Control
- •VB.NET at Work: The Label3D Control
- •Raising Events
- •Using the Custom Control in Other Projects
- •VB.NET at Work: The Alarm Control
- •Designing Irregularly Shaped Controls
- •Designing Owner-Drawn Menus
- •Designing Owner-Drawn ListBox Controls
- •Using ActiveX Controls
- •Summary
- •Programming Word
- •Objects That Represent Text
- •The Documents Collection and the Document Object
- •Spell-Checking Documents
- •Programming Excel
- •The Worksheets Collection and the Worksheet Object
- •The Range Object
- •Using Excel as a Math Parser
- •Programming Outlook
- •Retrieving Information
- •Recursive Scanning of the Contacts Folder
- •Summary
- •Advanced Array Topics
- •Sorting Arrays
- •Searching Arrays
- •Other Array Operations
- •Array Limitations
- •The ArrayList Collection
- •Creating an ArrayList
- •Adding and Removing Items
- •The HashTable Collection
- •VB.NET at Work: The WordFrequencies Project
- •The SortedList Class
- •The IEnumerator and IComparer Interfaces
- •Enumerating Collections
- •Custom Sorting
- •Custom Sorting of a SortedList
- •The Serialization Class
- •Serializing Individual Objects
- •Serializing a Collection
- •Deserializing Objects
- •Summary
- •Handling Strings and Characters
- •The Char Class
- •The String Class
- •The StringBuilder Class
- •VB.NET at Work: The StringReversal Project
- •VB.NET at Work: The CountWords Project
- •Handling Dates
- •The DateTime Class
- •The TimeSpan Class
- •VB.NET at Work: Timing Operations
- •Summary
- •Accessing Folders and Files
- •The Directory Class
- •The File Class
- •The DirectoryInfo Class
- •The FileInfo Class
- •The Path Class
- •VB.NET at Work: The CustomExplorer Project
- •Accessing Files
- •The FileStream Object
- •The StreamWriter Object
- •The StreamReader Object
- •Sending Data to a File
- •The BinaryWriter Object
- •The BinaryReader Object
- •VB.NET at Work: The RecordSave Project
- •The FileSystemWatcher Component
- •Properties
- •Events
- •VB.NET at Work: The FileSystemWatcher Project
- •Summary
- •Displaying Images
- •The Image Object
- •Exchanging Images through the Clipboard
- •Drawing with GDI+
- •The Basic Drawing Objects
- •Drawing Shapes
- •Drawing Methods
- •Gradients
- •Coordinate Transformations
- •Specifying Transformations
- •VB.NET at Work: Plotting Functions
- •Bitmaps
- •Specifying Colors
- •Defining Colors
- •Processing Bitmaps
- •Summary
- •The Printing Objects
- •PrintDocument
- •PrintDialog
- •PageSetupDialog
- •PrintPreviewDialog
- •PrintPreviewControl
- •Printer and Page Properties
- •Page Geometry
- •Printing Examples
- •Printing Tabular Data
- •Printing Plain Text
- •Printing Bitmaps
- •Using the PrintPreviewControl
- •Summary
- •Examining the Advanced Controls
- •How Tree Structures Work
- •The ImageList Control
- •The TreeView Control
- •Adding New Items at Design Time
- •Adding New Items at Runtime
- •Assigning Images to Nodes
- •Scanning the TreeView Control
- •The ListView Control
- •The Columns Collection
- •The ListItem Object
- •The Items Collection
- •The SubItems Collection
- •Summary
- •Types of Errors
- •Design-Time Errors
- •Runtime Errors
- •Logic Errors
- •Exceptions and Structured Exception Handling
- •Studying an Exception
- •Getting a Handle on this Exception
- •Finally (!)
- •Customizing Exception Handling
- •Throwing Your Own Exceptions
- •Debugging
- •Breakpoints
- •Stepping Through
- •The Local and Watch Windows
- •Summary
- •Basic Concepts
- •Recursion in Real Life
- •A Simple Example
- •Recursion by Mistake
- •Scanning Folders Recursively
- •Describing a Recursive Procedure
- •Translating the Description to Code
- •The Stack Mechanism
- •Stack Defined
- •Recursive Programming and the Stack
- •Passing Arguments through the Stack
- •Special Issues in Recursive Programming
- •Knowing When to Use Recursive Programming
- •Summary
- •MDI Applications: The Basics
- •Building an MDI Application
- •Built-In Capabilities of MDI Applications
- •Accessing Child Forms
- •Ending an MDI Application
- •A Scrollable PictureBox
- •Summary
- •What Is a Database?
- •Relational Databases
- •Exploring the Northwind Database
- •Exploring the Pubs Database
- •Understanding Relations
- •The Server Explorer
- •Working with Tables
- •Relationships, Indices, and Constraints
- •Structured Query Language
- •Executing SQL Statements
- •Selection Queries
- •Calculated Fields
- •SQL Joins
- •Action Queries
- •The Query Builder
- •The Query Builder Interface
- •SQL at Work: Calculating Sums
- •SQL at Work: Counting Rows
- •Limiting the Selection
- •Parameterized Queries
- •Calculated Columns
- •Specifying Left, Right, and Inner Joins
- •Stored Procedures
- •Summary
- •How About XML?
- •Creating a DataSet
- •The DataGrid Control
- •Data Binding
- •VB.NET at Work: The ViewEditCustomers Project
- •Binding Complex Controls
- •Programming the DataAdapter Object
- •The Command Objects
- •The Command and DataReader Objects
- •VB.NET at Work: The DataReader Project
- •VB.NET at Work: The StoredProcedure Project
- •Summary
- •The Structure of a DataSet
- •Navigating the Tables of a DataSet
- •Updating DataSets
- •The DataForm Wizard
- •Handling Identity Fields
- •Transactions
- •Performing Update Operations
- •Updating Tables Manually
- •Building and Using Custom DataSets
- •Summary
- •An HTML Primer
- •HTML Code Elements
- •Server-Client Interaction
- •The Structure of HTML Documents
- •URLs and Hyperlinks
- •The Basic HTML Tags
- •Inserting Graphics
- •Tables
- •Forms and Controls
- •Processing Requests on the Server
- •Building a Web Application
- •Interacting with a Web Application
- •Maintaining State
- •The Web Controls
- •The ASP.NET Objects
- •The Page Object
- •The Response Object
- •The Request Object
- •The Server Object
- •Using Cookies
- •Handling Multiple Forms in Web Applications
- •Summary
- •The Data-Bound Web Controls
- •Simple Data Binding
- •Binding to DataSets
- •Is It a Grid, or a Table?
- •Getting Orders on the Web
- •The Forms of the ProductSearch Application
- •Paging Large DataSets
- •Customizing the Appearance of the DataGrid Control
- •Programming the Select Button
- •Summary
- •How to Serve the Web
- •Building a Web Service
- •Consuming the Web Service
- •Maintaining State in Web Services
- •A Data-Driven Web Service
- •Consuming the Products Web Service in VB
- •Summary
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 |