Simplifying Drawing and Printing


Many applications draw some graphics, possibly with some user interaction, and then later print the same graphics, perhaps centered and scaled to fit the page.

You can make this process easier if you move all of the program’s drawing code into subroutines that are independent of the drawing or printing surface. These drawing routines should take as a parameter a Graphics object on which to draw. Then it doesn’t matter whether the program passes these routines the Graphics object provided by a PrintPage event handler or a control’s Paint event handler. They can even use a Graphics object generated by the control’s CreateGraphics method.

The DrawGraphics subroutine shown in the following code encapsulates the drawing code used in the previous sections. It takes a Graphics object as a parameter, draws a background on it, and calls DrawBar to draw five hatched rectangles to form a bar chart.

  ' Draw the bar chart with world coordinate bounds (100, 100)-(600, 400). Private Sub DrawGraphics(ByVal gr As Graphics)     ' Draw a rectangle around the chart.     Dim picture_rect As New Rectangle(100, 100, 500, 300)     gr.FillRectangle(Brushes.LightGray, picture_rect)     gr.DrawRectangle(Pens.Black, picture_rect)     ' Draw the values.     Dim x As Integer = 100     DrawBar(gr, x, 200, HatchStyle.BackwardDiagonal)     DrawBar(gr, x, 280, HatchStyle.Vertical)     DrawBar(gr, x, 240, HatchStyle.ForwardDiagonal)     DrawBar(gr, x, 170, HatchStyle.Horizontal)     DrawBar(gr, x, 290, HatchStyle.DiagonalCross) End Sub 

Now the PrintPage event handler and other code can call this subroutine to draw the program’s graphics. The following code shows how a program can use this routine to draw the bar chart on a PictureBox named picCanvas. The control’s Resize event handler invalidates the control, so the Paint event handler can redraw the entire surface. The control’s Paint event handler clears the PictureBox, calls Fit?Picture?ToMargins to fit the bar chart to the PictureBox’s surface (minus a 3-pixel margin), and calls DrawGraphics to draw the bar chart.

  Private Sub picCanvas_Resize(ByVal sender As Object, _  ByVal e As System.EventArgs) Handles picCanvas.Resize     picCanvas.Invalidate() End Sub Private Sub picCanvas_Paint(ByVal sender As Object, _  ByVal e As System.Windows.Forms.PaintEventArgs) Handles picCanvas.Paint     ' Clear the picture.     e.Graphics.Clear(picCanvas.BackColor)     ' This routine draws a bar chart for 5 values     ' in printer coordinates between      ' (100, 100) - (600, 400).      ' Transform the Graphics object to center the results.     Dim picture_rect As New RectangleF(100, 100, 500, 300)     Dim margin_rect As New RectangleF( _         picCanvas.ClientRectangle.X + 3, _         picCanvas.ClientRectangle.Y + 3, _         picCanvas.ClientRectangle.Width - 6, _         picCanvas.ClientRectangle.Height - 6)     FitPictureToMargins(e.Graphics, picture_rect, margin_rect)     ' Draw the bar chart.     DrawGraphics(e.Graphics) End Sub 

Figure 24-7 shows the result.

image from book
Figure 24-7: A program can use subroutine FitPictureToMargins to make a picture fit a PictureBox as well as a printed page.

This technique minimizes the amount of drawing code. It lets the program share the same code for drawing, printing, and print previewing. That means less code to debug and maintain. It also means that you need only to modify the code in one place if you need to change it later.

By calling FitPictureToMargins, the program makes the bar chart fill the PictureBox as much as possible without distorting it. If the control is anchored or docked so that it resizes when the form does, the bar chart also resizes so that it is as big as possible, a fairly impressive feat at the cost of a single subroutine call.

Although very useful, the technique of using a common routine to draw and print graphics is not appropriate for every application. Sometimes a program must take advantage of the particular characteristics of a printer or screen object, and the results may not make sense for other types of devices.

For example, suppose that a program draws fractals by performing time-consuming calculations for each pixel. It may make sense to show the results as the pixels are calculated on the screen. That would take advantage of the fact that the user can immediately see the results of pixels drawn on the screen. On the printer, however, the results aren’t visible until the complete page is printed, so sending pixels to the printer one at a time doesn’t particularly help the user and may slow printing. It might make more sense to draw the complete image on a Bitmap in memory and then send the result to the printer all at once by using the Graphics object’s DrawImage method.

Similarly, the text-printing example described earlier in this chapter prints a long series of paragraphs broken across several pages. It takes advantage of the printed page’s exact size and margins. You might be able to display the same page data in a scrolling window on the screen, but that probably wouldn’t make much sense. In that application, trying to force screen drawing and page printing routines to produce exactly the same result would probably be a waste of time.




Visual Basic 2005 with  .NET 3.0 Programmer's Reference
Visual Basic 2005 with .NET 3.0 Programmer's Reference
ISBN: 470137053
EAN: N/A
Year: 2007
Pages: 417

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net