How to print listview table in vb.net? - vb.net

Hi, I need to print my listview, but I'm not sure how to do it?

Public Class listViewPrinter
Private lv As ListView
Private location As Point
Private border As Boolean
Private title As String
Private titleHeight As Integer
Private hLines As Boolean
Private vLines As Boolean
Private WithEvents pd As New Printing.PrintDocument
Public Sub New(ByVal lv As ListView, ByVal location As Point, ByVal border As Boolean, ByVal _hLines As Boolean, ByVal _vLines As Boolean, Optional ByVal title As String = "")
Me.lv = lv
Me.location = location
Me.border = border
Me.title = title
Me.hLines = _hLines
Me.vLines = _vLines
titleHeight = If(title <> "", lv.FindForm.CreateGraphics.MeasureString(title, New Font(lv.Font.Name, 25)).ToSize.Height, 0)
End Sub
Public Sub print()
'pd.Print()
Dim ppd As New PrintPreviewDialog
ppd.Document = pd
ppd.WindowState = FormWindowState.Maximized
ppd.ShowDialog()
End Sub
Private Structure pageDetails ' structure to hold printed page details
Dim columns As Integer
Dim rows As Integer
Dim startCol As Integer
Dim startRow As Integer
Dim headerIndices As List(Of Integer)
End Structure
Private pages As Dictionary(Of Integer, pageDetails) ' dictionary to hold printed page details, with index key
Dim maxPagesWide As Integer
Dim maxPagesTall As Integer
Dim items() As ListViewItem
' the majority of this Sub is calculating printed page ranges
Private Sub pd_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles pd.BeginPrint
pd.DefaultPageSettings.Landscape = True
pd.OriginAtMargins = True 'this removes the printed page margins
pd.DefaultPageSettings.Margins = New Drawing.Printing.Margins(location.X, location.X, location.Y, location.Y)
pages = New Dictionary(Of Integer, pageDetails)
' Reversed MaxWidth & MaxHeight for landscape page...
'Dim maxWidth As Integer = CInt(pd.DefaultPageSettings.PrintableArea.Width) - (pd.DefaultPageSettings.Margins.Left + pd.DefaultPageSettings.Margins.Right + 40)
'Dim maxHeight As Integer = CInt(pd.DefaultPageSettings.PrintableArea.Height - (titleHeight + 12)) - (pd.DefaultPageSettings.Margins.Top + pd.DefaultPageSettings.Margins.Bottom + 40)
Dim maxWidth As Integer = CInt(pd.DefaultPageSettings.PrintableArea.Height) - (pd.DefaultPageSettings.Margins.Left + pd.DefaultPageSettings.Margins.Right + 0)
Dim maxHeight As Integer = CInt(pd.DefaultPageSettings.PrintableArea.Width - (titleHeight + 12)) - (pd.DefaultPageSettings.Margins.Top + pd.DefaultPageSettings.Margins.Bottom + 0)
Dim pageCounter As Integer = 0
pages.Add(pageCounter, New pageDetails With {.headerIndices = New List(Of Integer)})
Dim columnCounter As Integer = 0
Dim columnSum As Integer = 0
For c As Integer = 0 To lv.Columns.Count - 1
If columnSum + lv.Columns(c).Width < maxWidth Then
columnSum += lv.Columns(c).Width
columnCounter += 1
Else
pages(pageCounter) = New pageDetails With {.columns = columnCounter, .rows = 0, .startCol = pages(pageCounter).startCol, .headerIndices = pages(pageCounter).headerIndices}
columnSum = lv.Columns(c).Width
columnCounter = 1
pageCounter += 1
pages.Add(pageCounter, New pageDetails With {.startCol = c, .headerIndices = New List(Of Integer)})
End If
If c = lv.Columns.Count - 1 Then
If pages(pageCounter).columns = 0 Then
pages(pageCounter) = New pageDetails With {.columns = columnCounter, .rows = 0, .startCol = pages(pageCounter).startCol, .headerIndices = pages(pageCounter).headerIndices}
End If
End If
Next
maxPagesWide = pages.Keys.Max + 1
pageCounter = 0
Dim rowCounter As Integer = 0
Dim counter As Integer = 0
Dim itemHeight As Integer = lv.GetItemRect(0).Height
Dim rowSum As Integer = itemHeight
For r As Integer = 0 To lv.Items.Count - 1
counter += 1
If rowSum + itemHeight < maxHeight Then
rowSum += itemHeight
rowCounter += 1
Else
pages(pageCounter) = New pageDetails With {.columns = pages(pageCounter).columns, .rows = rowCounter, .startCol = pages(pageCounter).startCol, .startRow = pages(pageCounter).startRow}
For x As Integer = 1 To maxPagesWide - 1
pages(pageCounter + x) = New pageDetails With {.columns = pages(pageCounter + x).columns, .rows = rowCounter, .startCol = pages(pageCounter + x).startCol, .startRow = pages(pageCounter).startRow}
Next
pageCounter += maxPagesWide
For x As Integer = 0 To maxPagesWide - 1
pages.Add(pageCounter + x, New pageDetails With {.columns = pages(x).columns, .rows = 0, .startCol = pages(x).startCol, .startRow = counter - 1})
Next
rowSum = itemHeight * 2
rowCounter = 1
End If
If counter = lv.Items.Count Then
For x As Integer = 0 To maxPagesWide - 1
If pages(pageCounter + x).rows = 0 Then
pages(pageCounter + x) = New pageDetails With {.columns = pages(pageCounter + x).columns, .rows = rowCounter, .startCol = pages(pageCounter + x).startCol, .startRow = pages(pageCounter + x).startRow}
End If
Next
End If
Next
maxPagesTall = pages.Count \ maxPagesWide
items = lv.Items.Cast(Of ListViewItem).ToArray
End Sub
Private Sub pd_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles pd.PrintPage
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
Dim r2 As New Rectangle(location, New Size(lv.Columns.Cast(Of ColumnHeader).Skip(pages(0).startCol).Take(pages(0).columns).Sum(Function(ch As ColumnHeader) ch.Width), titleHeight))
e.Graphics.DrawString(title, New Font(lv.Font.Name, 25), Brushes.Black, r2, sf)
sf.Alignment = StringAlignment.Near
Dim startX As Integer = location.X
Dim startY As Integer = location.Y + titleHeight + 12
Static startPage As Integer = 0
Dim itemHeight As Integer = lv.GetItemRect(0).Height
Dim bottomRight As Point
For p As Integer = startPage To pages.Count - 1
startX = location.X
startY = location.Y + titleHeight + 12
Dim cell As Rectangle
For c As Integer = pages(p).startCol To pages(p).startCol + pages(p).columns - 1
cell = New Rectangle(startX, startY, lv.Columns(c).Width, itemHeight)
e.Graphics.FillRectangle(New SolidBrush(SystemColors.ControlLight), cell)
e.Graphics.DrawRectangle(Pens.Black, cell)
e.Graphics.DrawString(lv.Columns(c).Text, lv.Font, Brushes.Black, cell, sf)
startX += lv.Columns(c).Width
Next
startY += itemHeight
startX = location.X
For r As Integer = pages(p).startRow To pages(p).startRow + pages(p).rows - 1
startX = location.X
For c As Integer = pages(p).startCol To pages(p).startCol + pages(p).columns - 1
cell = New Rectangle(startX, startY, lv.Columns(c).Width, itemHeight)
e.Graphics.DrawString(items(r).SubItems(c).Text, lv.Font, Brushes.Black, cell, sf)
If vLines Then
e.Graphics.DrawLine(Pens.Black, cell.Left, cell.Top, cell.Left, cell.Bottom)
e.Graphics.DrawLine(Pens.Black, cell.Right, cell.Top, cell.Right, cell.Bottom)
End If
If hLines Then
e.Graphics.DrawLine(Pens.Black, cell.Left, cell.Top, cell.Right, cell.Top)
e.Graphics.DrawLine(Pens.Black, cell.Left, cell.Bottom, cell.Right, cell.Bottom)
End If
startX += lv.Columns(c).Width
Next
startY += itemHeight
If r = pages(p).startRow + pages(p).rows - 1 Then
bottomRight = New Point(startX, startY)
If border Then e.Graphics.DrawRectangle(Pens.Black, New Rectangle(location, New Size(bottomRight.X - location.X, bottomRight.Y - location.Y)))
End If
Next
If p <> pages.Count - 1 Then
startPage = p + 1
e.HasMorePages = True
Return
Else
startPage = 0
End If
Next
End Sub
End Class
Courtesy of

Related

vb Image grid detection

Im looking for a way to detect the center of grid squares when VB.net is feed an image
I want to start with an image of a grid with blue squares like this:
Grid
and i want the program to make an array of points in the center of each square like this (points aren't centered in picture)
Grid with Red points
i dont want to modify the image, i just want to get the points. I've tried getpixel for x and y but that just returns the same point
Dim search_color As Color = Color.FromArgb(255, 64, 128, 192)
Dim background_color As Color = Color.FromArgb(255, 240, 240, 240)
Dim grid_color As Color = Color.FromArgb(255, 144, 144, 144)
Dim pix As Color
Dim liney = 0, linex = 0
Dim loc, sloc, gloc As Point
For ch As Integer = 1 To 64
For y As Integer = liney To Bmp.Height - 1
For x As Integer = linex To Bmp.Width - 1
If Bmp.GetPixel(x, y) = search_color Then
sloc = New Point(x, y)
linex = x
liney = y
x = Bmp.Width - 1
y = Bmp.Height - 1
End If
Next
Next
Dim xloc = 0
For x As Integer = sloc.X To Bmp.Width - 1
If Bmp.GetPixel(x, sloc.Y) = grid_color Then
xloc = x - 1
End If
If Bmp.GetPixel(x, sloc.Y) = background_color Then
xloc = x - 1
End If
Next
For y As Integer = sloc.Y To Bmp.Height - 1
If Bmp.GetPixel(xloc, y) = grid_color Or Bmp.GetPixel(xloc, y) = background_color Then
gloc = New Point(xloc, y - 1)
End If
Next
loc = New Point((gloc.X + sloc.X) / 2, (gloc.Y + sloc.Y) / 2)
liney = gloc.Y
linex = gloc.X + 20
ListBox1.Items.Add(loc.ToString)
Next
Try this:
I added the following controls to a form to test the code:
pbImageToScan (PictureBox) - btnAnalyzeIMG (Button) - lbResult (ListBox)
Public Class Form1
Dim arrCenters() As Point
Dim bmpToAnalyze As Bitmap
Dim search_color As Color = Color.FromArgb(255, 64, 128, 192)
Dim background_color As Color = Color.FromArgb(255, 240, 240, 240)
Dim grid_color As Color = Color.FromArgb(255, 144, 144, 144)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
bmpToAnalyze = New Bitmap(Application.StartupPath & "\Image.bmp")
pbImageToScan.Image = Image.FromFile(Application.StartupPath & "\Image.bmp")
End Sub
Private Sub btnAnalyzeIMG_Click(sender As Object, e As EventArgs) Handles btnAnalyzeIMG.Click
FindCenters()
End Sub
Private Sub FindCenters()
bmpToAnalyze = New Bitmap(Application.StartupPath & "\Image.bmp")
pbImageToScan.Image = Image.FromFile(Application.StartupPath & "\Image.bmp")
'arrCenters is the array who will contains all centers data
ReDim arrCenters(0)
'arrCenters already starts with an element; this boolean is used to handle the first point insertion
Dim bFirstElementAddedToArray As Boolean
lbResult.Items.Clear()
Dim iIMGWidth As Integer = bmpToAnalyze.Width
Dim iIMGHeight As Integer = bmpToAnalyze.Height
'X, Y coordinates used for iterations
Dim iX As Integer = 0
Dim iY As Integer = 0
'Bitmap limits reached
Dim bExit As Boolean
'Used to skip a great part of Ys, if a match has been found along the current examinated line
Dim iDeltaYMax As Integer = 0
'Main cycle
Do While Not bExit
Dim colCurrentColor As Color = bmpToAnalyze.GetPixel(iX, iY)
If colCurrentColor = search_color Then
Dim iXStart As Integer = iX
Dim iYStart As Integer = iY
Dim iXEnd As Integer
Dim iYEnd As Integer
'Width of the Blue square
For iXEnd = iX + 1 To iIMGWidth - 1
Dim colColorSearchX As Color = bmpToAnalyze.GetPixel(iXEnd, iY)
If (colColorSearchX = background_color) Or (colColorSearchX = grid_color) Then
iXEnd -= 1
Exit For
End If
Next
'Height of the Blue square
For iYEnd = iY + 1 To iIMGHeight - 1
Dim colColorSearchY As Color = bmpToAnalyze.GetPixel(iXEnd, iYEnd)
If (colColorSearchY = background_color) Or (colColorSearchY = grid_color) Then
iYEnd -= 1
Exit For
End If
Next
iDeltaYMax = iYEnd - iYStart
'Blue square center coordinates
Dim pCenter As New Point((iXStart + iXEnd) / 2, (iYStart + iYEnd) / 2)
Dim iArrLenght As Integer = 0
If Not bFirstElementAddedToArray Then
bFirstElementAddedToArray = True
Else
iArrLenght = arrCenters.GetLength(0)
ReDim Preserve arrCenters(iArrLenght)
End If
arrCenters(iArrLenght) = pCenter
lbResult.Items.Add(pCenter.ToString)
iX = iXEnd
'Checks if the Width limit of the bitmap has been reached
If iX = (iIMGWidth - 1) Then
iX = 0
iY += iDeltaYMax + 1
iDeltaYMax = 0
Else
iX += 1
End If
Else
'Checks if the Width limit of the bitmap has been reached
If iX = (iIMGWidth - 1) Then
iX = 0
iY += iDeltaYMax + 1
iDeltaYMax = 0
Else
iX += 1
End If
End If
'Width and Height limit of the bitmap have been reached
If (iX = iIMGWidth - 1) And (iY = iIMGHeight - 1) Then
bExit = True
End If
Loop
'Draws a Red point on every center found
For Each P As Point In arrCenters
bmpToAnalyze.SetPixel(P.X, P.Y, Color.Red)
Next
pbImageToScan.Image = bmpToAnalyze
End Sub
End Class

Calling the same function with different functions called inside

I hope my title is clear. Let me explain. I have 4 buttons that do pretty much the same.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
LimiteGlobalSeparador = InputBox("Introduzca la distancia máxima entre huecos en el tubo", "Cuadro de Datos, Separaciones", "")
Dim a, b, c, d, f, g As New Label
Dim o, p, q, r, s, t As New Label
a.Text = "Medida del Tubo"
b.Text = "Espacio 1"
c.Text = "Espacio 2"
d.Text = "Espacio 3"
f.Text = "Espacio 4"
g.Text = "Espacio 5"
For i = 0 To 5
TableLayoutPanel1.Controls.Add(a, 0, i)
Next
If TextBox1.Text <> 0 Then
For j = 1 To Int(TextBox1.Text)
Dim x As New List(Of Decimal)
x = MedTuboFuncPCT()
For i = 0 To x.Count - 1
Dim lbl As New Label
lbl.Text = Math.Round(x(i), 2)
TableLayoutPanel1.Controls.Add(lbl, j, i)
Next
ContadorGlobal = ContadorGlobal + 1
Next
Else
End If
ContadorGlobal = 0
Dim h As Integer
h = Int(TextBox2.Text - TextBox1.Text)
If TextBox2.Text <> 0 Then
If h = Int(TextBox2.Text) Then
For j = 1 To Int(TextBox2.Text)
Dim x As New List(Of Decimal)
x = MedTuboFunCTCT()
For i = 0 To x.Count - 1
Dim lbl As New Label
lbl.Text = Math.Round(x(i), 2)
TableLayoutPanel1.Controls.Add(lbl, j, i)
Next
ContadorGlobal = ContadorGlobal + 1
Next
Else
ContadorGlobal = 0
For j = Int(1) + Int(TextBox1.Text) To (Int(TextBox1.Text) + Int(TextBox2.Text))
Dim x As New List(Of Decimal)
x = MedTuboFunCTCT()
For i = 0 To x.Count - 1
Dim lbl As New Label
lbl.Text = Math.Round(x(i), 2)
TableLayoutPanel1.Controls.Add(lbl, j, i)
Next
ContadorGlobal = ContadorGlobal + 1
Next
End If
End If
ContadorGlobal = 0
If TextBox3.Text <> 0 Then
Dim x As New List(Of Decimal)
x = MedTuboFuncPP()
For i = 0 To x.Count - 1
Dim lbl As New Label
lbl.Text = Math.Round(x(i), 2)
TableLayoutPanel1.Controls.Add(lbl, 1, i)
Next
End If
If Te180 > 0 Then
o.Text = "Medida del Tubo"
p.Text = "Espacio 1"
q.Text = "Espacio 2"
r.Text = "Espacio 3"
s.Text = "Espacio 4"
t.Text = "Espacio 5"
For i = 6 To 11
TableLayoutPanel1.Controls.Add(o, 0, i)
Next
End If
End Sub
So I'm trying to create a Sub and then each button call that sub, so I don't have repeating code in each button like I have now. The only change is here:
One button calls this function. x = MedTuboFuncPCT().
Another one calls x = MedTuboFuncPCTVid()
Another one calls x = MedTuboFuncPCTVidBB()
I don't know how to make a Sub in which I can make this difference. Hope I'm clear enough. Thanks in advance.
Create your function and send a value in it so you can change the x function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
VFunction = 1
RepeatedCode(VFunction)
End Sub
On Button2 VFunction = 2 and so on. Then create your function.
Public Sub RepeatedCode (ByVal VFunction as integer)
If VFunction = 1 Then
x = MedTuboFuncPCT()
ElseIf VFunction = 2 Then
x = MedTuboFuncPCTVid()
ElseIf VFunction = 3 Then
x = MedTuboFuncPCT()
End If
'The Rest of your code
I belive the If condition must be placed inside your If TextBox1.Text <> 0
Since it its the only place where I see you used one of the Functions you mentioned

Reduce latency when Embossing an Image in PictureBox

How would I go about reducing the latency of grabbing an image from Picturebox then emboss that image and return you picturebox as this is a camera handle and will need to capture/emboss at least 16 fps but i'm getting like 1 every 2.5 seconds
SwitchImageSave = 1
Button1.Enabled = False
StCam.StopTransfer(m_hCamera)
Dim nReval As Integer
Dim nLastErrorNo As Integer
Dim nBufferSize As Integer
Dim dwWidth As Integer
Dim dwHeight As Integer
Dim dwLinePitch As Integer
nReval = StCam.GetPreviewDataSize(m_hCamera, nBufferSize, dwWidth, dwHeight, dwLinePitch)
Dim dwPreviewPixelFormat As Integer
nReval = StCam.GetPreviewPixelFormat(m_hCamera, dwPreviewPixelFormat)
Dim pixelFormat As Imaging.PixelFormat = Imaging.PixelFormat.Format8bppIndexed
Select Case dwPreviewPixelFormat
Case StCam.STCAM_PIXEL_FORMAT_24_BGR
pixelFormat = Imaging.PixelFormat.Format24bppRgb
Case StCam.STCAM_PIXEL_FORMAT_32_BGR
pixelFormat = Imaging.PixelFormat.Format32bppRgb
End Select
Dim pbyteImageBuffer(nBufferSize) As Byte
Dim dwNumberOfByteTrans As Integer = 0
Dim pdwFrameNo(1) As Integer
Dim dwMilliseconds As Integer = 100
Dim gch As System.Runtime.InteropServices.GCHandle = System.Runtime.InteropServices.GCHandle.Alloc(pbyteImageBuffer, System.Runtime.InteropServices.GCHandleType.Pinned)
Dim ptr As IntPtr = gch.AddrOfPinnedObject()
nReval = StCam.TakePreviewSnapShot(m_hCamera, ptr, nBufferSize, dwNumberOfByteTrans, pdwFrameNo, dwMilliseconds)
gch.Free()
Dim bitmap As Bitmap = New Bitmap(dwWidth, dwHeight, pixelFormat)
Select Case pixelFormat
Case Imaging.PixelFormat.Format8bppIndexed
Dim colorPalette As System.Drawing.Imaging.ColorPalette = bitmap.Palette
For pixelValue As Integer = 0 To 255
colorPalette.Entries(pixelValue) = Color.FromArgb(pixelValue, pixelValue, pixelValue)
Next
bitmap.Palette = colorPalette
End Select
Dim bitmapData As Imaging.BitmapData = bitmap.LockBits(New Rectangle(0, 0, dwWidth, dwHeight), Imaging.ImageLockMode.WriteOnly, pixelFormat)
Runtime.InteropServices.Marshal.Copy(pbyteImageBuffer, 0, bitmapData.Scan0(), nBufferSize)
bitmap.UnlockBits(bitmapData)
Dim bmap As Bitmap
bmap = New Bitmap(bitmap)
PictureBox2.Image = bmap
' PictureBox2.Image = bmap
Dim tempbmp As New Bitmap(bmap)
Dim i, j As Integer
Dim DispX As Integer = 1, DispY As Integer = 1
Dim red, green, blue As Integer
With tempbmp
For i = 0 To .Height - 2
For j = 0 To .Width - 2
Dim pixel1, pixel2 As System.Drawing.Color
pixel1 = .GetPixel(j, i)
pixel2 = .GetPixel(j + DispX, i + DispY)
red = Math.Min(Math.Abs(CInt(pixel1.R) - CInt(pixel2.R)) + 128, 255)
green = Math.Min(Math.Abs(CInt(pixel1.G) - CInt(pixel2.G)) + 128, 255)
blue = Math.Min(Math.Abs(CInt(pixel1.B) - CInt(pixel2.B)) + 128, 255)
bmap.SetPixel(j, i, Color.FromArgb(red, green, blue))
Next
Next
End With
PictureBox2.Image = bmap
PictureBox2.Refresh()
PictureBox2.BringToFront()
Dim bitmapData As Imaging.BitmapData = bitmap.LockBits(New Rectangle(0, 0, dwWidth, dwHeight), Imaging.ImageLockMode.WriteOnly, pixelFormat)
Runtime.InteropServices.Marshal.Copy(pbyteImageBuffer, 0, bitmapData.Scan0(), nBufferSize)
bitmap.UnlockBits(bitmapData)
PictureBox2.Image = bitmap
Dim temp As Bitmap = PictureBox2.Image
Dim raz As Integer = temp.Height / 4
Dim height As Integer = temp.Height
Dim width As Integer = temp.Width
Dim rect As New Rectangle(Point.Empty, temp.Size)
Dim bmpData As BitmapData = temp.LockBits(rect, ImageLockMode.[ReadOnly], temp.PixelFormat)
Dim bpp As Integer = If((temp.PixelFormat = PixelFormat.Format32bppArgb), 4, 3)
Dim size As Integer = bmpData.Stride * bmpData.Height
Dim data As Byte() = New Byte(size - 1) {}
'byte[] newdata = new byte[size];
System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, data, 0, size)
'System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, newdata, 0, size);
Dim options = New ParallelOptions()
Dim maxCore As Integer = Environment.ProcessorCount - 1
options.MaxDegreeOfParallelism = If(maxCore > 0, maxCore, 1)
For y As Integer = 0 To height - 4
For x As Integer = 0 To width - 4
If True Then
Dim index As Integer = y * bmpData.Stride + x * bpp
'Blue
data(index) = CByte(Math.Min(Math.Abs(CInt(data(index)) - CInt(data(index + bpp + bmpData.Stride))) + 128, 255))
'Green
data(index + 1) = CByte(Math.Min(Math.Abs(CInt(data(index + 1)) - CInt(data(index + bpp + 1 + bmpData.Stride))) + 128, 255))
'Red
data(index + 2) = CByte(Math.Min(Math.Abs(CInt(data(index + 2)) - CInt(data(index + bpp + 2 + bmpData.Stride))) + 128, 255))
End If
Next
Next

Printing forms in vb.net with many listviews

is it possible to print a form in vb.net using different listviews? For example I have 10 listviews and I want it all to be printed is a single form.
This is my code for my print document (So far it works with 2 listviews, but when I tried printing the 3rd listview, it overlaps the 2nd listview)
'Texts
Dim time As String
time = String.Format("{0:T}", DateTime.Now)
Dim dateNow As String = DateString
' Dim totalcash As String = Convert.ToDecimal(p_cashTotal).ToString("N2")
Dim fontTitle As New Font("Arial", 15, FontStyle.Bold)
Dim font1 As New Font("Arial", 10, FontStyle.Bold)
Dim font2 As New Font("Arial", 9, FontStyle.Bold)
Dim font3 As New Font("Arial", 9, FontStyle.Regular)
e.Graphics.DrawString("Company name", fontTitle, Brushes.Black, 270, 20)
e.Graphics.DrawString("Report name", font1, Brushes.Black, 350, 40)
' e.Graphics.DrawImage(pbxLogo.Image, 160, 10)
' e.Graphics.DrawString("SALES REPORT - " + salesType, font2, Brushes.Black, 277, 55)
' e.Graphics.DrawString("Description: List of customer who wasn't able to return items", font3, Brushes.Black, 133, 80)
e.Graphics.DrawString("Date/Time Printed:", font2, Brushes.Black, 133, 80)
e.Graphics.DrawString(dateNow, font3, Brushes.Black, 250, 80)
e.Graphics.DrawString(time, font3, Brushes.Black, 320, 80)
e.Graphics.DrawString("Date/Time Printed:", font2, Brushes.Black, 133, 80)
' e.Graphics.DrawString("Total Earnings:", font2, Brushes.Black, 133, 95)
' e.Graphics.DrawString("Php " + totalcash, font3, Brushes.Black, 240, 95)
Dim CurrRow As Integer = 0
Dim Ratio As Single = 0
Dim c As ColumnHeader
Dim g As Graphics = e.Graphics
Dim l As Integer = 120 'stores current left
Dim iCount As Integer
Dim f As Font = LVLevel1.Font
Dim FontBold As New System.Drawing.Font("Arial", 10, FontStyle.Regular)
Dim b As Brush = Brushes.Black
Dim currentY As Integer = 0
Dim maxY As Integer = 0
Dim gap As Integer = 5
Dim lvsi As ListViewItem.ListViewSubItem
Dim colLefts(LVLevel1.Columns.Count) As Integer
Dim colWidths(LVLevel1.Columns.Count) As Integer
Dim idx As Integer = 0
Dim ii As Integer
Dim lr As RectangleF
'LVLevel2
Dim colLefts2(LVLevel2.Columns.Count) As Integer
Dim colWidths2(LVLevel2.Columns.Count) As Integer
'LVLevel4
Dim colLefts3(LVLevel3.Columns.Count) As Integer
Dim colWidths3(LVLevel3.Columns.Count) As Integer
e.HasMorePages = False
' g.DrawRectangle(Pens.Black, 115, 140, 430, 30)
Dim sfc As New StringFormat
sfc.LineAlignment = StringAlignment.Center
sfc.Alignment = StringAlignment.Center
'LVLevel1
'Headings
currentY = 150
For Each c In LVLevel1.Columns
maxY = Math.Max(maxY, g.MeasureString(c.Text, f, c.Width).Height)
colLefts(idx) = l
colWidths(idx) = c.Width
lr = New RectangleF(colLefts(idx), currentY, colWidths(idx), maxY)
If lr.Width > 0 Then g.DrawString(c.Text, FontBold, b, lr, sfc)
l += c.Width
idx += 1
Next
currentY += maxY + gap
'g.DrawLine(Pens.Black, 0, currentY, e.PageBounds.Width, currentY)
currentY += gap
'Rows
iCount = LVLevel1.Items.Count - 1
For ii = CurrRow To iCount
If (currentY + maxY + maxY) > e.PageBounds.Height Then 'jump down another line to see if this line will fit
CurrRow = ii - 2
e.HasMorePages = True
currentY += maxY + gap
Exit For 'does next page
End If
l = 0
maxY = 0
idx = 0
For Each lvsi In LVLevel1.Items(ii).SubItems
maxY = Math.Max(maxY, g.MeasureString(lvsi.Text, f, colWidths(idx)).Height)
lr = New RectangleF(colLefts(idx), currentY, colWidths(idx), maxY)
If LVLevel1.Columns(idx).Text <> "Name" Then
If lr.Width > 0 Then g.DrawString(lvsi.Text, f, b, lr, sfc)
Else
If lr.Width > 0 Then g.DrawString(lvsi.Text, f, b, lr)
End If
idx += 1
Next
currentY += maxY + gap
Next
'LVLEvel2
currentY = 150
For Each c In LVLevel2.Columns
maxY = Math.Max(maxY, g.MeasureString(c.Text, f, c.Width).Height)
colLefts2(idx) = l
colWidths2(idx) = c.Width
lr = New RectangleF(colLefts2(idx), currentY, colWidths2(idx), maxY)
If lr.Width > 0 Then g.DrawString(c.Text, FontBold, b, lr, sfc)
l += c.Width
idx += 1
Next
currentY += maxY + gap
'g.DrawLine(Pens.Black, 0, currentY, e.PageBounds.Width, currentY)
currentY += gap
'Rows
iCount = LVLevel2.Items.Count - 1
For ii = CurrRow To iCount
If (currentY + maxY + maxY) > e.PageBounds.Height Then 'jump down another line to see if this line will fit
CurrRow = ii - 2
e.HasMorePages = True
currentY += maxY + gap
Exit For 'does next page
End If
l = 0
maxY = 0
idx = 0
For Each lvsi In LVLevel2.Items(ii).SubItems
maxY = Math.Max(maxY, g.MeasureString(lvsi.Text, f, colWidths2(idx)).Height)
lr = New RectangleF(colLefts2(idx), currentY, colWidths(idx), maxY)
If LVLevel2.Columns(idx).Text <> "Name" Then
If lr.Width > 0 Then g.DrawString(lvsi.Text, f, b, lr, sfc)
Else
If lr.Width > 0 Then g.DrawString(lvsi.Text, f, b, lr)
End If
idx += 1
Next
currentY += maxY + gap
Next
this are the additional variables
Protected WithEvents pd As Printing.PrintDocument 'used by Print sub
Protected Ratio As Single = 0, CurrRow As Integer = 0
this are my codes for the button PrintPreview, which opens print preview dialog
pdocDlines.DefaultPageSettings.Landscape = True
ppreviewDlines.PrintPreviewControl.Zoom = 1
ppreviewDlines.ShowDialog()
I just got this codes from some forums, what I want to do is to position the data from different listviews properly. Thanks

listview printing

I have found some code using google for listview printing. I modified the code base on my needs. I have some problem if the list view more than one pages. It will not stop counting "Generating Previews" of my document. If I press the cancel it was display the data in multiple pages but the same content.
Any suggestion would greatly appreciated.
Thanks in advance
Here is the code
Public Sub pd_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
Dim pd As New PrintDocument
Dim CurrRow As Integer = 0
Dim Ratio As Single = 0
Dim c As ColumnHeader
Dim g As Graphics = e.Graphics
Dim l As Integer = 0 'stores current left
Dim iCount As Integer
Dim f As Font = lsvToPrint.Font
Dim FontBold As New System.Drawing.Font("Microsoft Sans Serif", 10, FontStyle.Bold)
Dim b As Brush = Brushes.Black
Dim currentY As Integer = 0
Dim maxY As Integer = 0
Dim gap As Integer = 5
Dim lvsi As ListViewItem.ListViewSubItem
Dim colLefts(lsvToPrint.Columns.Count) As Integer
Dim colWidths(lsvToPrint.Columns.Count) As Integer
Dim idx As Integer = 0
Dim ii As Integer
Dim lr As RectangleF
e.HasMorePages = False
'Page Settings
Dim PSize As Integer = lsvToPrint.Items.Count
Dim PHi As Double
With pd.DefaultPageSettings
Dim Ps As PaperSize
PHi = PSize * 20 + 350
Ps = New PaperSize("Cust", 800, PHi)
.Margins.Top = 15
.Margins.Bottom = 20
.PaperSize = Ps
End With
Dim sfc As New StringFormat
sfc.LineAlignment = StringAlignment.Center
sfc.Alignment = StringAlignment.Center
'Title
Dim headfont As Font
Dim X1 As Integer
Dim Y As Integer
headfont = New Font("Courier New", 16, FontStyle.Bold)
X1 = pd.DefaultPageSettings.Margins.Left
Y = pd.DefaultPageSettings.Margins.Top + 5
With pd.DefaultPageSettings
e.Graphics.DrawLine(Pens.Black, 0, Y + 70, e.PageBounds.Width, Y + 70)
End With
'Headings
currentY = 100
For Each c In lsvToPrint.Columns
maxY = Math.Max(maxY, g.MeasureString(c.Text, f, c.Width).Height)
colLefts(idx) = l
colWidths(idx) = c.Width
lr = New RectangleF(colLefts(idx), currentY, colWidths(idx), maxY)
If lr.Width > 0 Then g.DrawString(c.Text, FontBold, b, lr, sfc)
l += c.Width
idx += 1
Next
currentY += maxY + gap
g.DrawLine(Pens.Black, 0, currentY, e.PageBounds.Width, currentY)
currentY += gap
'Rows
iCount = lsvToPrint.Items.Count - 1
For ii = CurrRow To iCount
If (currentY + maxY + maxY) > e.PageBounds.Height Then 'jump down another line to see if this line will fit
CurrRow = ii - 1
e.HasMorePages = True
currentY += maxY + gap
Exit For 'does next page
End If
l = 0
maxY = 0
idx = 0
For Each lvsi In lsvToPrint.Items(ii).SubItems
maxY = Math.Max(maxY, g.MeasureString(lvsi.Text, f, colWidths(idx)).Height)
lr = New RectangleF(colLefts(idx), currentY, colWidths(idx), maxY)
If lsvToPrint.Columns(idx).Text <> "Name" Then
If lr.Width > 0 Then g.DrawString(lvsi.Text , f, b, lr, sfc)
Else
If lr.Width > 0 Then g.DrawString(lvsi.Text, f, b, lr)
End If
idx += 1
Next
currentY += maxY + gap
Next
End Sub
Make sure that you compensate the height of the MaxY for the new page. On the first page it's fine, but then when it gets to the next page, CurrentY + MaxY might already be bigger than the height of the page.