Question How to print tabpage silently

Grega

Active member
Joined
Jun 21, 2007
Messages
25
Programming Experience
1-3
I am not sure if this fits in some other forum thread but here goes...


I have an application in which I open larger number of files create a specific report (I fill in values in a usercontrol with 3 tabpages and some textboxes labels and graph on each of them) for each and would like to print this control silently (meaning never to open it for user to view)...

it works great if I open it and print then, but if I only fill the report and try to print this I just get a blank page. (I am printing in a pdf printer to save paper :) - for now), although here also if I only look at first tabpage and print all 3 of them (but never actually clicking on the rest) I only get a print of first tabpage and the second two pages are again blank.

The code I use to print:

VB.NET:
Public Class PrintMe

    Dim printdialog1 As New PrintDialog
    Dim WithEvents PrintDocument1 As New Printing.PrintDocument
    Private bmp As Bitmap
    Public tp() As TabPage
    'Public tc As TabControl
    Private tabpagecount As Integer = 0

    Public Sub Print() 'ByVal _ucreportpreview As ucReportPreview
      
        '_ucreportpreview.TpPS.DrawToBitmap(bmp, _ucreportpreview.TpPS.DisplayRectangle)
        With printdialog1
            'If PrintDocument1.DefaultPageSettings.PaperSize.Width - bmp.Width < 12 Then
            If PrintDocument1.DefaultPageSettings.PaperSize.Width - tp(tabpagecount).Width < 12 Then

                PrintDocument1.DefaultPageSettings.Margins.Left = Convert.ToInt32((3.0 / 25.4) * 100)
                PrintDocument1.DefaultPageSettings.Margins.Right = Convert.ToInt32((3.0 / 25.4) * 100)
            Else
                'PrintDocument1.DefaultPageSettings.Margins.Left = (PrintDocument1.DefaultPageSettings.PaperSize.Width - bmp.Width) / 2
                PrintDocument1.DefaultPageSettings.Margins.Left = (PrintDocument1.DefaultPageSettings.PaperSize.Width - tp(tabpagecount).Width) / 2
                PrintDocument1.DefaultPageSettings.Margins.Right = PrintDocument1.DefaultPageSettings.Margins.Left

            End If

            PrintDocument1.DefaultPageSettings.Margins.Top = Convert.ToInt32((3.0 / 25.4) * 100)
            'If PrintDocument1.DefaultPageSettings.PaperSize.Height - bmp.Height < 12 Then
            If PrintDocument1.DefaultPageSettings.PaperSize.Height - tp(tabpagecount).Height < 12 Then

                PrintDocument1.DefaultPageSettings.Margins.Bottom = Convert.ToInt32((3.0 / 25.4) * 100)
            Else
                'PrintDocument1.DefaultPageSettings.Margins.Bottom = PrintDocument1.DefaultPageSettings.PaperSize.Height - bmp.Height
                PrintDocument1.DefaultPageSettings.Margins.Bottom = PrintDocument1.DefaultPageSettings.PaperSize.Height - tp(tabpagecount).Height

            End If
            .Document = PrintDocument1
            If printdialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
                PrintDocument1.Print()
            End If
        End With

    End Sub


    Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
        bmp = New Bitmap(tp(tabpagecount).Width, tp(tabpagecount).Height)
        tp(tabpagecount).DrawToBitmap(bmp, tp(tabpagecount).DisplayRectangle)

        tabpagecount += 1
        e.Graphics.DrawImage(bmp, e.MarginBounds)

        If tabpagecount < tp.Length Then
            e.HasMorePages = True
        Else
            e.HasMorePages = False
            bmp = Nothing
        End If
    End Sub

End Class


Any help is greatly appreciated.

Regards,
Greg
 
Where in your code do you tell the tabpage tp() what is on each tab-page?

If you define a tabcontrol on your form, fill it with controls and data, then print this tabcontrol, your code should work fine, and so it does, doen't it?

The tp() you print in your code shown hasn't got anything on it, so it prints a blank, I suppose.

If I miss something, tell me, and I will look further.

Good luck,

Joris,
author of Developers Challenges
 
thanks for reply

the code I posted earlier is in a class PrintMe
here is what I do on my form on which my usercontrol with tabcontrol and tabpages reside!.

Hope this is more clear now.

Greg

VB.NET:
Private Sub BtnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnPrint.Click
        Dim _PrintMe As New PrintMe
        If Me._UcReportPreview.TabControl1.TabPages.Count > 0 Then
            ReDim _PrintMe.tp(_UcReportPreview.TabControl1.TabPages.Count - 1)
            If _UcReportPreview.TpPS IsNot Nothing Then
                _PrintMe.tp(1) = _UcReportPreview.TpPS
            End If
            If _UcReportPreview.TpSC IsNot Nothing Then
                _PrintMe.tp(0) = _UcReportPreview.TpSC
            End If
            _PrintMe.Print()
        End If
End sub

Where in your code do you tell the tabpage tp() what is on each tab-page?

If you define a tabcontrol on your form, fill it with controls and data, then print this tabcontrol, your code should work fine, and so it does, doen't it?

The tp() you print in your code shown hasn't got anything on it, so it prints a blank, I suppose.

If I miss something, tell me, and I will look further.

Good luck,

Joris,
author of Developers Challenges
 
What I found when testing this was that the TabPage didn't have to be visible/selected at the time of printing, but it had to be 'shown' at least once during runtime before DrawToBitmap would draw it. So adding this loop in Form.Load resolved that (even though nothing is really shown at Load event).
VB.NET:
For Each page As TabPage In Me.TabControl1.TabPages
    Me.TabControl1.SelectedTab = page
Next
Me.TabControl1.SelectedTab = TabPage1
 
What I found when testing this was that the TabPage didn't have to be visible/selected at the time of printing, but it had to be 'shown' at least once during runtime before DrawToBitmap would draw it. So adding this loop in Form.Load resolved that (even though nothing is really shown at Load event).
VB.NET:
For Each page As TabPage In Me.TabControl1.TabPages
    Me.TabControl1.SelectedTab = page
Next
Me.TabControl1.SelectedTab = TabPage1

This is it!
I knew posting a question here will give a solution :D I tried to work this out for two days now without a success.
Thank you very very much!...


Regards,
Greg
 
I was a little fast with my previous reply... it isn't 100% yet.

This works when I show a form with usercontrol on which I have tabcontrol and more than 1 tabpage. So it prints all tabpages although I only have first visible without clicking and showing any other tabpage.

But If I dynamically create usercontrol and do everything except bind it to a form, it still prints only blank pages.

this is the code where i dynamically prepare data on a usercontrol.


VB.NET:
 Private Sub BtnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnPrint.Click
        Dim _ucDataView As ucDataView
        For Each row As DataGridViewRow In DgvLoadedFiles.Rows
            If row.Cells(1).Value = True Or row.Cells(2).Value = True Or row.Cells(3).Value = True Then
                For Each ctr As Control In Frm_Main.TbcViewer.TabPages(row.Index + 1).Controls
                    If TypeOf ctr Is ucDataView Then
                        _ucDataView = DirectCast(ctr, ucDataView)
                        'Dim fp As New Frm_Preview
                        Dim _PrintMe As New PrintMe
                        Dim _ucreportpreview As New ucReportPreview
                        Dim dv As DataView = _ucDataView.DgvStream.DataSource
                        _ucreportpreview.ds = dv.Table.DataSet
                        _ucreportpreview.TabsEnabled(0) = row.Cells(1).Value
                        _ucreportpreview.TabsEnabled(1) = row.Cells(2).Value
                        _ucreportpreview.TabsEnabled(2) = row.Cells(3).Value
                                               _ucreportpreview.Init()
                        For Each page As TabPage In _ucreportpreview.TabControl1.TabPages
                            _ucreportpreview.TabControl1.SelectedTab = page
                        Next
                        _ucreportpreview.TabControl1.SelectedIndex = 0

                        'Print(_ucreportpreview)
                        ReDim _PrintMe.tp(_ucreportpreview.TabControl1.TabPages.Count - 1)
                        Dim c As Integer = 0
                        If row.Cells(1).Value Then
                            _PrintMe.tp(c) = _ucreportpreview.TpDS
                            c += 1
                        End If
                        If row.Cells(2).Value Then
                            _PrintMe.tp(c) = _ucreportpreview.TpSC
                            c += 1
                        End If
                        If row.Cells(3).Value Then
                            _PrintMe.tp(c) = _ucreportpreview.TpPS
                            c += 1
                        End If
                        '_PrintMe.tc = _ucreportpreview.TabControl1
                        _PrintMe.Print()
                    End If
                Next
            End If
        Next
    End Sub

Thanks,
Greg
 
Call uc.CreateControl() then loop the SelectedTab. All pages should now DrawToBitmap.
 
Call uc.CreateControl() then loop the SelectedTab. All pages should now DrawToBitmap.

I already managed this with adding a line _ucreportpreview.TabControl1.SelectedTab.Show()
in the loop you suggested earlier...but awsn't sure if it was the right way so I will stick with _ucreportpreview.CreateControl() wich also works.

I have one more problem.
on the user control there are tabpages (on 1 I have datagridview and few labels) on second there is a graph few labels and textboxes....if I only show the second tabpage and print it the textboxes are filled in but if I show both tabpages or do this dynamically textboxes are empty although graph draws as it is supposed to and labels have changed text and color.

any Idea what could be wrong here...is there something special about textboxes and printing?

I only noticed this an hour ago so I haven't done much research. I will post a solution if I find one.

Thanks for all the help.

Regards,
Grega


Thanks for all your help
 
I have one more problem.
on the user control there are tabpages (on 1 I have datagridview and few labels) on second there is a graph few labels and textboxes....if I only show the second tabpage and print it the textboxes are filled in but if I show both tabpages or do this dynamically textboxes are empty although graph draws as it is supposed to and labels have changed text and color.
I thought the idea here was that you didn't really show the control or any content on it. With the above scenario with a "detached" usercontrol instance with a tabcontrol and multiple tabpages I added a textbox and sets its Text, without that tabpage being currently selected DrawToBitmap included the textbox with text also. So from how I see it the procedure works. Btw, it didn't matter if I set the text before or after doing the SelectedTab loop.
 
I thought the idea here was that you didn't really show the control or any content on it. With the above scenario with a "detached" usercontrol instance with a tabcontrol and multiple tabpages I added a textbox and sets its Text, without that tabpage being currently selected DrawToBitmap included the textbox with text also. So from how I see it the procedure works. Btw, it didn't matter if I set the text before or after doing the SelectedTab loop.

I didn't make all this very clear I think, sorry for that.
I load the filenames into a datagridview:
Then I have two possible scenarios.
1. I click on a filename and make a preview of the report (in this case I show the form with my usercontrol)...It shows all data in textboxes no matter how many tabs are selected...but when I print I this preview of the report the textboxes are filled in only If the tab(second one) was actually clicked and shown. (shown is if only second tab is selected or if I click it and show it in the preview).

2. I iterate trough all rows in datagridview and print all filenames that have at least one checkbox(define which tab is filled) selected.
In this case I never get textboxes filled.

As I see it the problem is similar as the one I had that printed tabs were blank if I didn't show them, until I used your solution, just that this happens to textboxes only. Weird to me is that labels are normally filled and updated (text and color)

Regards,
grega
 
One more info update.

I was testing a little bit now, and I put a new textbox on the tabpage, and filled in text property ("test1")...

And tried to print it, but the textbox is empty when printed and control was not shown!

But it is filled if I show it first (report preview).

Hope this gives someone an idea what could be wrong, because I am all out.

Regards,
Grega
 
I'm not able to reproduce any problems with Textboxes in relation to the above.
 
I'm not able to reproduce any problems with Textboxes in relation to the above.


I don't know what is the problem here...Might be something with drawtobitmap (I read it has some problems with richtextbox and maybe there are problems with textbox also, or its my VS2005 or etc.

I created a new blank usercontrol and put just one textbox on with some text in it...result is the same.

My solution for now - change all textboxes with labels - works OK. :)


Thanks,

Grega
 
maybe there are problems with textbox also
I tested this using several Textboxes in any combination I can think of and they all print ok here. Regarding DrawToBitmap and RichTextBox that is not related to Textbox control.
 
by PM said:
Thanks for all your help.

I have a favor to ask, could you send me the project where you were testing if textbox is printed, so I can run it in my VS. I want to eliminate the VS studio as a potential cause of problems.

Best regards,
Grega
Test project attached.
 

Attachments

  • vbnet35-PreviewTest.zip
    23.6 KB · Views: 36
Back
Top