Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning Visual Basic 2005 (2006)

.pdf
Скачиваний:
226
Добавлен:
17.08.2013
Размер:
14.97 Mб
Скачать

Chapter 14

smaller than those used for FillEllipse. This is due to an idiosyncrasy in the way the Windows graphics subsystem works. You’ll often find when working with graphics features that you have to experiment a little!

Public Overrides Sub Draw(ByVal graphics As System.Drawing.Graphics)

If IsFilled = True Then

‘Create a new pen

Dim objSolidBrush As New SolidBrush(Me.Color)

‘Draw the circle graphics.FillEllipse(objSolidBrush, Me.Rectangle)

Else

‘Create a pen

Dim pen As New Pen(Me.Color)

‘Use DrawEllipse instead

Dim objRectangle As Rectangle = Me.Rectangle objRectangle.Inflate(-1, -1) graphics.DrawEllipse(pen, objRectangle)

End If

End Sub

Now that you’ve learned the basics of building user controls that support their own user interface, take a look at the image-handling capabilities in Visual Basic 2005.

Working with Images

The .NET Framework has very good support for loading and saving common image formats. In particular, you’re able to load images of these types:

.bmp: The standard Windows bitmap format

.gif: The standard “lossless” common Internet file format for graphic files and small images

.jpeg or .jpg: The standard “lossy” common Internet file format for photo-quality images

.png: The competitor to .gif that doesn’t have the tricky licensing implications

.tiff: The standard file format for storing and manipulated scanned documents

.wmf/.emf: The standard file formats for saving Windows Metafiles

.ico: The standard file format for program icons

.exif: The preferred file format for storage used internally with digital cameras

Prior to .NET, developers wanting to work with the most common Internet file formats (namely, .gif and .jpeg) had to buy third-party libraries. Now, support is built directly into the .NET Framework, so from day one you can start building applications that can handle these formats. What’s more surprising

466

Programming Custom Graphics

is that the .NET Framework also supports saving these files. This allows you to load a .gif file and save it as, say, a .bmp or .png file. There are two ways in which you can use images with Visual Basic 2005. First, you can use the PictureBox control that you can find in the Visual Studio 2005 Toolbox. This is a control that you place on a form, set a reference to an image, either at design time or runtime and it deals with painting itself. This is a quick way of getting a fixed image on a form. The second way in which you can use images is inside your owner-draw controls. In the following exercise, you’ll see how you can tweak WroxPaint so that, rather than drawing on a dull, white background, you’re actually drawing on an image you load.

Drawing Images

The property on the control takes a System.Drawing.Image object. In addition to using the Image class with PictureBox and a few other controls in the .NET Framework, you can also use it with your own owner-draw controls.

In the next Try It Out, you start by providing a way for your owner-drawn controls to display an image loaded from one of the supported image formats.

Try It Out

Setting the BackgroundImage

1.Open the Designer for Form1. Using the Toolbox drag an OpenFileDialog control onto the form. Set the Name property of the control to dlgFileOpenBackground.

2.Switch to the Code Editor for Form1. You are going to wire up the Open menu item under the File menu to show the Open File dialog box. Select openToolStripMenuItem in the Class Name combo box and then select the Click event in the Method Name combo box. Add the following highlighted code to the Click event handler:

Private Sub openToolStripMenuItem_Click(ByVal sender As Object, _

ByVal e As System.EventArgs) Handles openToolStripMenuItem.Click

‘Set the open file dialog properties With dlgFileOpenBackground

.Filter = “Image files (*.gif,*.jpg,*.jpeg,*.bmp,*.wmf,*.png)” & _ “|*.gif;*.jpg;*.jpeg;*.bmp;*.wmf;*.png|All files (*.*)|*.*”

.FilterIndex = 1

.Title = “Open Picture Files” End With

‘Show the dialog

If dlgFileOpenBackground.ShowDialog() = DialogResult.OK Then

‘Create a new image that references the file Dim backgroundImage As Image = _ Image.FromFile(dlgFileOpenBackground.FileName)

‘Set the background of the canvas Canvas.BackgroundImage = backgroundImage

End If

End Sub

467

Chapter 14

3.Run the project. Select File Open from the menu and find a .bmp, .jpg, .jpeg, or .gif file somewhere on your computer. (If you try to open a file from the network, you may get a security exception.) The image will be displayed as shown in Figure 14-9.

Figure 14-9

How It Works

If you said, “But I didn’t do anything!” you’re quite right — you didn’t have to write any code to support the background image. By default, the Control class from which UserControl is ultimately derived already supports a BackgroundImage property, and you’ve set this to the image you loaded. Therefore, the base class is dealing with drawing the image.

The loading is actually done with the shared FromFile method on the Image class. This method is the easiest way of loading a file from a disk:

‘Show the dialog

If dlgFileOpenBackground.ShowDialog() = DialogResult.OK Then

‘Create a new image that references the file Dim backgroundImage As Image = _ Image.FromFile(dlgFileOpenBackground.FileName)

‘Set the background of the canvas Canvas.BackgroundImage = backgroundImage

End If

Finally, when you’re actually drawing on the image, you may find the paint process sluggish. This is because the control is spending a lot of time drawing the image onto the control, and this slows everything down. Try using a smaller image, or consider this Try It Out an illustration of how to manipulate images rather than a neat paint package!

468

Programming Custom Graphics

Scaling Images

If you resize the form, you’ll notice that the image is actually tiled. More importantly, if you make the control too small to accommodate the whole image, the sides of the image are clipped. What you want is for the image to be scaled so that it fits the control exactly. Therefore, in the next Try It Out, you take over control of drawing the background image from the base Control class and provide a new implementation of the BackgroundImage property.

Try It Out

Drawing the Image Yourself

1.Open the Code Editor for PaintCanvas.

2.Rather than adding your code to draw the image to the Paint method, you’re going to work with a different event called OnPaintBackground. This method is called before the Paint method. Add the following highlighted code:

Protected Overrides Sub OnPaintBackground( _

ByVal e As System.Windows.Forms.PaintEventArgs)

‘Paint the invalid region with the background brush Dim backgroundBrush As New SolidBrush(BackColor)

e.Graphics.FillRectangle(backgroundBrush, e.ClipRectangle)

‘Paint the image

If Not BackgroundImage Is Nothing Then

‘Find our client rectangle

Dim clientRectangle As New Rectangle(0, 0, Width, Height)

‘Draw the image

e.Graphics.DrawImage(BackgroundImage, clientRectangle)

End If

End Sub

3.Now select (PaintCanvas Events) in the Class Name combo box and the Resize event in the Method Name combo box. Add the following highlighted code to the Resize event handler:

Private Sub PaintCanvas_Resize(ByVal sender As Object, _

ByVal e As System.EventArgs) Handles Me.Resize

‘Invalidate the control

Me.Invalidate()

End Sub

4.Now run the project again. This time, when you open the image it will appear stretched or shrunken to fit the whole screen and will adjust itself as you resize the form as shown in Figure 14-10.

How It Works

All you’re trying to do is take over the action of drawing the background image. As mentioned before, painting is a two-phase process: First, the background is erased (the PaintBackground event), and second, the control is given the opportunity to paint its user interface (the Paint event).

469

Chapter 14

Figure 14-10

With the BackgroundImage property set, when the base class needs to draw the background, it will automatically draw the image. You should stop it from doing this; otherwise you’ll effectively be drawing the image twice — in other words, it’ll draw the image and then you’ll draw your own image on top of it.

However, you do need to mimic the functionality that erases the background; otherwise things will not work properly. To do this, you create a new SolidBrush that uses the current background color (BackColor) and paint it on the area that’s marked as invalid (ClipRectangle):

Protected Overrides Sub OnPaintBackground( _

ByVal e As System.Windows.Forms.PaintEventArgs)

‘Paint the invalid region with the background brush Dim backgroundBrush As New SolidBrush(BackColor)

e.Graphics.FillRectangle(backgroundBrush, e.ClipRectangle)

After you have painted the background, you then need to draw the image. You can do this easily by using the DrawImage method of the Graphics object. But to stretch the image you need to provide a rectangle that describes the bounds of the image. Once you have that, you give DrawImage both the image and the rectangle, and the image is drawn.

‘Paint the image

If Not BackgroundImage Is Nothing Then

‘Find our client rectangle

Dim clientRectangle As New Rectangle(0, 0, Width, Height)

‘Draw the image

e.Graphics.DrawImage(BackgroundImage, clientRectangle)

End If

End Sub

470

Programming Custom Graphics

Preserving the Aspect Ratio

The problem you have now is that the image is stretched out of shape. Ideally, you want to make the image bigger or smaller while preserving the aspect ratio, which is the ratio between the width and the height, of the image. The aspect ratio describes the ratio between the width and height of the image.

The .NET Framework does not have any support for preserving the aspect ratio when it stretches an image. However, with a little work, you can do this yourself.

Try It Out

Preserving the Aspect Ratio

1.Open the Code Editor for PaintCanvas again. Add the following highlighted code to

OnPaintBackground.

Protected Overrides Sub OnPaintBackground( _

ByVal e As System.Windows.Forms.PaintEventArgs)

‘Paint the invalid region with the background brush Dim backgroundBrush As New SolidBrush(BackColor)

e.Graphics.FillRectangle(backgroundBrush, e.ClipRectangle)

‘Paint the image

If Not BackgroundImage Is Nothing Then

‘Find our client rectangle

Dim clientRectangle As New Rectangle(0, 0, Width, Height)

‘How big is the image?

Dim intImageWidth As Integer = BackgroundImage.Width Dim intImageHeight As Integer = BackgroundImage.Height

‘What’s the aspect ratio? Dim ratio As Double = _

CType(intImageHeight, Double) / CType(intImageWidth, Double)

‘Scale the image

If intImageWidth > clientRectangle.Width Then intImageWidth = clientRectangle.Width intImageHeight = _

CType(CType(intImageWidth, Double) * ratio, Integer)

End If

If intImageHeight > clientRectangle.Height Then intImageHeight = clientRectangle.Height intImageWidth = _

CType(CType(intImageHeight, Double) / ratio, Integer)

End If

‘You need to center the image

Dim pntImageLocation As New Point( _ (clientRectangle.Width / 2) - (intImageWidth / 2), _ (clientRectangle.Height / 2) - (intImageHeight / 2))

Dim sizImageSize As New Size(intImageWidth, intImageHeight)

471

Chapter 14

Dim recImageRectangle As New Rectangle(pntImageLocation, sizImageSize)

‘Draw the image

e.Graphics.DrawImage(BackgroundImage, recImageRectangle)

End If

End Sub

2.Run the project. Now if you load an image, it will scale and preserve the aspect ratio.

How It Works

Preserving the aspect ratio is a bit of rudimentary math coupled with throwing a few rectangles together. The first thing you need to know is how big the area that you have to fit the image into actually is. You call this clientRectangle.

Protected Overrides Sub OnPaintBackground( _

ByVal e As System.Windows.Forms.PaintEventArgs)

‘Paint the invalid region with the background brush Dim backgroundBrush As New SolidBrush(BackColor)

e.Graphics.FillRectangle(backgroundBrush, e.ClipRectangle)

‘Paint the image

If Not BackgroundImage Is Nothing Then

‘Find our client rectangle

Dim clientRectangle As New Rectangle(0, 0, Width, Height)

Next, you need to look at the image itself to see how big it is. You then need to know the aspect ratio. If, for example, you had an aspect ratio of 2:1 (width:height), and you had an image that was 200 pixels wide, you would know that the height had to be 100 pixels. Alternatively, if it were 25 pixels tall, it would be 50 pixels wide.

‘How big is the image?

Dim intImageWidth As Integer = BackgroundImage.Width Dim intImageHeight As Integer = BackgroundImage.Height

‘What’s the aspect ratio? Dim ratio As Double = _

CType(intImageHeight, Double) / CType(intImageWidth, Double)

When you calculate the aspect ratio, you want a floating-point number, so you have to convert the Integer width and height values to Doubles.

Next, you look at the shape of the client area compared to the shape of the image. If the native width of the image (in other words the size before its scaled) is wider than the width of the window, you fix the width of the image as being equal to the width of the client area. Once you’ve done that, you use the aspect ratio to work out how tall the image should be. (Again, you’ve used conversions to Doubles to make sure that the calculations work properly.)

‘Scale the image

If intImageWidth > clientRectangle.Width Then

472

Programming Custom Graphics

intImageWidth = clientRectangle.Width intImageHeight = _

CType(CType(intImageWidth, Double) * ratio, Integer)

End If

Alternatively, if the height of the client area is taller than the height of the image, you need to do the opposite — in other words, fix the height of the image and then work out the width:

If intImageHeight > clientRectangle.Height Then intImageHeight = clientRectangle.Height intImageWidth = _

CType(CType(intImageHeight, Double) / ratio, Integer)

End If

At this point you have an adjusted width and height of the image. When you have that, to start drawing, you need to work out the upper-left corner. To do this, you divide the width of the client area by two to get the exact middle and subtract half of the width of the image from it. This gives you the x coordinate at which drawing should start. Then, you do the same for the height:

‘You need to center the image

Dim pntImageLocation As New Point( _ (clientRectangle.Width / 2) - (intImageWidth / 2), _ (clientRectangle.Height / 2) - (intImageHeight / 2))

Once you have the location, you build a rectangle using the adjusted width and height:

Dim sizImageSize As New Size(intImageWidth, intImageHeight)

Dim recImageRectangle As New Rectangle(pntImageLocation, sizImageSize)

Finally, you use DrawImage to actually draw the image on the screen:

‘Draw the image

e.Graphics.DrawImage(BackgroundImage, recImageRectangle)

End If

End Sub

More Graphics Methods

In this chapter, you have used a few of the graphics features available with the .NET Framework. There are some commonly used methods on the Graphics object that we haven’t touched.

Whenever you have a Graphics object, either when you’re building owner-draw controls or forms, try using these methods:

DrawLine draws a single line between two points.

DrawCurve and DrawClosedCurve draw a curve between a set of points.

DrawArc draws a portion of a circle.

473

Chapter 14

DrawBezier draws a cubic Bezier curve defined by four points.

DrawPie draws a slice of a circle (like a pie chart).

DrawPolygon draws regular and irregular polygons from an array of points.

DrawIcon draws Windows icons.

All of these methods use the Brush, Pen, Point, and Rectangle objects that you’ve seen used throughout this chapter. Each of these methods has an associated Fill method that fills in the shape after it’s drawn it.

Summar y

In this chapter, you looked at how you could build your own user interface on your controls and forms. Previously, you have been able to build your user interface only by plugging other people’s controls together. Here you focused on building controls derived from System.Windows.Forms.UserControl, because you’re interested in building component-based software.

After discussing the difference between vector and raster graphics, you proceeded to build a simple application that allowed the user to draw dots on the screen using the mouse. You then looked at building a separate control that provided the user with a set of colors that they could choose from when drawing. You saw how to use the Color dialog box to add new colors and how to create new colors using the Windows RGB (red, green, blue) color scheme.

Finally, you took a look at the Image class and saw how this could load a variety of file formats, including Windows bitmap, .jpeg, and .gif. You also saw how to scale images and preserve their aspect ratio.

To summarize, you should know how to:

Use the mouse events to capture the current x, y coordinates of the mouse on the screen.

Invalidate only the rectangle that you are working in to prevent screen flicker.

Add and use named system colors as well as custom defined colors using their RGB values.

Use the different graphics tools such as circle and hollow circle.

Load, resize, and preserve the aspect ratio of images.

474

15

Accessing Databases

Most applications manipulate data in some way. Visual Basic 2005 applications often manipulate data that come from relational databases. To do this, your application needs to interface with relational database software such as Microsoft Access, Microsoft SQL Server, Oracle, or Sybase.

Visual Studio 2005 provides the data access tools and wizards to connect to these databases and retrieve and update their data. In this chapter, you will look at some of these tools and wizards and use them to retrieve data from a database.

In Chapter 16, you will concentrate more on writing code directly, which gives you more flexibility and control than relying on Visual Studio 2005 to create it for you. With practice, writing code will also take less time than working through a wizard.

In this chapter, you will:

Learn what a database really is

Examine the SQL SELECT statement

Examine data access components

Examine data binding in Windows Forms

Use the data access wizards in Visual Studio 2005

Note that in order to work through the exercises in this chapter, you will need Microsoft Access 2000 or higher.

What Is a Database?

Basically, a database consists of one or more large complex files that store data in a structured format. The database engine, in your case Microsoft Access, manages the file or files and the data within those files.