hi folks i want to print a scrollable panel probably more than 4 pages. the panel contain labels, text boxes, list views and picture boxes. How best can i be helped
Printable View
hi folks i want to print a scrollable panel probably more than 4 pages. the panel contain labels, text boxes, list views and picture boxes. How best can i be helped
Welcome to VBForums :wave:
Thread moved from the 'CodeBank VB.Net' forum (which is for you to post working code examples, not questions) to the 'VB.Net' forum
That depends on what your panel actally is and how the info gets into the panel controls etc.
You can capture the panel from the screen as is in a bitmap and then divide it and print it on multiple pages based on size.
However just printing a bitmap image of the panel will not give the best quality. Plus you need to size the image to the printout paper somehow.
Is the panel always the same size? What size is it in pixels on the screen? What size is the printout in pixels per inch on the paper?
If you want high quality printouts you should print the text/graphics from the panel on the printout using vector graphics instead of just printing a screen shot of the panel. This will give better quality but is more effort to do.
Finally if you draw the info on the panel with gdi+ vector graphics then you can just use the same code to print on paper instead of a panel (with scaling).
So tell us and show us what your panel looks like and what your printout should look like and exaplain what you have done already and what kind of print quality do you need?
I have tried this but this only takes capture the visible controls one the panel. The the hidden ones are not printed
Code:Dim xmax, ymax, w, h As Integer
For Each ctrl As Control In Panel1.Controls
w = ctrl.Left + ctrl.Width
If xmax < w Then xmax = w
h = ctrl.Top + ctrl.Height
If ymax < h Then ymax = h
Next
Using bmp As Bitmap = New Bitmap(xmax + 10, ymax + 10)
Using g As Graphics = Graphics.FromImage(bmp)
For Each ctrl As Control In Panel1.Controls
Dim rect As New Rectangle(ctrl.Left, ctrl.Top, ctrl.Width, ctrl.Height)
ctrl.DrawToBitmap(bmp, rect)
Next
e.Graphics.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height)
End Using
End Using
You need to count the controls and keep track of the position to print them. In this example see how there is the pagecount and each control is checked to see if off the bottom of the page. If so set the hasmorepages = true flag to have the system call the print sub again for the next page. See where it sets the hasmorepages?
The example has a panel with 20 labels and that requires 3 pages to print as shown in the preview. A rectangle is also drawn for the margin settings. See how the labels are fit to the margins?
To make the example put a panel and button on an empty form. Cut and paste the code. Change the form name as requred. The code makes the labels on the panel so you dont have to.
Attachment 170655
Code:Imports System.Drawing.Printing
Public Class Form7
Public PrintPreviewDialog1 As New PrintPreviewDialog
Public WithEvents PrintDocument1 As PrintDocument = New PrintDocument
Public LastControlCount, PageCount, PageY As Integer
Private Sub Form7_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PrintPreviewDialog1.Document = Me.PrintDocument1
Panel1.BackColor = Color.White
'add labels to panel
For i As Integer = 0 To 20
Dim lab As New Label With {.Parent = Panel1,
.Location = New Point(20, i * 100),
.Size = New Size(200, 24),
.Text = "Label " & i.ToString & ": Test printing panel controls."}
Next
End Sub
Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim ControlCount As Integer
'Dim factor As Double = 1
Dim rect As Rectangle
Dim MarginHeight As Integer = CInt((PrintDocument1.DefaultPageSettings.PaperSize.Height -
(PrintDocument1.DefaultPageSettings.Margins.Top + PrintDocument1.DefaultPageSettings.Margins.Bottom)))
For Each ctrl As Control In Panel1.Controls
Using bmp As Bitmap = New Bitmap(ctrl.Width, ctrl.Height)
ControlCount += 1
If ControlCount >= LastControlCount Then
If ctrl.Bottom < MarginHeight * (PageCount + 1) Then
ctrl.DrawToBitmap(bmp, ctrl.ClientRectangle)
rect = New Rectangle(CInt(e.MarginBounds.Left + (ctrl.Left)),
CInt((e.MarginBounds.Top + (ctrl.Top)) - (MarginHeight * PageCount)),
CInt(ctrl.Width),
CInt(ctrl.Height))
e.Graphics.DrawImage(bmp, rect)
Else
LastControlCount = ControlCount
If ControlCount > 0 Then
e.HasMorePages = True
PageCount += 1
Exit For
End If
End If
End If
End Using
Next
'draw margin bounds
e.Graphics.DrawRectangle(Pens.Black, e.MarginBounds)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
LastControlCount = 0
PageCount = 0
PrintPreviewDialog1.ShowDialog()
End Sub
End Class
I have tried this. this work well with labels, text boxes and picture boxes. Now my headache is the list view
Code:Static page As Integer = 1
Dim startPosition As Integer = (page - 1) * PrintDocument1.DefaultPageSettings.Bounds.Height
Static maxPages As Integer = 0
If page = 1 Then
For Each ctrl As Control In Me.Panel1.Controls
If TypeOf ctrl Is TextBox Or TypeOf ctrl Is Label Or TypeOf ctrl Is PictureBox Then
ctrl.Tag = Int((ctrl.Top + ctrl.Height) / PrintDocument1.DefaultPageSettings.Bounds.Height) + 1
If CInt(ctrl.Tag) > maxPages Then maxPages = CInt(ctrl.Tag)
End If
Next
End If
For Each ctrl As Control In Me.Panel1.Controls
If CInt(ctrl.Tag) = page Then
If TypeOf ctrl Is TextBox Or TypeOf ctrl Is Label Then
Dim sf As New System.Drawing.StringFormat
If TypeOf ctrl Is TextBox Then
If DirectCast(ctrl, TextBox).TextAlign = HorizontalAlignment.Right Then
sf.Alignment = StringAlignment.Far
Else
sf.Alignment = StringAlignment.Near
End If
ElseIf TypeOf ctrl Is Label Then
If DirectCast(ctrl, Label).TextAlign = ContentAlignment.TopLeft Then
sf.Alignment = StringAlignment.Near
ElseIf DirectCast(ctrl, Label).TextAlign = ContentAlignment.TopRight Then
sf.Alignment = StringAlignment.Far
End If
End If
sf.FormatFlags = StringFormatFlags.NoClip
e.Graphics.DrawString(ctrl.Text, ctrl.Font, New SolidBrush(ctrl.ForeColor), New RectangleF(ctrl.Left, ctrl.Top - startPosition, ctrl.Width + 50, ctrl.Height), sf)
ElseIf TypeOf ctrl Is PictureBox Then
If Not DirectCast(ctrl, PictureBox).Image Is Nothing Then
e.Graphics.DrawImage(DirectCast(ctrl, PictureBox).Image, New PointF(ctrl.Left, ctrl.Top - startPosition))
End If
End If
End If
Next
page += 1
If page > maxPages Then
e.HasMorePages = False
page = 1
maxPages = 0
Else
e.HasMorePages = True
End If
As I asked you earlier, can you see everything in the listview without scrolling? It makes a huge difference in how to tackle that...
That's a much more difficult question. What is the View of your ListViews? Is it Details? Whatever it is, it'll need a fairly complex print algorithm. ListViews with contents extending beyond the viewable bounds are a more difficult print job, as in themselves they may extend beyond one printed page...
Here's an example that may help...
https://code.msdn.microsoft.com/List...inter-7a9be0a7
https://drive.google.com/file/d/1u61...ew?usp=sharing
short demo of how the list views look like
So you don't have to scroll your listview to see all of the contents?
As long as your contents are all visible within the unscrolled listview (not the form), you can capture an image of the control and print it like a picturebox image
Try this...
Code:ElseIf TypeOf ctrl Is ListView Then
Dim lv As ListView = DirectCast(ctrl, ListView)
Dim img As New Bitmap(lv.Width, lv.Height)
lv.DrawToBitmap(img, New Rectangle(Point.Empty, img.Size))
e.Graphics.DrawImage(img, New PointF(ctrl.Left, ctrl.Top - StartPosition))
Ok. Please note we could've solved this sooner, if you'd been more able to explain exactly what you were trying to print...