question

Jramos avatar image
0 Votes"
Jramos asked Jramos commented

You can use Print.Toolkit with Mvvm.Toolkit. Print is included mvvm.toolkit. you print serious for inkcanvas uwp c#


Hello: how can I implement the print for INkCanvas to print

windows-uwp
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

AryaDing-MSFT avatar image
0 Votes"
AryaDing-MSFT answered AryaDing-MSFT edited

Hi,

Welcome to Microsoft Q&A!

For printing the InkCanvas, you could save the whole InkCanvas into an image then print the image.

Steps: You need to download the Win2D.uwp package and use CanvasDrawingSession.DrawInk(IEnumerable<InkStroke>) method to draw ink strokes inside inkCanvas. Then, you could use CanvasRenderTarget.SaveAsync(IRandomAccessStream, CanvasBitmapFileFormat,Single) method to saves the entire bitmap to the specified file stream of an image file. So that you could print the image that contains InkCanvas .


Please refer to this answer to know the detailed code.


Update:

public readonly InkCanvas inkCanvas;
public readonly Canvas drawingCanvas, printCanvas;

  1. First, you need to design the inkCanvas and printCanvas in xaml page rather than declare them in code-behind. The inkCanvas is used to receive and display all pen input. The printCanvas is a XAML panel that will be used to host printable control, it needs to be in your visual tree. Besides, the drawingCanvas is unnecessary, you could delete it.

  2. Second, you need to add a print button to call the print event.

  3. Third, install Microsoft.Toolkit.Uwp package through Manage Nuget Packages.

Please refer to the following code.

Xaml code:

 <Grid>
         <StackPanel>
             <InkCanvas x:Name="inkCanvas" Height="400"  />                
             <Canvas x:Name="printCanvas" Opacity="0"/>
             <Button Content="Print" Name="printBtn" Click="printBtn_Click"/>
         </StackPanel>
    </Grid>

Code behind:

  public sealed partial class MainPage : Page
     {
         public PrintHelper _printHelper;
         public MainPage()
         {
             this.InitializeComponent();
             inkCanvas.InkPresenter.InputDeviceTypes = Windows.UI.Core.CoreInputDeviceTypes.Mouse | Windows.UI.Core.CoreInputDeviceTypes.Pen;
         }
    
         private async void printBtn_Click(object sender, RoutedEventArgs e)
         {
             // Create a Bitmap from the strokes.
             var inkStream = new InMemoryRandomAccessStream();
             await inkCanvas.InkPresenter.StrokeContainer.SaveAsync(inkStream.GetOutputStreamAt(0));
             var inkBitmap = new BitmapImage();
             await inkBitmap.SetSourceAsync(inkStream);
    
             // You need to adjust Margin to layout the image properly in the print-page. 
             var inkBounds = inkCanvas.InkPresenter.StrokeContainer.BoundingRect;
             var inkMargin = new Thickness(inkBounds.Left, inkBounds.Top, inkCanvas.ActualWidth - inkBounds.Right, inkCanvas.ActualHeight - inkBounds.Bottom);
    
             // Prepare Viewbox+Image to be printed.
             var inkViewbox = new Viewbox()
             {
                 Child = new Image()
                 {
                     Source = inkBitmap,
                     Margin = inkMargin
                 },
                 Width = inkCanvas.ActualWidth,
                 Height = inkCanvas.ActualHeight
             };
    
             _printHelper = new PrintHelper(printCanvas);
             _printHelper.AddFrameworkElementToPrint(inkViewbox);
    
    
             _printHelper.OnPrintFailed += _printHelper_OnPrintFailed;
             _printHelper.OnPrintSucceeded += _printHelper_OnPrintSucceeded;
    
             var printHelperOptions = new PrintHelperOptions();
             printHelperOptions.AddDisplayOption(StandardPrintTaskOptions.Orientation);
             printHelperOptions.Orientation = PrintOrientation.Landscape;
    
             await _printHelper.ShowPrintUIAsync("printing InkPen", printHelperOptions);
         }
    
         private void _printHelper_OnPrintSucceeded()
         {
             Debug.WriteLine("print successfully");
         }
    
         private void _printHelper_OnPrintFailed()
         {
             Debug.WriteLine("print failed");
         }
 }

When the app runs, you could draw something in InkCanvas control with the mouse, then click the print button.


Update2:


The reason is that your defined a class whose name is PrintHelper, the compiler can’t distinguish your custom PrintHelper class and PrintHelper class.

Please change

 public class PrintHelper {…} 

to

 public class MyPrintHelper {…} 




If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.














5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Jramos avatar image
0 Votes"
Jramos answered Jramos commented
 using Microsoft.Toolkit.Uwp.Helpers;
 using System;
 using Windows.Graphics.Printing;
 using Windows.Storage.Streams;
 using Windows.UI.Popups;
 using Windows.UI.Xaml;
 using Windows.UI.Xaml.Controls;
 using Windows.UI.Xaml.Media.Imaging;
    
 namespace InkPen.Helpers
 {
     public class PrintHelper
     {
         public readonly InkCanvas inkCanvas;
         public readonly Canvas drawingCanvas, printCanvas;
         private PrintHelper _printHelper;
    
           
    
         protected async void PrintTaskResquested()
         { 
             var inkStream = new InMemoryRandomAccessStream();
             await inkCanvas.InkPresenter.StrokeContainer.SaveAsync(inkStream.GetOutputStreamAt(0));
             var inkBitmap = new BitmapImage();
             await inkBitmap.SetSourceAsync(inkStream);
    
             var inkBounds = inkCanvas.InkPresenter.StrokeContainer.BoundingRect;
             var inkMargin = new Thickness(inkBounds.Left, inkBounds.Top, inkCanvas.ActualWidth - inkBounds.Right, inkCanvas.ActualHeight - inkBounds.Bottom);
    
    
             var inkViewBox = new Viewbox()
             {
                 Child = new Image()
                 {
                     Source = inkBitmap,
                     Margin = inkMargin
                 },
    
                 Width =  drawingCanvas.ActualWidth,
                 Height = drawingCanvas.ActualHeight
             };
    
    
             _printHelper = new PrintHelper(printCanvas);
             _printHelper.AddFrameworkElementToPrint(inkViewBox);
             _printHelper.OnPrintFailed += PrintHelper_OnPrintFailed;
             _printHelper.OnPrintSucceded += PrintHelper_OnPrintSucceded;
    
             var printHelperOptions = new PrintHelperOptions();
    
             printHelperOptions.AddDisplayOption(StandardPrintTaskOptions.Copies);
             printHelperOptions.AddDisplayOption(StandardPrintTaskOptions.MediaSize);
             printHelperOptions.AddDisplayOption(StandardPrintTaskOptions.Collation);
             printHelperOptions.AddDisplayOption(StandardPrintTaskOptions.Orientation);
    
    
             printHelperOptions.PrintQuality = PrintQuality.Default;
             printHelperOptions.MediaSize = PrintMediaSize.Default;
             printHelperOptions.Collation = PrintCollation.Default;
             printHelperOptions.Orientation = PrintOrientation.Landscape;
    
    
             }
    
         private async void PrintHelper_OnPrintSucceded()
         {
             _printHelper.Dispose();
    
    
             var dialog = new MessageDialog("Print Done");
             await dialog.ShowAsync();
         }
    
         private async void PrintHelper_OnPrintFailed()
         {
             _printHelper.Dispose();
    
    
             var dialog = new MessageDialog("Print Failed");
             await dialog.ShowAsync();
         }
     }
 }

Here I have some faults like :

             _printHelper = new PrintHelper(printCanvas);
             _printHelper.AddFrameworkElementToPrint(inkViewBox);
             _printHelper.OnPrintFailed += PrintHelper_OnPrintFailed;
             _printHelper.OnPrintSucceded += PrintHelper_OnPrintSucceded;

 private async void PrintHelper_OnPrintSucceded()
         {
             _printHelper.Dispose();
    
    
             var dialog = new MessageDialog("Print Done");
             await dialog.ShowAsync();
         }
    
         private async void PrintHelper_OnPrintFailed()
         {
             _printHelper.Dispose();
    
    
             var dialog = new MessageDialog("Print Failed");
             await dialog.ShowAsync();
         }




· 10
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@Jramos I have updated my answer, you could try it.

0 Votes 0 ·

I Have problem : PrinHelper does not contine a definition of three

 _printHelper.AddFrameworkElementToPrint(inkViewBox);
             _printHelper.OnPrintFailed += PrintHelper_OnPrintFailed;
             _printHelper.OnPrintSucceded += PrintHelper_OnPrintSucceded;



0 Votes 0 ·

@Jramos PrintHelper contains these definitions, please check AddFrameworkElementToPrint(FrameworkElement), OnPrintSucceeded, OnPrintFailed. Beisdes, did you install the Microsoft.Toolkit.Uwp package like the second step of my previous answer?

0 Votes 0 ·
Show more comments
Jramos avatar image
0 Votes"
Jramos answered Jramos edited

I have seen this PrintHelper codePrintHelper.cs


· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@Jramos Since I can't reproduce your issue, could you please us a minimal reproducible sample through OneDrive or GitHub?

0 Votes 0 ·

this example is Github PrintHelper.cs


0 Votes 0 ·

@Jramos When you install the Microsoft.Toolkit.Uwp Package, you could create an PrintHelper object, then you could use it call these event, such as OnPreviewPagesCreated,OnPrintCanceled,OnPrintFailed, OnPrintSucceeded. Why could you do these? The reason is Microsoft.Toolkit.Uwp Package contains a class file named PrintHelper.cs , which defines these event implementation principle.

Therefore, you don’t need to refer to the PrintHelper.cs to write logic. You could declare PrintHelper object and call its built-in event directly when you install the corresponding package.

0 Votes 0 ·
Show more comments
Jramos avatar image
0 Votes"
Jramos answered Jramos commented
  public class PrintHelper
     {
         private Canvas printCanvas, drawingCanvas;
         private InkCanvas inkCanvas;
         private PrintHelper _printHelper;
    
         public event Action OnPrintSucceeded;
         public event Action OnPrintFailed;
         public event Action OnPrintCanceled;
    
    
         public PrintHelper(Canvas printCanvas)
         {
             this.printCanvas = printCanvas;
         }
    
         public  async Task PrintAsync()
         {
             var inkStream = new InMemoryRandomAccessStream();
             await inkCanvas.InkPresenter.StrokeContainer.SaveAsync(inkStream.GetOutputStreamAt(0));
             var inkBitmap = new BitmapImage();
             await inkBitmap.SetSourceAsync(inkStream);
    
             var inkBounds = inkCanvas.InkPresenter.StrokeContainer.BoundingRect;
             var inkMargin = new Thickness(inkBounds.Left, inkBounds.Top, inkCanvas.ActualWidth - inkBounds.Right, inkCanvas.ActualHeight - inkBounds.Bottom);
    
             var inkViewBox = new Viewbox()
             {
    
                 Child = new Image()
                 {
                     Source = inkBitmap,
                     Margin = inkMargin
                 },
    
                 Width = drawingCanvas.ActualWidth,
                 Height = drawingCanvas.ActualHeight
             };
    
             _printHelper = new PrintHelper(printCanvas);
             _printHelper.AddFrameworkElementToPrint(inkViewBox);
    
             _printHelper.OnPrintFailed += printHelper_OnPrintFailed;
             _printHelper.OnPrintSucceeded += printHelper_OnPrintSucceeded;
               
             var printHelperOptions = new PrintHelperOptions();
    
             printHelperOptions.AddDisplayOption(StandardPrintTaskOptions.Copies);
             printHelperOptions.AddDisplayOption(StandardPrintTaskOptions.MediaSize);
             printHelperOptions.AddDisplayOption(StandardPrintTaskOptions.Collation);
             printHelperOptions.AddDisplayOption(StandardPrintTaskOptions.Orientation);
    
    
             printHelperOptions.PrintQuality = PrintQuality.Default;
             printHelperOptions.MediaSize = PrintMediaSize.Default;
             printHelperOptions.Collation = PrintCollation.Default;
             printHelperOptions.Orientation = PrintOrientation.Landscape;
                
    
    
            // await _printHelper.ShowPrintUIAsync("Printing Ink", printHelperOptions);
    
         }
    
    
            
         private async  void printHelper_OnPrintSucceeded()
         {
             _printHelper.Dispose();
    
             var dialog = new MessageDialog("Printing Done");
             await dialog.ShowAsync();
               
         }
    
    
         private async void printHelper_OnPrintFailed()
         {
             _printHelper.Dispose();
             var dialog = new MessageDialog("Sorry, Printing Failed");
             await dialog.ShowAsync();
                
         }
    
    
     }
           
 }

the probelma I have in AddFrameworkElementToPrint and dispose. PrintHelper does not contain an FRameworkElementToPrint definition or an extenion method.

· 10
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@Jramos I have updated my answer, please see my update2.

0 Votes 0 ·

the named the file the doubt I have is the showPrintUIAsync, what before failed is correct

0 Votes 0 ·

@Jramos Let’s back to the beginning. Your exception reports “PrintHelper no contain an definition “”AddFrameworkElementToPrint”. I found you created a class named PrintHelper, which is your custom class. What we need is PrintHelper Class, it contains the AddFrameworkElementToPrint method. They are different, so I suggest you change your custom class name to distinguish the real PrintHelper Class.

1 Vote 1 ·
Show more comments

Hello:

in some MVVM examples I have seen that you can use the Click event instead of Command={x:Bind PrintCommand}.

0 Votes 0 ·

Please contact our paid phone support at MS Support. You will get 1:1 support on this issue and you could talk to the engineers directly via email or phone.

0 Votes 0 ·

I have this problem when i press the print button gives me this error:

Object reference not set to an instance of an object.'

inkCanvas fue null.



0 Votes 0 ·