Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
ShortDevelopment opened this issue Mar 21, 2024 · 0 comments
Labels
API suggestion Early API idea and discussion, it is NOT ready for implementation

Comments

@ShortDevelopment
Copy link

ShortDevelopment commented Mar 21, 2024

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 (The modern print dialog) for a WPF app.
See PrintCompat.cs and WpfPrintDocumentSource.cs for context.

API Proposal

See XpsSerializationHelper.il for a minimal code flow.

New class XpsSerializationManagerInterop

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

_currentFixedDocumentSequenceWriter = _packageTarget.GetXpsOMPackageWriter(partUri, null);
if (_printQueue != null)
{
((PrintQueue)_printQueue).XpsOMPackageWriter = _currentFixedDocumentSequenceWriter;
}

namespace System.Windows.Xps.Packaging
{
    internal class XpsOMPackagingPolicy : BasePackagingPolicy
    {
        ...
+        public IXpsOMPackageWriter XpsOMPackageWriter => _currentFixedDocumentSequenceWriter;
        ...
        private IXpsOMPackageWriter _currentFixedDocumentSequenceWriter;
    }
}

API Usage

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:

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.

@Kuldeep-MS Kuldeep-MS added the API suggestion Early API idea and discussion, it is NOT ready for implementation label Mar 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API suggestion Early API idea and discussion, it is NOT ready for implementation
Projects
None yet
Development

No branches or pull requests

2 participants