Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter
 
 
 
MSDN Visual Basic Community
 
 
 
 
 
TitlePrint a Window in WPF/XAML using Visual Basic 2008
DescriptionThis example shows how to print a Window in WPF/XAML using Visual Basic 2008.
Keywordsprint, print Window, PrintForm, Visual Basic 2008
CategoriesWPF, 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).

 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated