|
|
Title | Print a Window in WPF/XAML using Visual Basic 2008 |
Description | This example shows how to print a Window in WPF/XAML using Visual Basic 2008. |
Keywords | print, print Window, PrintForm, Visual Basic 2008 |
Categories | WPF, VB.NET |
|
|
This is basically a version of PrintForm for WPF.
The PrintDialog class can display a print dialog and its PrintVisual method can easily print a Window or other visual control. Unfortunately the result is positioned at the extreme upper left corner of the printed page. Because most printers cannot print all the way to the edge of the paper, that means the result is clipped at the top and left.
This program centers a Window's image, optionally enlarging it.
First, add references to System.Printing and ReachFramework (another fine, intuitive name brought to you by WPF ;-). This example also imports System.Windows.Shapes and System.Windows.Media.Effects to make it easier to produce the results it generates.
When you click the Print Centered button, the following code creates a new PrintDialog and displays it. If the user selects a printer and clicks OK, the code calls PrintWindowCentered to do the actual printing.
|
|
Dim pd As New PrintDialog()
If pd.ShowDialog() Then
PrintWindowCentered(pd, Me, "New Customer", Nothing)
End If
|
|
When you click the Print Stretched button, the following code calls PrintWindowCentered. The final argument is a margin around the edges of the paper. The image of the Window will be enlarged as much as possible to fit within this margin.
|
|
Dim pd As New PrintDialog()
If pd.ShowDialog() Then
PrintWindowCentered(pd, Me, "New Customer", New Thickness(50))
End If
|
|
The PrintVisual method prints a visual control in the paper's upper left corner. While you can't change that (at least as far as I know), you can create new controls that position the image of the control where you want it. Subroutine PrintWindowCentered does that.
The routine first creates a Grid control that fills the entire printed page and places a Viewbox centered inside it.
If the margin parameter is Nothing, then the code sets the Viewbox's Stretch property to None so it won't resize the Window's image.
If the margin is not Nothing, then the code sets the Viewbox's Stretch property to Uniform so it will stretch the Window's
image as much as possible without distorting it. It also sets the Viewbox's Margin property to the desired margin so the Viewbox is enlarged to fill the paper, minus the margin.
Next the code makes a VisualBrush from the Window. That makes the brush contain an image of the Window.
The code then places a Rectangle inside the Viewbox, filling it with the VisualBrush. This makes the Rectangle display an image of the Window. The code adds a black border and a drop shadow.
Next the code calls thue Grid's Arrange method to make it arrange and render its children recursively. If you don't do this, then the printout is blank.
Finally thue code calls the PrintDialog's PrintVisual method to print the Grid and its contents.
|
|
' Print a Window centered on the printer.
Private Sub PrintWindowCentered(ByVal pd As PrintDialog, ByVal win As Window, ByVal title As String, ByVal margin As Thickness?)
' Make a Grid to hold the contents.
Dim drawing_area As New Grid()
drawing_area.Width = pd.PrintableAreaWidth
drawing_area.Height = pd.PrintableAreaHeight
' Make a Viewbox to stretch the result if necessary.
Dim view_box As New Viewbox()
drawing_area.Children.Add(view_box)
view_box.HorizontalAlignment = Windows.HorizontalAlignment.Center
view_box.VerticalAlignment = Windows.VerticalAlignment.Center
If margin Is Nothing Then
' Center without resizing.
view_box.Stretch = Windows.Media.Stretch.None
Else
' Resize to fit the margin.
view_box.Margin = margin.Value
view_box.Stretch = Windows.Media.Stretch.Uniform
End If
' Make a VisualBrush holding an image of the Window's contents.
Dim vis_br As New VisualBrush(win)
' Make a rectangle the size of the Window.
Dim win_rect As New Rectangle()
view_box.Child = win_rect
win_rect.Width = win.Width
win_rect.Height = win.Height
win_rect.Fill = vis_br
win_rect.Stroke = Brushes.Black
win_rect.BitmapEffect = New DropShadowBitmapEffect()
' Arrange to produce output.
Dim rect As New Rect(0, 0, _
pd.PrintableAreaWidth, pd.PrintableAreaHeight)
drawing_area.Arrange(rect)
' Print it.
pd.PrintVisual(drawing_area, title)
End Sub
|
|
Note that WPF doesn't have a print preview dialog. I guess it is assumed that you are printing something that you have already displayed on the screen so you don't need a preview. (You can also print things generated in code but it's more work and in that casae you'll have to provide your own preview.
However, you can print using the "Microsoft XPS Document Writer" and then view the resulting .xps file using the XPS Viewer or Internet Explorer (version 7 works--I don't know about earlier versions).
|
|
|
|
|
|