Printing in WPF port for .NET (#1156)

* Initial files

* update toc

* Content update - print-xps-files (user story 1861941) (#1151)

* Add C# and VB sample code projects

* Fix comments

* Update C# and VB code

* Add article

* Further edits

* Reviewer requested edits

* Further edits

* Use xref to link to API

* Minor edits

* Content update - invoke-print-dialog (user story 1861941) (#1141)

* Content update including C# WPF project

* Fix link

* Remove test code

* Further doc and C# sample edits

* Add feature: printing with no print dialog

* Separate out specific page range print functionality

* Cleanup comments

* UI tweaks

* Add VB sample code project

* Code file formatting

* Update dotnet-desktop-guide/net/wpf/documents/how-to-display-print-dialog.md

Co-authored-by: Andy (Steve) De George <[email protected]>

* Add page range printing

* Minor edits

* Update dotnet-desktop-guide/net/wpf/documents/snippets/how-to-display-print-dialog/csharp/MainWindow.xaml.cs

Co-authored-by: Andy (Steve) De George <[email protected]>

* Update dotnet-desktop-guide/net/wpf/documents/how-to-display-print-dialog.md

Co-authored-by: Andy (Steve) De George <[email protected]>

* Promote example headings

* Reorganize and add detail

* Minor edits

* Add detail

* Further edits

* Further edits

* Add resource links

* Add alternative API suggestions to a tip

* Minor edit

Co-authored-by: Andy (Steve) De George <[email protected]>

* Content update - print-overview (user story 1861941) (#1153)

* Add C# and VB sample code projects

* Add article

* Add redirects

Co-authored-by: Tris Shores <[email protected]>
This commit is contained in:
Andy (Steve) De George
2021-09-24 16:16:55 -04:00
committed by GitHub
co-authored by Tris Shores
parent e96218f17e
commit bdd178c010
42 changed files with 2295 additions and 452 deletions
@@ -0,0 +1,9 @@
<Application x:Class="CodeSampleCsharp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CodeSampleCsharp"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace CodeSampleCsharp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}
@@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>
@@ -0,0 +1,16 @@
<Window x:Class="CodeSampleCsharp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Print an XPS file" Height="234" Width="509">
<Grid Margin="0,0,0,-6" Loaded="Grid_Loaded">
<Label Content="Select an XPS file" HorizontalAlignment="Left" Margin="27,12,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="339"/>
<Button Content="Print" HorizontalAlignment="Left" Margin="32,148,0,0" FontSize="14" Width="51" x:Name="btnPrint" Height="28" VerticalAlignment="Top" Click="BtnPrint_Click"/>
<ComboBox x:Name="cmbPrinters" HorizontalAlignment="Left" Margin="32,90,0,0" VerticalAlignment="Top" Width="372"/>
<Label Content="Select a printer" HorizontalAlignment="Left" Margin="27,66,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="339"/>
<Button Content="Browse" HorizontalAlignment="Left" Margin="428,35,0,0" VerticalAlignment="Top" Width="48" x:Name="btnBrowse" Height="20" Click="BtnBrowse_Click"/>
<TextBox HorizontalAlignment="Left" Margin="32,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="391" FontSize="14" x:Name="txtXpsFilePath" Height="21"/>
</Grid>
</Window>
@@ -0,0 +1,186 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Printing;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;
using Microsoft.Win32;
namespace CodeSampleCsharp
{
/// <summary>
/// Interaction logic for MainWindow.xaml.
/// </summary>
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
foreach (PrintQueue printQueue in GetPrintQueues())
{
// Add printers that have at least one relevant print options.
PrintCapabilities printCapabilites = printQueue.GetPrintCapabilities();
if (printCapabilites.CollationCapability.Contains(Collation.Collated) ||
printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge) ||
printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft))
cmbPrinters.Items.Add(printQueue.Name);
}
// Select the first printer.
if (cmbPrinters.Items.Count > 0)
cmbPrinters.SelectedIndex = 0;
}
private void BtnBrowse_Click(object sender, RoutedEventArgs e)
{
// Configure an open file dialog box.
OpenFileDialog openFileDialog = new()
{
FileName = "Document",
DefaultExt = ".xps",
Filter = "Text documents (.xps)|*.xps"
};
// Show open file dialog box.
bool? result = openFileDialog.ShowDialog();
// Process open file dialog box results.
if (result == true)
{
// Show selected XPS file path.
txtXpsFilePath.Text = openFileDialog.FileName;
}
}
private void BtnPrint_Click(object sender, RoutedEventArgs e)
{
// Check the XPS file exists.
if (!File.Exists(txtXpsFilePath.Text))
{
MessageBox.Show("First select an XPS file.");
return;
}
// Get the print queue for the selected printer.
PrintQueue selectedPrintQueue = GetPrintQueues().SingleOrDefault(x => Equals(x.Name, cmbPrinters.SelectedItem.ToString()));
// Get a print ticket with modified print options for the selected printer.
PrintTicket printTicket = GetPrintTicket(selectedPrintQueue);
// Send the XPS document to the selected printer.
PrintXpsDocumentAsync(txtXpsFilePath.Text, selectedPrintQueue, printTicket);
// Show modified print options.
List<string> optionList = new();
if (printTicket.Collation == Collation.Collated)
optionList.Add("Collated");
if (printTicket.Duplexing == Duplexing.TwoSidedLongEdge)
optionList.Add("TwoSidedLongEdge");
if (printTicket.Stapling == Stapling.StapleDualLeft)
optionList.Add("StapleDualLeft");
var options = optionList.Count > 0 ? string.Join(", ", optionList) : "None";
// Show result message.
MessageBox.Show($"Sent {Path.GetFileName(txtXpsFilePath.Text)} to the printer.\r\nPrint options: {options}");
}
// <GetPrintQueues>
/// <summary>
/// Return a collection of print queues, which individually hold the features or states
/// of a printer as well as common properties for all print queues.
/// </summary>
/// <returns>A collection of print queues.</returns>
public static PrintQueueCollection GetPrintQueues()
{
// Create a LocalPrintServer instance, which represents
// the print server for the local computer.
LocalPrintServer localPrintServer = new();
// Get the default print queue on the local computer.
//PrintQueue printQueue = localPrintServer.DefaultPrintQueue;
// Get all print queues on the local computer.
PrintQueueCollection printQueueCollection = localPrintServer.GetPrintQueues();
// Return a collection of print queues, which individually hold the features or states
// of a printer as well as common properties for all print queues.
return printQueueCollection;
}
// </GetPrintQueues>
// <GetPrintTicket>
/// <summary>
/// Returns a print ticket, which is a set of instructions telling a printer how
/// to set its various features, such as duplexing, collating, and stapling.
/// </summary>
/// <param name="printQueue">The print queue to print to.</param>
/// <returns>A print ticket.</returns>
public static PrintTicket GetPrintTicket(PrintQueue printQueue)
{
PrintCapabilities printCapabilites = printQueue.GetPrintCapabilities();
// Get a default print ticket from printer.
PrintTicket printTicket = printQueue.DefaultPrintTicket;
// Modify the print ticket.
if (printCapabilites.CollationCapability.Contains(Collation.Collated))
printTicket.Collation = Collation.Collated;
if (printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge))
printTicket.Duplexing = Duplexing.TwoSidedLongEdge;
if (printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft))
printTicket.Stapling = Stapling.StapleDualLeft;
// Returns a print ticket, which is a set of instructions telling a printer how
// to set its various features, such as duplexing, collating, and stapling.
return printTicket;
}
// </GetPrintTicket>
// <PrintXpsDocument>
/// <summary>
/// Asynchronously, add the XPS document together with a print ticket to the print queue.
/// </summary>
/// <param name="xpsFilePath">Path to source XPS file.</param>
/// <param name="printQueue">The print queue to print to.</param>
/// <param name="printTicket">The print ticket for the selected print queue.</param>
public static void PrintXpsDocumentAsync(string xpsFilePath, PrintQueue printQueue, PrintTicket printTicket)
{
// Create an XpsDocumentWriter object for the print queue.
XpsDocumentWriter xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue);
// Open the selected document.
XpsDocument xpsDocument = new(xpsFilePath, FileAccess.Read);
// Get a fixed document sequence for the selected document.
FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();
// Asynchronously, add the XPS document together with a print ticket to the print queue.
xpsDocumentWriter.WriteAsync(fixedDocSeq, printTicket);
}
/// <summary>
/// Synchronously, add the XPS document together with a print ticket to the print queue.
/// </summary>
/// <param name="xpsFilePath">Path to source XPS file.</param>
/// <param name="printQueue">The print queue to print to.</param>
/// <param name="printTicket">The print ticket for the selected print queue.</param>
public static void PrintXpsDocument(string xpsFilePath, PrintQueue printQueue, PrintTicket printTicket)
{
// Create an XpsDocumentWriter object for the print queue.
XpsDocumentWriter xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue);
// Open the selected document.
XpsDocument xpsDocument = new(xpsFilePath, FileAccess.Read);
// Get a fixed document sequence for the selected document.
FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();
// Synchronously, add the XPS document together with a print ticket to the print queue.
xpsDocumentWriter.Write(fixedDocSeq, printTicket);
}
// </PrintXpsDocument>
}
}
@@ -0,0 +1,9 @@
<Application x:Class="Application"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CodeSampleVb"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
@@ -0,0 +1,6 @@
Class Application
' Application-level events, such as Startup, Exit, and DispatcherUnhandledException
' can be handled in this file.
End Class
@@ -0,0 +1,11 @@
Imports System.Windows
'The ThemeInfo attribute describes where any theme specific and generic resource dictionaries can be found.
'1st parameter: where theme specific resource dictionaries are located
'(used if a resource is not found in the page,
' or application resource dictionaries)
'2nd parameter: where the generic resource dictionary is located
'(used if a resource is not found in the page,
'app, and any theme specific resource dictionaries)
<Assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)>
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<RootNamespace>CodeSampleVb</RootNamespace>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Import Include="System.Windows" />
<Import Include="System.Windows.Controls" />
<Import Include="System.Windows.Data" />
<Import Include="System.Windows.Documents" />
<Import Include="System.Windows.Input" />
<Import Include="System.Windows.Media" />
<Import Include="System.Windows.Media.Imaging" />
<Import Include="System.Windows.Navigation" />
<Import Include="System.Windows.Shapes" />
</ItemGroup>
</Project>
@@ -0,0 +1,16 @@
<Window x:Class="CodeSampleVb.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Print an XPS file" Height="234" Width="509">
<Grid Margin="0,0,0,-6" Loaded="Grid_Loaded">
<Label Content="Select an XPS file" HorizontalAlignment="Left" Margin="27,12,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="339"/>
<Button Content="Print" HorizontalAlignment="Left" Margin="32,148,0,0" FontSize="14" Width="51" x:Name="btnPrint" Height="28" VerticalAlignment="Top" Click="BtnPrint_Click"/>
<ComboBox x:Name="cmbPrinters" HorizontalAlignment="Left" Margin="32,90,0,0" VerticalAlignment="Top" Width="372"/>
<Label Content="Select a printer" HorizontalAlignment="Left" Margin="27,66,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="339"/>
<Button Content="Browse" HorizontalAlignment="Left" Margin="428,35,0,0" VerticalAlignment="Top" Width="48" x:Name="btnBrowse" Height="20" Click="BtnBrowse_Click"/>
<TextBox HorizontalAlignment="Left" Margin="32,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="391" FontSize="14" x:Name="txtXpsFilePath" Height="21"/>
</Grid>
</Window>
@@ -0,0 +1,191 @@
Imports System.IO
Imports System.Printing
Imports System.Windows.Xps
Imports System.Windows.Xps.Packaging
Imports Microsoft.Win32
Namespace CodeSampleVb
Partial Public Class MainWindow
Inherits Window
''' <summary>
''' Interaction logic for MainWindow.xaml
''' </summary>
Public Sub New()
InitializeComponent()
End Sub
Private Sub Grid_Loaded(sender As Object, e As RoutedEventArgs)
For Each printQueue As PrintQueue In GetPrintQueues()
' Add printers that have at least one relevant print options.
Dim printCapabilites As PrintCapabilities = printQueue.GetPrintCapabilities()
If printCapabilites.CollationCapability.Contains(Collation.Collated) _
OrElse printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge) _
OrElse printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft) Then
cmbPrinters.Items.Add(printQueue.Name)
End If
Next
' Select the first printer.
If cmbPrinters.Items.Count > 0 Then cmbPrinters.SelectedIndex = 0
End Sub
Private Sub BtnBrowse_Click(sender As Object, e As RoutedEventArgs)
' Configure an open file dialog box.
Dim openFileDialog As OpenFileDialog = New OpenFileDialog() With {
.FileName = "Document",
.DefaultExt = ".xps",
.Filter = "Text documents (.xps)|*.xps"
}
' Show open file dialog box.
Dim result As Boolean? = openFileDialog.ShowDialog()
' Process open file dialog box results.
If result = True Then
' Show selected XPS file path.
txtXpsFilePath.Text = openFileDialog.FileName
End If
End Sub
Private Sub BtnPrint_Click(sender As Object, e As RoutedEventArgs)
' Check the XPS file exists.
If Not File.Exists(txtXpsFilePath.Text) Then
MessageBox.Show("First select an XPS file.")
Return
End If
' Get the print queue for the selected printer.
Dim selectedPrintQueue As PrintQueue = GetPrintQueues().SingleOrDefault(Function(x) Equals(x.Name, cmbPrinters.SelectedItem.ToString()))
' Get a print ticket with modified print options for the selected printer.
Dim printTicket As PrintTicket = GetPrintTicket(selectedPrintQueue)
' Send the XPS document to the selected printer.
PrintXpsDocumentAsync(txtXpsFilePath.Text, selectedPrintQueue, printTicket)
' Show modified print options.
Dim optionList As List(Of String) = New List(Of String)()
If printTicket.Collation = Collation.Collated Then optionList.Add("Collated")
If printTicket.Duplexing = Duplexing.TwoSidedLongEdge Then optionList.Add("TwoSidedLongEdge")
If printTicket.Stapling = Stapling.StapleDualLeft Then optionList.Add("StapleDualLeft")
Dim options = If(optionList.Count > 0, String.Join(", ", optionList), "None")
' Show result message.
MessageBox.Show($"Sent {Path.GetFileName(txtXpsFilePath.Text)} to the printer.{vbCrLf}Print options: {options}")
End Sub
' <GetPrintQueues>
''' <summary>
''' Return a collection of print queues, which individually hold the features or states
''' of a printer as well as common properties for all print queues.
''' </summary>
''' <returns>A collection of print queues.</returns>
Public Shared Function GetPrintQueues() As PrintQueueCollection
' Create a LocalPrintServer instance, which represents
' the print server for the local computer.
Dim localPrintServer As LocalPrintServer = New LocalPrintServer()
' Get the default print queue on the local computer.
'Dim printQueue As PrintQueue = localPrintServer.DefaultPrintQueue
' Get all print queues on the local computer.
Dim printQueueCollection As PrintQueueCollection = localPrintServer.GetPrintQueues()
' Return a collection of print queues, which individually hold the features or states
' of a printer as well as common properties for all print queues.
Return printQueueCollection
End Function
' </GetPrintQueues>
' <GetPrintTicket>
''' <summary>
''' Returns a print ticket, which is a set of instructions telling a printer how
''' to set its various features, such as duplexing, collating, and stapling.
''' </summary>
''' <param name="printQueue">The print queue to print to.</param>
''' <returns>A print ticket.</returns>
Public Shared Function GetPrintTicket(printQueue As PrintQueue) As PrintTicket
Dim printCapabilites As PrintCapabilities = printQueue.GetPrintCapabilities()
' Get a default print ticket from printer.
Dim printTicket As PrintTicket = printQueue.DefaultPrintTicket
' Modify the print ticket.
If printCapabilites.CollationCapability.Contains(Collation.Collated) Then
printTicket.Collation = Collation.Collated
End If
If printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge) Then
printTicket.Duplexing = Duplexing.TwoSidedLongEdge
End If
If printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft) Then
printTicket.Stapling = Stapling.StapleDualLeft
End If
' Returns a print ticket, which is a set of instructions telling a printer how
' to set its various features, such as duplexing, collating, and stapling.
Return printTicket
End Function
' </GetPrintTicket>
' <PrintXpsDocument>
''' <summary>
''' Asynchronously, add the XPS document together with a print ticket to the print queue.
''' </summary>
''' <param name="xpsFilePath">Path to source XPS file.</param>
''' <param name="printQueue">The print queue to print to.</param>
''' <param name="printTicket">The print ticket for the selected print queue.</param>
Public Shared Sub PrintXpsDocumentAsync(xpsFilePath As String, printQueue As PrintQueue, printTicket As PrintTicket)
' Create an XpsDocumentWriter object for the print queue.
Dim xpsDocumentWriter As XpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue)
' Open the selected document.
Dim xpsDocument As XpsDocument = New XpsDocument(xpsFilePath, FileAccess.Read)
' Get a fixed document sequence for the selected document.
Dim fixedDocSeq As FixedDocumentSequence = xpsDocument.GetFixedDocumentSequence()
' Asynchronously, add the XPS document together with a print ticket to the print queue.
xpsDocumentWriter.WriteAsync(fixedDocSeq, printTicket)
End Sub
''' <summary>
''' Synchronously, add the XPS document together with a print ticket to the print queue.
''' </summary>
''' <param name="xpsFilePath">Path to source XPS file.</param>
''' <param name="printQueue">The print queue to print to.</param>
''' <param name="printTicket">The print ticket for the selected print queue.</param>
Public Shared Sub PrintXpsDocument(xpsFilePath As String, printQueue As PrintQueue, printTicket As PrintTicket)
' Create an XpsDocumentWriter object for the print queue.
Dim xpsDocumentWriter As XpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue)
' Open the selected document.
Dim xpsDocument As XpsDocument = New XpsDocument(xpsFilePath, FileAccess.Read)
' Get a fixed document sequence for the selected document.
Dim fixedDocSeq As FixedDocumentSequence = xpsDocument.GetFixedDocumentSequence()
' Synchronously, add the XPS document together with a print ticket to the print queue.
xpsDocumentWriter.Write(fixedDocSeq, printTicket)
End Sub
' </PrintXpsDocument>
End Class
End Namespace