GoodsReturnForm.vb
'' '' This code is part of Document Solutions for PDF demos. '' Copyright (c) MESCIUS inc. All rights reserved. '' Imports System.IO Imports System.Drawing Imports GrapeCity.Documents.Common Imports GrapeCity.Documents.Drawing Imports GrapeCity.Documents.Pdf Imports GrapeCity.Documents.Text Imports GrapeCity.Documents.Pdf.Annotations Imports GrapeCity.Documents.Pdf.AcroForms Imports GCTEXT = GrapeCity.Documents.Text Imports GCDRAW = GrapeCity.Documents.Drawing '' Creates a "Goods return or exchange form" AcroForm with multiple input fields And a complex layout. Public Class GoodsReturnForm '' Page margins: Const MarginLeft = 32.0F Const MarginTop = 32.0F Const MarginRight = 32.0F Const MarginBottom = 32.0F '' Const TableCaptionHeight = 20.0F ReadOnly TableSampleHeight As Single = Textbox.Height Const SmallTextVOff As Single = -0.5F '' Section delimiting line: Dim CaptionLineThickness As Single = 2.5F '' Struct to hold a text style: Private Structure TextStyle Public Property Font As GCTEXT.Font Public Property FontSize As Single Public Property ForeColor As Color Public Property GlyphAdvanceFactor As Single End Structure '' Various styles used throughout the form: Shared TsTitle As TextStyle = New TextStyle() With { .Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "LiberationSerif-Bold.ttf")), .FontSize = 30, .ForeColor = Color.FromArgb(&HFF, &H3B, &H5C, &HAA), .GlyphAdvanceFactor = 0.93F } Shared TsCaption As TextStyle = New TextStyle() With { .Font = TsTitle.Font, .FontSize = 14, .ForeColor = Color.FromArgb(&HFF, &H3B, &H5C, &HAA), .GlyphAdvanceFactor = 0.93F } Shared TsBold As TextStyle = New TextStyle() With { .Font = TsTitle.Font, .FontSize = 9, .ForeColor = Color.Black, .GlyphAdvanceFactor = 1 } Shared TsNormal As TextStyle = New TextStyle() With { .Font = GrapeCity.Documents.Text.Font.FromFile(Path.Combine("Resources", "Fonts", "LiberationSans-Regular.ttf")), .FontSize = 8.0F, .ForeColor = Color.Black, .GlyphAdvanceFactor = 0.922F } Shared TsSmall As TextStyle = New TextStyle() With { .Font = TsNormal.Font, .FontSize = 5, .ForeColor = Color.FromArgb(&HF, &HF, &HF), .GlyphAdvanceFactor = 1.1F } '' Input field styles: Private Structure Textbox Public Shared Property Font As GCTEXT.Font = TsNormal.Font Public Shared Property FontSize As Single = 12 Public Shared Property Height As Single Public Shared Property BaselineOffset As Single Public Shared Property LabelSpacing As Single = 2 End Structure Private Structure Checkbox Public Shared Font As GCTEXT.Font = TsNormal.Font Public Shared FontSize As Single = TsNormal.FontSize - 2 Public Shared Height As Single Public Shared BaselineOffset As Single Public Shared LabelSpacing As Single = 3 End Structure '' The document being created: Private _doc As GcPdfDocument '' Insertion point: Private _ip As PointF = New PointF(MarginLeft, MarginTop) '' If non-null, DrawText use this to align text to last baseline: Private _lastBaselineOffset As Single? = Nothing '' Shortcuts to current values: Private ReadOnly Property CurrPageIdx As Integer Get Return _doc.Pages.Count - 1 End Get End Property Private ReadOnly Property CurrPage As Page Get Return _doc.Pages(CurrPageIdx) End Get End Property Private ReadOnly Property CurrGraphics As GcGraphics Get Return CurrPage.Graphics End Get End Property '' Static ctor: Shared Sub New() '' Init Textbox: Dim tl = New TextLayout(72) tl.Append("Qwerty") tl.DefaultFormat.Font = Textbox.Font tl.DefaultFormat.FontSize = Textbox.FontSize tl.PerformLayout(True) Textbox.Height = tl.ContentHeight Textbox.BaselineOffset = tl.Lines(0).GlyphRuns(0).BaselineOffset '' Init Checkbox: tl.Clear() tl.Append("Qwerty") tl.DefaultFormat.Font = Checkbox.Font tl.DefaultFormat.FontSize = Checkbox.FontSize tl.PerformLayout(True) Checkbox.Height = tl.ContentHeight Checkbox.BaselineOffset = tl.Lines(0).GlyphRuns(0).BaselineOffset End Sub '' The main entry point: Function CreatePDF(ByVal stream As Stream) As Integer Acme() _doc.Save(stream) Return _doc.Pages.Count End Function '' Sets or advances the insertion point vertically: Private Sub SetY(ByVal abs As Single?, ByVal offset As Single?) If (abs.HasValue) Then _ip.Y = abs.Value End If If (offset.HasValue) Then _ip.Y += offset.Value End If _lastBaselineOffset = Nothing End Sub '' Creates the PDF form: Private Sub Acme() _doc = New GcPdfDocument() _doc.NewPage() Dim pageWidth = CurrPage.Size.Width '' Main caption: SetY(Nothing, -2) Dim cr = DrawText("ACME Inc.", TsTitle) SetY(Nothing, _lastBaselineOffset - CaptionLineThickness / 2) DrawGreenLine(MarginLeft, cr.Left - CaptionLineThickness) DrawGreenLine(cr.Right + CaptionLineThickness, pageWidth - MarginRight) '' 'return and exchange form': SetY(cr.Bottom, 10) cr = DrawText("Return and Exchange Form", TsCaption) SetY(Nothing, CaptionLineThickness + 14) cr = DrawText("Please type in the appropriate information below, then print this form.", TsBold) _ip.X = pageWidth - 150 cr = DrawText("Have Any Questions?", TsBold) SetY(Nothing, 10) _ip.X = MarginLeft cr = DrawText("(Or you may print the form and complete it by hand.)", TsNormal) _ip.X = pageWidth - 150 cr = DrawText("Please call us at 800-123-4567.", TsNormal) '' Step 1 - line 1: SetY(Nothing, 18) _ip.X = MarginLeft cr = DrawText("Step 1", TsCaption) _ip.X = cr.Right + 10 cr = DrawText("Original Order #", TsBold) _ip.X = cr.Right + 4 cr = DrawText("(if available):", TsNormal) _ip.X = cr.Right + Textbox.LabelSpacing cr = DrawTextbox(120) _ip.X = cr.Right + 6 cr = DrawText("Estimated Order Date:", TsBold) _ip.X = cr.Right + Textbox.LabelSpacing cr = DrawTextbox(pageWidth - MarginRight - _ip.X) SetY(Nothing, 17) DrawGreenLine() '' Step 1 - line 2: SetY(Nothing, 10) _ip.X = MarginLeft cr = DrawText("Originally Purchased by:", TsBold) _ip.X = cr.Right + 20 cr = DrawCheckbox("Address Change") Dim col1right = pageWidth / 2 - 10 Dim col2left = col1right + 20 _ip.X = col2left cr = DrawText("Send Refund or Exchange to:", TsBold) _ip.X = cr.Right + 2 cr = DrawText("(If different from left)", TsNormal) '' Step 1 - line 3: SetY(cr.Bottom, 10) _ip.X = MarginLeft cr = DrawText("Name:", TsNormal) _ip.X = cr.Right + Textbox.LabelSpacing cr = DrawTextbox(col1right - _ip.X) _ip.X = col2left cr = DrawText("Name:", TsNormal) _ip.X = cr.Right + Textbox.LabelSpacing cr = DrawTextbox(pageWidth - MarginRight - _ip.X) '' Step 1 - line 4: SetY(cr.Bottom, 4 + 4) _ip.X = MarginLeft cr = DrawText("Address:", TsNormal) _ip.X = cr.Right + Textbox.LabelSpacing cr = DrawTextbox(col1right - _ip.X) _ip.X = col2left cr = DrawText("Address:", TsNormal) _ip.X = cr.Right + Textbox.LabelSpacing cr = DrawTextbox(pageWidth - MarginRight - _ip.X) '' Step 1 - line 5: SetY(cr.Bottom, 4 + 0.5F) _ip.X = MarginLeft cr = DrawTextbox(col1right - _ip.X) _ip.X = col2left cr = DrawTextbox(pageWidth - MarginRight - _ip.X) '' Step 1 - line 6 (city state zip): SetY(cr.Bottom, 4 + 0.5F) _ip.X = MarginLeft cr = DrawTextbox(160) _ip.X = cr.Right + 4 Dim oState = _ip.X - MarginLeft cr = DrawTextbox(40) _ip.X = cr.Right + 4 Dim oZip = _ip.X - MarginLeft cr = DrawTextbox(col1right - _ip.X) '' _ip.X = col2left cr = DrawTextbox(160) _ip.X = cr.Right + 4 cr = DrawTextbox(40) _ip.X = cr.Right + 4 cr = DrawTextbox(pageWidth - MarginRight - _ip.X) '' small text SetY(cr.Bottom, SmallTextVOff) _ip.X = MarginLeft cr = DrawText("(City)", TsSmall) _ip.X = MarginLeft + oState cr = DrawText("(State)", TsSmall) _ip.X = MarginLeft + oZip cr = DrawText("(Zip)", TsSmall) '' _ip.X = col2left cr = DrawText("(City)", TsSmall) _ip.X = col2left + oState cr = DrawText("(State)", TsSmall) _ip.X = col2left + oZip cr = DrawText("(Zip)", TsSmall) '' Step 1 - line 7 (daytime): SetY(cr.Bottom, 4 - 0.5F) _ip.X = MarginLeft cr = DrawText("Phone: (", TsNormal) _ip.X = cr.Right cr = DrawTextbox(30) _ip.X = cr.Right cr = DrawText(")", TsNormal) _ip.X += 3 cr = DrawTextbox(80) Dim oDay = cr.Left - MarginLeft + 10 '' (evening) _ip.X = cr.Right + 3 cr = DrawText("(", TsNormal) _ip.X = cr.Right cr = DrawTextbox(30) _ip.X = cr.Right cr = DrawText(")", TsNormal) _ip.X += 3 cr = DrawTextbox(col1right - _ip.X) Dim oEve = cr.Left - MarginLeft + 10 '' _ip.X = col2left cr = DrawText("Phone: (", TsNormal) _ip.X = cr.Right cr = DrawTextbox(30) _ip.X = cr.Right cr = DrawText(")", TsNormal) _ip.X += 3 cr = DrawTextbox(80) '' (evening) _ip.X = cr.Right + 3 cr = DrawText("(", TsNormal) _ip.X = cr.Right cr = DrawTextbox(30) _ip.X = cr.Right cr = DrawText(")", TsNormal) _ip.X += 3 cr = DrawTextbox(pageWidth - MarginRight - _ip.X) '' small text SetY(cr.Bottom, SmallTextVOff) _ip.X = MarginLeft + oDay cr = DrawText("(Daytime)", TsSmall) _ip.X = MarginLeft + oEve cr = DrawText("(Evening)", TsSmall) _ip.X = col2left + oDay cr = DrawText("(Daytime)", TsSmall) _ip.X = col2left + oEve cr = DrawText("(Evening)", TsSmall) '' Step 1 - email SetY(cr.Bottom, 4 - 0.5F) _ip.X = MarginLeft cr = DrawText("Email Address:", TsNormal) _ip.X = cr.Right + Textbox.LabelSpacing cr = DrawTextbox(col1right - _ip.X) _ip.X = col2left cr = DrawText("Email Address:", TsNormal) _ip.X = cr.Right + Textbox.LabelSpacing cr = DrawTextbox(pageWidth - MarginRight - _ip.X) '' Options: SetY(Nothing, 16) _ip.X = MarginLeft cr = DrawText("Please select one of the following options:", TsBold) SetY(cr.Bottom, 2) cr = DrawCheckbox("Exchange for another item(s).") SetY(cr.Bottom, 2) cr = DrawCheckbox("Send me an ACME Gift Card for the amount of the refund.") SetY(cr.Bottom, 2) cr = DrawCheckbox("Reimburse my original method of payment. " + "(Gift recipients who select this option will receive a merchandise only gift card.)") '' Step 2 SetY(Nothing, 18) _ip.X = MarginLeft cr = DrawText("Step 2–Returns", TsCaption) _ip.X = cr.Right + 10 cr = DrawText("In the form below please indicate the item(s) you are returning, " + "including a reason code.", TsNormal) SetY(Nothing, 17) DrawGreenLine() SetY(Nothing, 10) cr = DrawReturnsTable() SetY(cr.Bottom, 10) cr = DrawReasonCodes() '' Step 3 SetY(Nothing, 25) _ip.X = MarginLeft cr = DrawText("Step 3–Exchanges", TsCaption) _ip.X = cr.Right + 10 SetY(Nothing, -5) cr = DrawText( "For the fastest service, call Customer Service at 800-123-4567 to request a QuickExchange " + "or place a new order online or by phone. We'll ship your new item right away. " + "Note: If you use our QuickExchange option, you do not need to fill out Step 3.", TsNormal) SetY(Nothing, 22) DrawGreenLine() SetY(Nothing, 10) cr = DrawExchangesTable() '' Step 4 SetY(Nothing, 18) _ip.X = MarginLeft cr = DrawText("Step 4", TsCaption) SetY(Nothing, 17) DrawGreenLine() SetY(Nothing, 10) _ip.X = MarginLeft Dim oCc = col2left - 30 cr = DrawText("Method of Payment:", TsBold) _ip.X = oCc cr = DrawText("Credit Card Information:", TsBold) SetY(cr.Bottom, 2) _ip.X = MarginLeft cr = DrawText("If the total of your exchange or new order exceeds the value of your" + vbCrLf + "return, please provide a method of payment. (Select one)", TsNormal) _ip.X = oCc cr = DrawCheckbox("ACME® Visa®") Dim oCcOff = 90 _ip.X += oCcOff cr = DrawCheckbox("MasterCard®") _ip.X += oCcOff cr = DrawCheckbox("JCB Card™") SetY(cr.Bottom, 2) _ip.X = oCc cr = DrawCheckbox("VISA") _ip.X += oCcOff cr = DrawCheckbox("American Express") _ip.X += oCcOff cr = DrawCheckbox("Discover®/Novus® Cards") SetY(cr.Bottom, 4) _ip.X = MarginLeft cr = DrawCheckbox("Credit Card") SetY(cr.Bottom, 2) cr = DrawCheckbox("Check or Money Order enclosed") SetY(cr.Bottom, 2) cr = DrawCheckbox("Gift Card, Gift Certificate or ACME Visa coupon dollars." + vbCrLf + "Enter # below (for Gift Cards, please include PIN).") _ip.X = oCc cr = DrawText("Card Number:", TsNormal) _ip.X = cr.Right + Textbox.LabelSpacing cr = DrawTextbox(180) _ip.X = cr.Right + 4 cr = DrawTextbox(pageWidth - MarginRight - _ip.X) '' small text SetY(cr.Bottom, SmallTextVOff) _ip.X = cr.Left cr = DrawText("Exp. Date (MM/YY)", TsSmall) SetY(cr.Bottom, 10) _ip.X = MarginLeft cr = DrawText("Number:", TsNormal) _ip.X = cr.Right + Textbox.LabelSpacing cr = DrawTextbox(140) Dim tbBottom = cr.Bottom _ip.X = cr.Right + 4 cr = DrawTextbox(60) Dim oPin = cr.Left _ip.X = oCc cr = DrawText("Signature:", TsNormal) CurrGraphics.DrawLine(New PointF(cr.Right, cr.Bottom), New PointF(pageWidth - MarginRight, cr.Bottom), Color.Black, 0.5F) '' small text SetY(tbBottom, SmallTextVOff) _ip.X = oPin cr = DrawText("PIN", TsSmall) End Sub Private Sub DrawGreenLine(Optional ByVal from_ As Single? = Nothing, Optional ByVal to_ As Single? = Nothing) Dim page = CurrPage If Not from_.HasValue Then from_ = MarginLeft End If If Not to_.HasValue Then to_ = page.Size.Width - MarginRight End If Dim g = page.Graphics Dim pen = New GCDRAW.Pen(TsTitle.ForeColor, CaptionLineThickness) g.DrawLine(New PointF(from_.Value, _ip.Y), New PointF(to_.Value, _ip.Y), pen) End Sub Private Function DrawText(ByVal text As String, ByVal ts As TextStyle) As RectangleF Dim page = CurrPage Dim tl = page.Graphics.CreateTextLayout() tl.MaxWidth = page.Size.Width - MarginRight - _ip.X If ts.FontSize = TsTitle.FontSize Then tl.TextAlignment = TextAlignment.Center End If tl.DefaultFormat.Font = ts.Font tl.DefaultFormat.FontSize = ts.FontSize tl.DefaultFormat.GlyphAdvanceFactor = ts.GlyphAdvanceFactor tl.DefaultFormat.ForeColor = ts.ForeColor tl.Append(text) tl.PerformLayout(True) Dim line = tl.Lines(tl.Lines.Count - 1) Dim run = line.GlyphRuns(0) Dim baselineOffset = run.BaselineOffset Dim p = If(_lastBaselineOffset.HasValue, New PointF(_ip.X, _ip.Y + _lastBaselineOffset.Value - baselineOffset), _ip) page.Graphics.DrawTextLayout(tl, p) If Not _lastBaselineOffset.HasValue Then _lastBaselineOffset = baselineOffset ''#34 within one 'line', keep imports the first offset End If Return New RectangleF(_ip.X + tl.ContentX, _ip.Y + tl.ContentY, tl.ContentWidth, tl.ContentHeight) End Function Private Function DrawTextbox(ByVal width As Single, Optional ByVal inTable As Boolean = False) As RectangleF Dim fld = New TextField() fld.Widget.Page = CurrPage Dim p = If(_lastBaselineOffset.HasValue, New PointF(_ip.X, _ip.Y + _lastBaselineOffset.Value - Textbox.BaselineOffset), _ip) fld.Widget.Rect = New RectangleF(p.X, p.Y, width, Textbox.Height) If inTable Then fld.Widget.Border = Nothing Else fld.Widget.Border.Style = BorderStyle.Underline End If fld.Widget.DefaultAppearance.Font = Textbox.Font fld.Widget.DefaultAppearance.FontSize = Textbox.FontSize _doc.AcroForm.Fields.Add(fld) If Not _lastBaselineOffset.HasValue Then _lastBaselineOffset = Textbox.BaselineOffset End If Return fld.Widget.Rect End Function Private Function DrawCheckbox(ByVal text As String) As RectangleF Dim fld = New CheckBoxField() fld.Widget.Page = CurrPage Dim p = If(_lastBaselineOffset.HasValue, New PointF(_ip.X, _ip.Y + _lastBaselineOffset.Value - Checkbox.BaselineOffset), _ip) fld.Widget.Rect = New RectangleF(p.X, p.Y, Checkbox.Height, Checkbox.Height) _doc.AcroForm.Fields.Add(fld) If Not _lastBaselineOffset.HasValue Then _lastBaselineOffset = Checkbox.BaselineOffset End If Dim pSave = _ip _ip.X = fld.Widget.Rect.Right + Checkbox.LabelSpacing Dim r = DrawText(Text, TsNormal) _ip = pSave Return New RectangleF(fld.Widget.Rect.X, r.Y, r.Right - fld.Widget.Rect.Left, r.Height) End Function Private Function DrawReturnsTable() As RectangleF Dim widths As Single() = { 55, 60, 60, 35, 35, 200, 50, 0 } Dim captions As String() = { "Reason Code", "Item #", "Color", "Size", "Quantity", "Item Name", "Pirce", "Total" } Dim samples As String() = { "23", "KK123456", "Navy", "8", "1", "Example Item Only", "59.00", "59.00" } Return DrawTable(widths, captions, samples, 4) End Function Private Function DrawExchangesTable() As RectangleF '' This table has two special extra titles spanning two tolumns. '' To achieve this, we: '' - force the column titles in those 4 columns to print as '2nd paragraph', '' thus leaving an empty line for the span title '' - print the span titles here as a special case. Dim widths As Single() = { 50, 25, 25, 25, 25, 60, 150, 50, 40, 25, 35, 0 } Dim captions As String() = { "Item", "Style", vbCrLf + "1st", vbCrLf + "2nd", "Size", "Sleeve Length" + vbCrLf + "& Inseam", "Item Name", vbCrLf + "Characters", vbCrLf + "Style", "Qty.", "Price", "Total" } Dim samples As String() = { "LH123456", "Plain", "Tan", "Olive", "8", "28", "Example Item Only", "Amanda", "Block", "1", "49.95", "49.95" } Dim cr = DrawTable(widths, captions, samples, 4) '' print 2 spanning titles: Dim g = CurrGraphics Dim tl = g.CreateTextLayout() tl.ParagraphAlignment = ParagraphAlignment.Near tl.TextAlignment = TextAlignment.Center tl.DefaultFormat.Font = TsNormal.Font tl.DefaultFormat.FontSize = TsNormal.FontSize tl.DefaultFormat.GlyphAdvanceFactor = TsNormal.GlyphAdvanceFactor tl.DefaultFormat.ForeColor = Color.White tl.WrapMode = WrapMode.NoWrap '' Color Choice Dim width = widths(2) + widths(3) tl.MaxWidth = width tl.Append("Color Choice") tl.PerformLayout(True) Dim pt = New PointF(cr.Left + widths(0) + widths(1), cr.Top) g.DrawTextLayout(tl, pt) Dim pen = New GCDRAW.Pen(Color.White, 0.5F) Dim pt1 = New PointF(pt.X + 0.5F, pt.Y + TableCaptionHeight / 2) Dim pt2 = New PointF(pt1.X + width, pt1.Y) g.DrawLine(pt1, pt2, pen) pt1 = New PointF(pt.X + widths(2) + 0.5F, pt.Y + TableCaptionHeight / 2) pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight) g.DrawLine(pt1, pt2, pen) pt1 = New PointF(pt.X + 0.5F, pt.Y) pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight) g.DrawLine(pt1, pt2, pen) pt1 = New PointF(pt.X + width + 0.5F, pt.Y) pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight) g.DrawLine(pt1, pt2, pen) '' Monogramming width = widths(7) + widths(8) tl.Inlines.Clear() tl.MaxWidth = width tl.Append("Monogramming") tl.PerformLayout(True) pt = New PointF(cr.Left + widths(0) + widths(1) + widths(2) + widths(3) + widths(4) + widths(5) + widths(6), cr.Top) g.DrawTextLayout(tl, pt) pt1 = New PointF(pt.X + 0.5F, pt.Y + TableCaptionHeight / 2) pt2 = New PointF(pt1.X + width, pt1.Y) g.DrawLine(pt1, pt2, pen) pt1 = New PointF(pt.X + widths(7) + 0.5F, pt.Y + TableCaptionHeight / 2) pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight) g.DrawLine(pt1, pt2, pen) pt1 = New PointF(pt.X + 0.5F, pt.Y) pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight) g.DrawLine(pt1, pt2, pen) pt1 = New PointF(pt.X + width + 0.5F, pt.Y) pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight) g.DrawLine(pt1, pt2, pen) Return cr End Function Private Function DrawTable(ByVal widths As Single(), ByVal captions As String(), ByVal samples As String(), ByVal rowCount As Integer) As RectangleF Debug.Assert(captions.Length = widths.Length AndAlso samples.Length = widths.Length) Dim ipSave = _ip Dim p = New GCDRAW.Pen(Color.Black, 0.5F) Dim g = CurrGraphics Dim tl = g.CreateTextLayout() tl.ParagraphAlignment = ParagraphAlignment.Center tl.TextAlignment = TextAlignment.Center tl.DefaultFormat.Font = TsNormal.Font tl.DefaultFormat.FontSize = TsNormal.FontSize tl.DefaultFormat.GlyphAdvanceFactor = TsNormal.GlyphAdvanceFactor tl.DefaultFormat.ForeColor = Color.White tl.WrapMode = WrapMode.NoWrap tl.MaxHeight = TableCaptionHeight Dim totW = 0F For i = 0 To widths.Length - 1 If i = widths.Length - 1 Then widths(i) = CurrPage.Size.Width - MarginLeft - MarginRight - totW - 1 totW += 1 End If totW += widths(i) Next g.FillRectangle(New RectangleF(MarginLeft, _ip.Y, totW, TableCaptionHeight), Color.Black) Dim pt = New PointF(MarginLeft, _ip.Y) For i = 0 To widths.Length - 1 tl.MaxWidth = widths(i) tl.Append(captions(i)) tl.PerformLayout(True) g.DrawTextLayout(tl, pt) pt.X = pt.X + widths(i) tl.Inlines.Clear() Next tl.DefaultFormat.ForeColor = Color.Teal tl.MaxHeight = TableSampleHeight pt = New PointF(MarginLeft, _ip.Y + TableCaptionHeight) For i = 0 To widths.Length - 1 tl.MaxWidth = widths(i) tl.Append(samples(i)) tl.PerformLayout(True) g.DrawTextLayout(tl, pt) pt.X = pt.X + widths(i) tl.Inlines.Clear() Next SetY(_ip.Y + TableCaptionHeight + TableSampleHeight, 0.5F) For row = 0 To rowCount - 1 _ip.X = MarginLeft + 1 For i = 0 To widths.Length - 1 Dim cr = DrawTextbox(widths(i) - 1, True) _ip.X = cr.Right + 1 Next g.DrawLine(New PointF(MarginLeft, _ip.Y - 0.5F), New PointF(MarginLeft + totW, _ip.Y - 0.5F), p) SetY(Nothing, Textbox.Height + 1) Next Dim totH = TableCaptionHeight + TableSampleHeight + (Textbox.Height + 1) * rowCount _ip.X = MarginLeft + 0.5F For i = 0 To widths.Length - 2 _ip.X += widths(i) g.DrawLine(New PointF(_ip.X, ipSave.Y), New PointF(_ip.X, ipSave.Y + totH), p) Next Dim rect = New RectangleF(MarginLeft, ipSave.Y, totW, totH) g.DrawRectangle(rect, p) Return rect End Function Private Function DrawReasonCodes() As RectangleF Dim startX = 150.0F Dim capOff = 16.0F Dim colOff = 110.0F Dim ipSave = _ip _ip.X = startX Dim cr = DrawText("01", TsNormal) _ip.X += capOff cr = DrawText("Unsatisfactory", TsNormal) _ip.X = startX + colOff cr = DrawText("33", TsNormal) _ip.X += capOff cr = DrawText("Did not like color", TsNormal) _ip.X = startX + colOff * 2 cr = DrawText("23", TsNormal) _ip.X += capOff cr = DrawText("Ordered wrong size", TsNormal) _ip.X = startX + colOff * 3 cr = DrawText("51", TsNormal) _ip.X += capOff cr = DrawText("Shipping damage", TsNormal) SetY(Nothing, TsNormal.FontSize + 2) _ip.X = startX cr = DrawText("02", TsNormal) _ip.X += capOff cr = DrawText("Defective construction", TsNormal) _ip.X = startX + colOff cr = DrawText("21", TsNormal) _ip.X += capOff cr = DrawText("Too small", TsNormal) _ip.X = startX + colOff * 2 cr = DrawText("25", TsNormal) _ip.X += capOff cr = DrawText("Too short", TsNormal) _ip.X = startX + colOff * 3 cr = DrawText("52", TsNormal) _ip.X += capOff cr = DrawText("Wrong item shipped", TsNormal) _ip.X = MarginLeft + 10 cr = DrawText("Reason Codes", TsBold) Dim lineX = cr.Right + 20 SetY(Nothing, TsNormal.FontSize + 2) _ip.X = startX cr = DrawText("31", TsNormal) _ip.X += capOff cr = DrawText("Did not like styling", TsNormal) _ip.X = startX + colOff cr = DrawText("22", TsNormal) _ip.X += capOff cr = DrawText("Too large", TsNormal) _ip.X = startX + colOff * 2 cr = DrawText("36", TsNormal) _ip.X += capOff cr = DrawText("Too long", TsNormal) Dim rect = New RectangleF(MarginLeft, ipSave.Y, CurrPage.Size.Width, cr.Bottom - ipSave.Y) CurrGraphics.DrawLine(lineX, rect.Top, lineX, rect.Bottom, Color.Black, 0.5F) Return rect End Function End Class