1

The code below that can nicely print image and text.

The problem now is, how can I automatically move printing to next page when a page is filled.

Will be nice to add a page number, too:

Public Class Form1

  Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    PrintPreviewDialog1.Document = PrintDocument1
    PrintPreviewDialog1.ShowDialog()
  End Sub

  Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    PrintDocument1.Print()
  End Sub

  Private Sub printDocument1_PrintPage(sender As Object, e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
    Dim rect1 As Rectangle = New Rectangle(New Point(0, 0), PictureBox1.Image.Size)
    Dim rect2 As Rectangle = New Rectangle(New Point(100, 200), PictureBox1.Image.Size)
    Dim fmt As StringFormat = New StringFormat()
    e.Graphics.DrawImage(PictureBox1.Image, rect1)
    e.Graphics.DrawString(RichTextBox1.Text, RichTextBox1.Font, New SolidBrush(Color.Red), rect2, fmt)
  End Sub

  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    For S = 1 To 200
      RichTextBox1.AppendText("Test Line No. - " & S & vbCrLf)
    Next
  End Sub

End Class
LarsTech
  • 80,625
  • 14
  • 153
  • 225
Abbas1999
  • 395
  • 1
  • 9
  • 27
  • 1
    you should set `e.HasMorePages = True` in `printDocument1_PrintPage` when you think you have more pages. The way you determine if you have more pages is up to you. Once you set `HasMorePages` to true `printDocument1_PrintPage` will be called again. Also it is your duty to keep track of the page numbers. – bansi Mar 18 '14 at 03:01
  • I am beginner and could not find e.HasMorePages or HasMorePages anywhere; can you post a sample code or image to show what you've meant? – Abbas1999 Mar 18 '14 at 04:00
  • check these links [Printing Multiple Pages in VB.NET](http://social.msdn.microsoft.com/Forums/vstudio/en-US/e78b9ab1-9205-4b27-ac04-d13a5d37355d/printing-multiple-pages-in-vbnet) and [Printing multiple pages with printdocument](http://stackoverflow.com/questions/16945172/printing-multiple-pages-with-printdocument) – bansi Mar 18 '14 at 04:20
  • Just tried it, it is giving me errors, it doesn't seem that they solve this issue? – Abbas1999 Mar 18 '14 at 04:26

1 Answers1

1

PrintPageEventArgs contains a member HasMorePages that you can set to True to raise the same event again at the end of current iteration.

To print page numbers, you'll need to keep a local class variable to track current page number. Then use an e.Graphics.DrawString() overload to print page numbers anywhere on the page.

An example using your own code:

Private mPageNumber As Integer = 1

Private Sub printDocument1_PrintPage(ByVal sender As System.Object, ByVal e As  _
             System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
    Dim rect1 As Rectangle = New Rectangle(New Point(0, 0), PictureBox1.Image.Size)
    Dim rect2 As Rectangle = New Rectangle(New Point(100, 200), PictureBox1.Image.Size)
    Dim fmt As StringFormat = New StringFormat()
    e.Graphics.DrawImage(PictureBox1.Image, rect1)
    e.Graphics.DrawString(RichTextBox1.Text, RichTextBox1.Font, New SolidBrush(Color.Red), rect2, fmt)

    Using f as New Font("Arial" , 10)
        e.Graphics.DrawString(mPageNumber.ToString(), , Brushes.Black, 0, 0) 'Page number at top-left of the page
    End Using

    mPageNumber += 1        


    e.HasMorePages = (mPageNumber <= 10) 'Will keep printing till 10 pages are printed
 End Sub

Going to next page is entirely dependent upon how you want to compute next page. Specifically, you'll need to print each character in its own font (since it is a RichTextBox) and then take care of paragraphs etc. as well. And as if that were not enough, you may need to tackle bidirectional text, text wrapping, alignment and what not too. Welcome to the world of printing!!

I won't be writing the exact code here, but will give you some hints so you could start your journey. RichTextBox has a method named GetPositionFromCharIndex() that gives you the x,y coordinates of the specified character index. You could use a loop to determine the last character whose Y-coordinate is less than or equal to e.MarginBounds.Height in your PrintPage event handler and then send all words upto that index to DrawString() function. You should keep a class level variable to track the last character upto which you have printed on the current page and then start from that point forward in the next iteration. You could use DrawString() overload that takes layout rectangle as parameter and send e.MarginBounds to it to let it automatically do word-wrapping for you.

Remember that this will only work with RichTextBox that has a single font used for all its text, which is highly unlikely given the very purpose of RichTextBox. For situations where you have multiple fonts, you'll need to call DrawString() many times for each character range comprising of a single font. As I said, this has lots of details (such as font kerning, hanging edges and other devils) that cannot be covered here. Keep reading and you'll find lots of good stuff on SO and other places.

dotNET
  • 33,414
  • 24
  • 162
  • 251
  • Thanks dotNET; I've used your code and got 2 problems: 1- it marked (e.Graphics.DrawString(mPageNumber.ToString(), 0, 0) 'Page number at top-left of the page) as error; 2-it prints 10 copies of first page only. – Abbas1999 Mar 18 '14 at 04:15
  • I fixed the first problem. The second one however is more complex. See my edit above. – dotNET Mar 18 '14 at 04:41
  • Thanks dotNET for trying, but I am still getting the exact same 2 errors, as the first time. – Abbas1999 Mar 18 '14 at 04:52
  • @Abbas1999: Added more detail – dotNET Mar 18 '14 at 05:13