|
|
Title | Preview and print a core sample report using custom fill patterns with Visual Basic 2005 |
Description | This example shows how to preview and print a core sample report using custom fill patterns with Visual Basic 2005. |
Keywords | print, preview, core sample, VB 2005 |
Categories | VB.NET, Graphics |
|
|
This example displays a core sample report showing various notations at different core depths, together with graphics hilighting different soil types.
The form contains a PrintPreviewDialog control named ppdCoreSample. At design time, its Document property was set to the PrintDocument object pdocCoreSample.
When you click the Preview button, the following code executes. It calls subroutine DefineData to build some sample data. It then sets the PrintPreview dialog's size, sets it to appear maximized, and shows the dialog.
|
|
' Make and display some data.
Private Sub btnPreview_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnPreview.Click
' Define the data.
DefineData()
' Display the preview.
ppdCoreSample.Width = 800
ppdCoreSample.Height = 600
DirectCast(ppdCoreSample, Form).WindowState = _
FormWindowState.Maximized
ppdCoreSample.ShowDialog()
End Sub
|
|
The program stores information aboout a core sample layer in a CoreLayer object. The class's only constructor simply initializes the object's fields.
|
|
Private Class CoreLayer
Public Thickness As Single ' Feet.
Public Recovery As Single ' Shown as a percent.
Public Moisture As String ' d, m, w, or s.
Public Plasticity As Single ' ?
Public PID As Integer ' PPM.
Public FillPicture As Image
Public AstmClass As AstmClassifications
Public Description As String
' Constructor omitted ...
End Class
|
|
The form's imlFillPictures control is an ImageList that contains the patterns used to represent different kinds of soil (clay, sand, and so forth). The images are named after their bitmap files so, for example, imlFillPictures.Images("Silt.bmp") is the image used to represent silt.
Subroutine DefineData uses the images in the imlFillPictures control to initialize an array of CoreLayer objects.
|
|
' Define the data.
Private m_CoreData() As CoreLayer
Private Sub DefineData()
m_CoreData = New CoreLayer() { _
New CoreLayer(0.5, -1, "d", -1, -1, Nothing, _
AstmClassifications.None, "Crushed stone and " & _
"fill."), _
New CoreLayer(2, -1, "d", -1, 4, _
imlFillPictures.Images("Silt.bmp"), _
AstmClassifications.ML, "SILT w/fine sand, not " & _
"hard, crumbly, dark brown, no odor."), _
... others omitted...
}
End Sub
|
|
When the PrintPreviewDialog is displayed, it raises the PrintDocument object's PrintPage event handler shown in the following code to generate printed pages. The code starts by drawing a string in the page's top area. In a real application, this would include information about the sample.
Next the code makes a font and StringFormat object to use while drawing text. It calls subroutine DrawRotatedString, described shortly, to draw header text for each of the report's columns. It passes in X and Y coordinates to position each column header. DrawRotatedString automatically increases the X coordinate (it's passed ByRef) after it draws a header so the next header is moved to the right.
The program draws the ground line. It then loops through the CoreLayer objects, calling subroutine DrawSample for each. It draws depth marks to show the depth every five feet and draws a box around the whole thing.
Finally the code draws some summary text at the bottom. It sets e.HasMorePages = False so the printout ends after this page.
|
|
Private Const COL_WID As Integer = 30
Private Const HEADER_HGT As Integer = 100
Private Const Y_SCALE As Single = 20 ' Pixels per foot
' vertically.
Private Const MAX_FEET As Single = 30
Private Sub pdocCoreSample_PrintPage(ByVal sender As _
System.Object, ByVal e As _
System.Drawing.Printing.PrintPageEventArgs) Handles _
pdocCoreSample.PrintPage
Dim xmin As Integer = e.MarginBounds.Left
Dim xmax As Integer = e.MarginBounds.Right
Dim y As Integer = e.MarginBounds.Top
' Draw top area here.
Using the_font As New Font("Times New Roman", 20, _
FontStyle.Regular)
e.Graphics.DrawString("Top stuff goes here...", _
the_font, Brushes.Black, xmin, y)
' ...
y += 150
End Using
' Draw the core data area.
Dim ymin As Integer = y
Using the_font As New Font("Times New Roman", 10, _
FontStyle.Regular)
Using center_format As New StringFormat()
center_format.Alignment = StringAlignment.Center
center_format.LineAlignment = _
StringAlignment.Center
' Draw column headers.
Dim x As Integer = xmin + COL_WID \ 2
y += HEADER_HGT \ 2
DrawRotatedString(e.Graphics, the_font, _
center_format, x, y, "Depth (feet)")
DrawRotatedString(e.Graphics, the_font, _
center_format, x, y, "Recovery %")
DrawRotatedString(e.Graphics, the_font, _
center_format, x, y, "Moisture")
DrawRotatedString(e.Graphics, the_font, _
center_format, x, y, "Plasticity")
DrawRotatedString(e.Graphics, the_font, _
center_format, x, y, "PID (ppm)")
DrawRotatedString(e.Graphics, the_font, _
center_format, x, y, "Graphic Log")
DrawRotatedString(e.Graphics, the_font, _
center_format, x, y, "ASTM Class.")
y += HEADER_HGT \ 2
e.Graphics.DrawLine(Pens.Black, xmin, y, xmax, _
y)
xmin = e.MarginBounds.Left
Dim y0 As Integer = y + 0.5 * Y_SCALE
y = y0
' Draw the ground line.
Using ground_pen As New Pen(Color.Black)
ground_pen.DashStyle = DashStyle.Custom
ground_pen.DashPattern = New Single() {25, _
25}
e.Graphics.DrawLine(ground_pen, xmin + _
COL_WID, y0, xmax, y0)
End Using
' Draw the ground line's "0".
e.Graphics.DrawString("0", the_font, _
Brushes.Black, xmin + COL_WID \ 2, y, _
center_format)
' Draw sample data.
Dim total_feet As Single = 0
For i As Integer = 0 To m_CoreData.Length - 1
DrawSample(e.Graphics, m_CoreData(i), xmin, _
y, xmax, the_font, center_format, _
total_feet)
Next i
' Draw depth markers.
For i As Integer = 5 To MAX_FEET - 5 Step 5
y = y0 + Y_SCALE * i
e.Graphics.DrawLine(Pens.Black, xmin + _
COL_WID, y, xmin + 2 * COL_WID, y)
e.Graphics.DrawString(i.ToString, the_font, _
Brushes.Black, xmin + COL_WID \ 2, y, _
center_format)
Next i
' Draw lines and a box around everything.
y = y0 + MAX_FEET * Y_SCALE
' Box.
e.Graphics.DrawRectangle(Pens.Black, xmin, _
ymin, xmax - xmin, y - ymin)
' Column lines.
For i As Integer = 1 To 7
x = xmin + COL_WID * i
e.Graphics.DrawLine(Pens.Black, x, ymin, x, _
y)
Next i
End Using
End Using
' Draw bottom area here.
y += 20
Using the_font As New Font("Times New Roman", 20, _
FontStyle.Regular)
e.Graphics.DrawString("Bottom stuff goes here...", _
the_font, Brushes.Black, xmin, y)
' ...
End Using
e.HasMorePages = False
End Sub
|
|
Subroutine DrawRotatedString draws a string rotated 90 degrees. It applies a rotation transformation to the Graphics object to rotate the text 90 degrees and a translation transformation to move the text to its desired location. It then draws the text centered at the origin. The Graphics object's transformations rotate the text and move it to the proper position.
The subroutine resets the Graphics object's transformation to remove the rotation and translation, and it increases the X coordinate so the next column header appears to the right.
|
|
' Draw a string centered at the given position rotated 90
' degrees.
' Increment x by COL_WID.
Private Sub DrawRotatedString(ByVal gr As Graphics, ByVal _
the_font As Font, ByVal center_format As StringFormat, _
ByRef x As Integer, ByVal y As Integer, ByVal txt As _
String)
gr.RotateTransform(-90)
gr.TranslateTransform(x, y, MatrixOrder.Append)
gr.DrawString(txt, the_font, Brushes.Black, 0, 0, _
center_format)
gr.ResetTransform()
x += COL_WID
End Sub
|
|
Subroutine DrawSample draws the data for a CoreLayer object. It draws a line to mark the sample's end depth and draws appropriate text in the sample's columns. The subroutine fills the area in the graphic log column with the custom image assigned to the CoreLayer.
|
|
' Draw a sample.
Private Sub DrawSample(ByVal gr As Graphics, ByVal _
core_data As CoreLayer, ByVal x1 As Integer, ByVal y1 _
As Single, ByVal x2 As Single, ByVal the_font As Font, _
ByVal center_format As StringFormat, ByRef total_feet _
As Single)
' Divider line below.
Dim ymin As Integer = y1 + total_feet * Y_SCALE
Dim ymax As Integer = ymin + core_data.Thickness * _
Y_SCALE
gr.DrawLine(Pens.Black, x1 + COL_WID * 2, ymax, x2, _
ymax)
Dim ymid As Integer = ymin + (core_data.Thickness * _
Y_SCALE) \ 2
Dim xmid As Integer = x1 + COL_WID + COL_WID \ 2
' % Recovery.
If core_data.Recovery >= 0 Then
gr.DrawString(core_data.Recovery.ToString(), _
the_font, Brushes.Black, xmid, ymid, _
center_format)
End If
' Moisture.
xmid += COL_WID
gr.DrawString(core_data.Moisture, _
the_font, Brushes.Black, xmid, ymid, center_format)
' Plasticity.
xmid += COL_WID
If core_data.Plasticity >= 0 Then
gr.DrawString(core_data.Plasticity.ToString(), _
the_font, Brushes.Black, xmid, ymid, _
center_format)
End If
' PID.
xmid += COL_WID
If core_data.PID >= 0 Then
gr.DrawString(core_data.PID.ToString(), _
the_font, Brushes.Black, xmid, ymid, _
center_format)
End If
' Graphic log.
xmid += COL_WID
If core_data.FillPicture IsNot Nothing Then
Using fill_brush As New _
TextureBrush(core_data.FillPicture, _
WrapMode.Tile)
Dim xmin As Integer = x1 + 5 * COL_WID
gr.FillRectangle(fill_brush, xmin, ymin, _
COL_WID, ymax - ymin)
gr.DrawRectangle(Pens.Black, xmin, ymin, _
COL_WID, ymax - ymin)
End Using
End If
' ASTM classification.
xmid += COL_WID
If core_data.AstmClass <> AstmClassifications.None Then
gr.DrawString(core_data.AstmClass.ToString(), _
the_font, Brushes.Black, xmid, ymid, _
center_format)
End If
' Description.
Using descr_format As New StringFormat()
descr_format.Alignment = StringAlignment.Near
descr_format.LineAlignment = StringAlignment.Center
Dim x As Integer = x1 + 7 * COL_WID + 4
xmid += COL_WID
Dim rect As New Rectangle(x, ymin, x2 - x - 8, ymax _
- ymin)
gr.DrawString(core_data.Description, _
the_font, Brushes.Black, rect, descr_format)
End Using
total_feet += core_data.Thickness
End Sub
|
|
|
|
|
|