dotnet / dotnet/wpf

[API Proposal]: Print without `PrintQueue` abstraction using the modern print dialog

Open
#8,940 0 comments 0 reactions 0 assignees View on GitHub
API suggestion
Dominant language
C#
Stars
7.7k
Forks
1.3k
Avg merge
1d 11h
Merged PRs (30d)
61

Description

### Background and motivation

AFAIK there's currently no solution to print without a `PrintQueue` in case an application already has an instance of `IXpsDocumentPackageTarget`.
This scenario occurs when implementing the WinRT [`PrintManager`](https://learn.microsoft.com/en-us/uwp/api/windows.graphics.printing.printmanager) (The modern print dialog) for a WPF app.
See [PrintCompat.cs](https://github.com/Diahon/Diahon.WinUI.Printing/blob/921e1f9a5f3e52b723dafe87bc3b9df3530ddcaa/Diahon.WinUI.Printing.Wpf/PrintCompat.cs) and [WpfPrintDocumentSource.cs](https://github.com/Diahon/Diahon.WinUI.Printing/blob/921e1f9a5f3e52b723dafe87bc3b9df3530ddcaa/Diahon.WinUI.Printing.Wpf/WpfPrintDocumentSource.cs) for context.

### API Proposal

See [XpsSerializationHelper.il](https://github.com/Diahon/Diahon.WinUI.Printing/blob/main/ReachFrameworkHelper/XpsSerializationHelper.il) for a minimal code flow.

#### New class `XpsSerializationManagerInterop`
```cs
using System.Windows.Xps.Serialization.RCW;
using System.Windows.Xps.Packaging;

namespace System.Windows.Xps.Serialization;
public sealed class XpsSerializationManagerInterop
{
readonly XpsOMSerializationManager _serializer;
readonly IXpsOMPackageWriter _writer;
private XpsSerializationManagerInterop(...);

public static XpsSerializationManagerInterop CreateFromXpsDocumentPackageTarget(object target)
{
// https://github.com/dotnet/wpf/blob/7b755d2bbcc9d77760f68b5e738b2587cabe1a37/src/Microsoft.DotNet.Wpf/src/System.Printing/CPP/src/PrintQueue.cpp#L4723-L4734
XpsOMPackagingPolicy policy = new((IXpsDocumentPackageTarget)target);
policy.EnsureXpsOMPackageWriter();

// Internally expose XpsOMPackagingPolicy._currentFixedDocumentSequenceWriter
var writer = policy.XpsOMPackageWriter;

XpsOMSerializationManager serializer = new(policy);
return new(serializer, )
}

// Proxy events from XpsOMSerializationManager
public event XpsSerializationPrintTicketRequiredEventHandler? PrintTicketRequired;
public event XpsSerializationProgressChangedEventHandler? ProgressChanged;

public void Print(object serializedObject)
{
_serializer.SaveAsXaml(serializedObject);
_serializer.Commit();

// Close writer to flush to printer
// Only close on success (no exception)
// https://github.com/dotnet/wpf/blob/906eb2878bbe4d5f86e77e9a0d4f85815e9f5aaf/src/Microsoft.DotNet.Wpf/src/System.Printing/CPP/src/XpsCompatiblePrinter.cpp#L125
_writer.Close();
}
}
```

#### Internally expose `IXpsOMPackageWriter` from `XpsOMPackagingPolicy`
https://github.com/dotnet/wpf/blob/7b755d2bbcc9d77760f68b5e738b2587cabe1a37/src/Microsoft.DotNet.Wpf/src/ReachFramework/Serialization/manager/XpsOMPackagingPolicy.cs#L68-L72
```diff
namespace System.Windows.Xps.Packaging
{
internal class XpsOMPackagingPolicy : BasePackagingPolicy
{
...
+ public IXpsOMPackageWriter XpsOMPackageWriter => _currentFixedDocumentSequenceWriter;
...
private IXpsOMPackageWriter _currentFixedDocumentSequenceWriter;
}
}
```

### API Usage

```cs
object target = ...; // IXpsDocumentPackageTarget com object
var serializer = XpsSerializationManagerInterop.CreateFromXpsDocumentPackageTarget(target);
serializer.PrintTicketRequired += ...;
serializer.Print(paginator); // Might throw
```

### Alternative Designs

Create an alternative interop `PrintQueue` implementation:
```csharp
object target = ...; // IXpsDocumentPackageTarget com object
var queue = PrintQueueInterop.CreateFromXpsOMPackageWriter(target);
var writer = PrintQueue.CreateXpsDocumentWriter(queue);
writer.Write(paginator, printTicket);
```
This has less new public api surface (only one new method `CreateFromXpsOMPackageWriter`) but might require a lot more internal api changes / abstractions.

### Risks

Both solutions can likely only be used for a single print, as the `IXpsOMPackageWriter` has to be closed to flush the buffered data to the printer.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.