Is there a simple way to send the graphic contents of form to prin

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Let's say I have a form that has all kinds of controls on it (not just text).
Is there a simple way that I can send the entire contents of the form to a
printer? I've looked at things such as PrintDocument and using the
DrawToBitmap method of the form. Is this the correct path to follow?
 
Hi Michael,

Try this:
-------------------------CODE STARTS------------------------------
Public Class Form1
Dim img As Bitmap
Dim WithEvents pd As Printing.PrintDocument

'-1- API CALL TO BITBLT
<Runtime.InteropServices.DllImport("gdi32.DLL", EntryPoint:="BitBlt",
SetLastError:=True, CharSet:=Runtime.InteropServices.CharSet.Unicode,
ExactSpelling:=True,
CallingConvention:=Runtime.InteropServices.CallingConvention.StdCall)> _

'Function to convert the form to an image
Function CaptureForm1() As Bitmap
Dim g1 As Graphics = Me.CreateGraphics()
Dim MyImage = New Bitmap(Me.ClientRectangle.Width,
(Me.ClientRectangle.Height), g1)
Dim g2 As Graphics = Graphics.FromImage(MyImage)
Dim dc1 As IntPtr = g1.GetHdc()
Dim dc2 As IntPtr = g2.GetHdc()
'BitBlt is an API Call as defined above at -1-
BitBlt(dc2, 0, 0, Me.ClientRectangle.Width,
(Me.ClientRectangle.Height), dc1, 0, 0, 13369376)
g1.ReleaseHdc(dc1)
g2.ReleaseHdc(dc2)

Return MyImage
End Function

Private Shared Function BitBlt(ByVal hdcDest As IntPtr, ByVal nXDest As
Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As
Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As
Integer, ByVal dwRop As System.Int32) As Boolean
End Function

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
img = CaptureForm1()
pd = New Printing.PrintDocument

'Page is sent to the default printer for printing
'Use Printing.PrinterSettings object to customize the print behavior
pd.Print()
End Sub

Sub pd_PrintPage(ByVal sender As Object, ByVal e As
Printing.PrintPageEventArgs) Handles pd.PrintPage
Dim x As Integer = e.MarginBounds.X
Dim y As Integer = e.MarginBounds.Y
e.Graphics.DrawImage(img, x, y)
e.HasMorePages = False
End Sub
End Class
---------------------------CODE ENDS-------------------------------

The following article provides another approach:
http://www.codeproject.com/useritems/MCLFormPrintControl.asp

I hope this is helpful!
-Rajneesh

www.ComponentOne.com
 
Oh the word wrap messes it all up!

This is word-wrap safe :)

-------------------------CODE STARTS--------------------------------
Dim img As Bitmap
Dim WithEvents pd As Printing.PrintDocument

'-1- API CALL TO BITBLT
'Function to convert the form to an image
Function CaptureForm1() As Bitmap
Dim g1 As Graphics = Me.CreateGraphics()
Dim MyImage = New Bitmap(Me.ClientRectangle.Width, _
(Me.ClientRectangle.Height), g1)
Dim g2 As Graphics = Graphics.FromImage(MyImage)
Dim dc1 As IntPtr = g1.GetHdc()
Dim dc2 As IntPtr = g2.GetHdc()
'BitBlt is an API Call as defined above at -1-
BitBlt(dc2, 0, 0, Me.ClientRectangle.Width, _
(Me.ClientRectangle.Height), dc1, 0, 0, 13369376)
g1.ReleaseHdc(dc1)
g2.ReleaseHdc(dc2)

Return MyImage
End Function

<Runtime.InteropServices.DllImport("gdi32.DLL", _
EntryPoint:="BitBlt", SetLastError:=True, _
CharSet:=Runtime.InteropServices.CharSet.Unicode, _
ExactSpelling:=True, _

CallingConvention:=Runtime.InteropServices.CallingConvention.StdCall)> _
Private Shared Function BitBlt(ByVal hdcDest As IntPtr, _
ByVal nXDest As Integer, ByVal nYDest As Integer, _
ByVal nWidth As Integer, ByVal nHeight As Integer, _
ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, _
ByVal nYSrc As Integer, ByVal dwRop As System.Int32) As Boolean
End Function

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
img = CaptureForm1()
pd = New Printing.PrintDocument

'Page is sent to the default printer for printing
'Use Printing.PrinterSettings object to customize the print behavior
pd.Print()
End Sub

Sub pd_PrintPage(ByVal sender As Object, _
ByVal e As Printing.PrintPageEventArgs) Handles pd.PrintPage
Dim x As Integer = e.MarginBounds.X
Dim y As Integer = e.MarginBounds.Y
e.Graphics.DrawImage(img, x, y)
e.HasMorePages = False
End Sub
---------------------------CODE ENDS---------------------------------

-Rajneesh
 
I'll give this a try. I guess that the BitBlt copies the data from the source
(display context?) to the destination. I can't really see how you have
identifed the source. Each looks like a clean slate to me (sorry, haven't
done graphics in a while)--
Michael
 
Ok. I get it now.

MyImage in a new bitmap with the size and resolution of the client window.
g2 is a graphics object which allows you to draw on MyImage
The mighty BitBlt copies the bits from the client dc to the dc of the MyImage
Return MyImage

That's elegant.

I see that you release the dc's. Should you not also dispose of the g's?
(g1.Dispose and g2.Dispose)

Is there no other way to copy bits without reaching to the API?

(BTW I'm a big C1 fan)
 
You are right, we should have disposed it. Can cause memory stack up.

And glad to hear about C1 :-)
-Rajneesh
 
Let's say I have a form that has all kinds of controls on it (not just text).
Is there a simple way that I can send the entire contents of the form to a
printer? I've looked at things such as PrintDocument and using the
DrawToBitmap method of the form. Is this the correct path to follow?

I have an article/component on Codeproject : "Form Print Control"
http://www.codeproject.com/useritems/MCLFormPrintControl.asp that
prints the controls on the form according to design time settings
(Font, position etc.)
It uses Control.DrawToBitmap to get a picture of any control or uses
the Image property if that is there.

Hope this helps
Duncan
 
Back
Top