Hi,
I'm printing a VB.NET form using BitBlt API my code as follows:
' create a printing component
Private WithEvents pd As Printing.PrintDocument
' storage for form image
Dim formImage As Bitmap
' create API prototype
Private Declare Function BitBlt Lib "gdi32.dll" Alias _
"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 Long
Private Sub GetFormImageToPrint()
Dim g As Graphics = Me.CreateGraphics()
Dim formSize As Size = Me.Size
formImage = New Bitmap(formSize.Width, formSize.Height, g)
Dim mg As Graphics = Graphics.FromImage(formImage)
Dim dc1 As IntPtr = g.GetHdc
Dim dc2 As IntPtr = mg.GetHdc
' added code to compute and capture the form
' title bar and borders
Dim widthDiff As Integer = _
(Me.Width - Me.ClientRectangle.Width)
Dim heightDiff As Integer = _
(Me.Height - Me.ClientRectangle.Height)
Dim borderSize As Integer = widthDiff \ 2
Dim heightTitleBar As Integer = heightDiff - borderSize
BitBlt(dc2, 0, 0, _
Me.ClientRectangle.Width + widthDiff, _
Me.ClientRectangle.Height + heightDiff, dc1, _
0 - borderSize, 0 - heightTitleBar, 13369376)
g.ReleaseHdc(dc1)
mg.ReleaseHdc(dc2)
End Sub
' Callback from PrintDocument component to do the actual printing
Private Sub pd_PrintPage(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) _
Handles pd.PrintPage
Dim sz As SizeF = formImage.GetBounds(GraphicsUnit.Pixel).Size
'scale image if it unscaled doesn't fit marginbounds
If sz.Height > e.MarginBounds.Size.Height Or sz.Width > e.MarginBounds.Size.Width Then
Dim scaleheight As Double = sz.Height / e.MarginBounds.Size.Height
Dim scalewidth As Double = sz.Width / e.MarginBounds.Size.Width
Dim scale As Double = Math.Max(scalewidth, scaleheight)
scalewidth = sz.Width / scale
scaleheight = sz.Height / scale
sz = New SizeF(CSng(scalewidth), CSng(scaleheight))
Dim scalebounds As New RectangleF(e.MarginBounds.Location, sz)
'draw scaled image
e.Graphics.DrawImage(formImage, scalebounds)
Else
'draw unscaled image
e.Graphics.DrawImageUnscaled(formImage, e.MarginBounds)
End If
'e.Graphics.DrawImage(formImage, 0, 0)
End Sub
Private Sub mnuPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuPrint.Click
PrintScr()
End Sub
Private Sub PrintScr()
Try
GetFormImageToPrint()
' create an instance of the PrintDocument component
pd = New Printing.PrintDocument
If PrintDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
pd.PrinterSettings = PrintDialog1.PrinterSettings
pd.Print()
End If
Catch ex As Exception
ErrorMsg(" Error number:" & Err.Number & Chr(13) & "Error Description:" & Err.Description, ParentForm.Text)
End Try
Exit Sub
End Sub
the problem I have is the File menu (mnuFile which contains mnuPrint and about 5 other mnu's) remains on screen thus being also printed. Any ideas how I can close the menu before GetFormImageToPrint is executed.
Cheers
Darren
Hi,
I think you can't, because your making a printscreen and that will be printing.
What you need is the create a bitmap that only prints the client area.
here's an example:
Private Declare Auto Function BitBlt Lib "gdi32.dll" (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
Private Const SRCCOPY As Integer = &HCC0020
' Variables used to print.
Private m_PrintBitmap As Bitmap
Private WithEvents m_PrintDocument As PrintDocument
' Print the picture.
Private Sub btnPrint_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnPrint.Click
' Copy the form's image into a bitmap.
m_PrintBitmap = GetFormImage()
' Make a PrintDocument and print.
m_PrintDocument = New PrintDocument
m_PrintDocument.Print()
End Sub
Private Function GetFormImage() As Bitmap
' Get this form's Graphics object.
Dim me_gr As Graphics = Me.CreateGraphics
' Make a Bitmap to hold the image.
Dim bm As New Bitmap(Me.ClientSize.Width, _
Me.ClientSize.Height, me_gr)
Dim bm_gr As Graphics = me_gr.FromImage(bm)
Dim bm_hdc As IntPtr = bm_gr.GetHdc
' Get the form's hDC. We must do this after
' creating the new Bitmap, which uses me_gr.
Dim me_hdc As IntPtr = me_gr.GetHdc
' BitBlt the form's image onto the Bitmap.
BitBlt(bm_hdc, 0, 0, Me.ClientSize.Width, _
Me.ClientSize.Height, _
me_hdc, 0, 0, SRCCOPY)
me_gr.ReleaseHdc(me_hdc)
bm_gr.ReleaseHdc(bm_hdc)
' Return the result.
Return bm
End Function
' Print the form image.
Private Sub m_PrintDocument_PrintPage(ByVal sender As _
Object, ByVal e As _
System.Drawing.Printing.PrintPageEventArgs) Handles _
m_PrintDocument.PrintPage
' Draw the image centered.
Dim x As Integer = e.MarginBounds.X + _
(e.MarginBounds.Width - m_PrintBitmap.Width) \ 2
Dim y As Integer = e.MarginBounds.Y + _
(e.MarginBounds.Height - m_PrintBitmap.Height) \ 2
e.Graphics.DrawImage(m_PrintBitmap, x, y)
' There's only one page.
e.HasMorePages = False
End SubThanks for input guys....
adatapost, I hid the MenuBar but it still printed the unwanted menu.
Luc001, I replaced my code with yours but it still printed the unwanted menu.
VB6 worked a treat using the PrintWindowVB api. But using in .Net started causing problems ie the Unwanted menu hence why I started looking at BitBlt api.
Cheers
Darren
Correct me if I am wrong. Are you turn off Control menu? I have turn off visible property (say MenuStrip1 control) and got output without menu. I have also used VB.NET PrintForm utility control and got same result (In this case you can turn off controls menu).
I have used the code which was in previous posts and also from the - http://www.knowdotnet.com/articles/printform.html
MenuStrip1.Visible = False
GetFormImage()
pd.Print()
Code using PrintForm control.
MenuStrip1.Visible = False
PrintForm1.PrintAction = Printing.PrintAction.PrintToPreview
PrintForm1.Print(Me, PowerPacks.Printing.PrintForm.PrintOption.ClientAreaOnly)Hi,
I found a way how to hide the Menu.
I did it in VB 2003 and added a MainMenu to it.
Now to hide the mainmenu I've used MainMenu1.Dispose like this.
Private Function GetFormImage() As Bitmap
' Get this form's Graphics object.
Dim me_gr As Graphics = Me.CreateGraphics
' Make a Bitmap to hold the image.
Dim bm As New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height, me_gr)
Dim bm_gr As Graphics = me_gr.FromImage(bm)
Dim bm_hdc As IntPtr = bm_gr.GetHdc
' Get the form's hDC. We must do this after
' creating the new Bitmap, which uses me_gr.
Dim me_hdc As IntPtr = me_gr.GetHdc
' BitBlt the form's image onto the Bitmap.
BitBlt(bm_hdc, 0, 0, Me.ClientSize.Width, Me.ClientSize.Height, _
me_hdc, 0, 0, SRCCOPY)
me_gr.ReleaseHdc(me_hdc)
bm_gr.ReleaseHdc(bm_hdc)
' Return the result.
Return bm
MainMenu1.Dispose() ' Add this part of code into the function
End FunctionHi,,
adatapost, the PrintForm works great to a certain extent and I dont have to hide the the Menu. However is there a way I can scale the image to fit on one page and automatically adjust the orientation?
I was doing this:
Private Sub Pd_BeginPrint(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles pd.BeginPrint
pd.DefaultPageSettings.Landscape = False
Dim sz As SizeF = formImage.GetBounds(GraphicsUnit.Pixel).Size
Dim pw As Integer = pd.DefaultPageSettings.Bounds.Width
pw -= pd.DefaultPageSettings.Margins.Left
pw -= pd.DefaultPageSettings.Margins.Right
'landscape if image unscaled is wider than marginbounds width
If sz.Width > pw Then pd.DefaultPageSettings.Landscape = True
End Sub
and this for scaling:
Private Sub pd_PrintPage(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) _
Handles pd.PrintPage
Dim sz As SizeF = formImage.GetBounds(GraphicsUnit.Pixel).Size
'scale image if it unscaled doesn't fit marginbounds
If sz.Height > e.MarginBounds.Size.Height Or sz.Width > e.MarginBounds.Size.Width Then
Dim scaleheight As Double = sz.Height / e.MarginBounds.Size.Height
Dim scalewidth As Double = sz.Width / e.MarginBounds.Size.Width
Dim scale As Double = Math.Max(scalewidth, scaleheight)
scalewidth = sz.Width / scale
scaleheight = sz.Height / scale
sz = New SizeF(CSng(scalewidth), CSng(scaleheight))
Dim scalebounds As New RectangleF(e.MarginBounds.Location, sz)
'draw scaled image
e.Graphics.DrawImage(formImage, scalebounds)
Else
'draw unscaled image
e.Graphics.DrawImageUnscaled(formImage, e.MarginBounds)
End If
'e.Graphics.DrawImage(formImage, 0, 0)
End Sub
Luc001, Thanks but the Dispose will destroy the Menu
Thanks for your help on this:)
Darren
In your Print event, simply add the form update method
Private Sub PrintToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PrintToolStripMenuItem.Click
Me.Update()
Me.PrintForm1.Print()
End Sub
It will force the redraw of the form prior to executing the print command. The problem is that the PrintForm control takes over immediately and the form has not yet had time to redraw.