Im hoping someone has an idea what (stupid thing) I've done wrong here.
We are trying to print labels from a PDF file. The file is generated using SkiaSharp PDF canvas. Each page is the same size and it validates and is displayed correctly in Adobe Reader etc. However, we cannot get the correct page size set when printing. Ive seen several examples here but none of them work. The only thing that sets the correct paper size on the thermal printer is using the Paginator method that prints each page as a bitmap, but the quality of the output is rubbish - ie, barcodes are fuzzy. It looks like it's resizing and dithering and/or expecting lots of colours. Labels are typically b/w only.
Sample code below from my last attempt. See attached pdf and image of printed output. Label is 80mm x 180mm (~ 3x7 inches). Printer is a TEC 245 Thermal, no ribbon, with 203 pixel resolution.
You can see from the image that the page size is clipping the content. I've experimented with various calculations for the page size. Im using my own unit converter. The measurements at all DPI are correctly calculated. At 203 DPI I get 1438 x 639 pixels, which is correct, but the image is much the same as the sample - the barcode is truncated and the corner blocks are not printed.
Cheers
public class WindowsGenericPrinterDriver
{
public float DPI => 96;
public override void PrintDocument(string documentFile)
{
using var t = StartSTATask(() =>
{
PrintPDFFile(documentFile);
return Task.CompletedTask;
});
t.Wait();
if (t.Exception != null)
{
throw t.Exception;
}
}
Task StartSTATask(Func func)
{
var tcs = new TaskCompletionSource();
Thread thread = new Thread(() =>
{
try
{
tcs.SetResult(func());
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
private bool PrintPDFFile(string pdfFile)
{
using var localPrintServer = new LocalPrintServer();
using var printQueue = localPrintServer.GetPrintQueue(PrintRequest.Printer.Name);
if (printQueue == null)
{
throw new Exception($"No printer called ${PrintRequest.Printer.Name} found");
}
var pdfViewer = new PdfDocumentView();
pdfViewer.Load(pdfFile);
var doc = pdfViewer.PrintDocument;
var ticket = GetPrintTicket(printQueue);
var @object = new PrintDlgPrintTicketEventHandler(ticket);
var xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue);
xpsDocumentWriter.WritingPrintTicketRequired += @object.SetPrintTicket;
xpsDocumentWriter.Write(doc, ticket);
return true;
}
private PrintTicket GetPrintTicket(PrintQueue printQueue)
{
var ticket = printQueue.DefaultPrintTicket.Clone();
ticket.Collation = PrintRequest.Collate ? Collation.Collated : Collation.Uncollated;
ticket.CopyCount = PrintRequest.Copies;
ticket.PageBorderless = PageBorderless.Borderless;
ticket.OutputQuality = OutputQuality.High;
var pageSize = UnitConverter.ToPixels(PrintRequest.Label.Media.PageOuterSize, PrintRequest.Label.Media.DefaultMeasure, DPI);
if (PrintRequest.Label.Media.Landscape)
{
// landscape we need to flip height and width
ticket.PageOrientation = System.Printing.PageOrientation.Landscape;
ticket.PageMediaSize = new PageMediaSize(PageMediaSizeName.Unknown, pageSize.Height, pageSize.Width);
}
else
{
ticket.PageOrientation = System.Printing.PageOrientation.Portrait;
ticket.PageMediaSize = new PageMediaSize(PageMediaSizeName.Unknown, pageSize.Width, pageSize.Height);
}
return ticket;
}
}
internal class PrintDlgPrintTicketEventHandler
{
private readonly PrintTicket _printTicket;
public PrintDlgPrintTicketEventHandler(PrintTicket printTicket)
{
_printTicket = printTicket;
}
public void SetPrintTicket(object sender, WritingPrintTicketRequiredEventArgs args)
{
// if (args.CurrentPrintTicketLevel == PrintTicketLevel.FixedDocumentSequencePrintTicket)
{
args.CurrentPrintTicket = _printTicket;
}
}
}
Attachment: sample_9a07ef16.zip
Hi
I can confirm your method does indeed work, thank you for the sample, but it only works if I set the paper size in the printer settings first.
We would like to be able to set the paper / media size from code and there doesnt seem to be a way to do this with PDFViewer, hence our attempt to use the print document. Maybe we need to set the printer defaults before printing or there is some other trick but I think this is outside of the control of the PDFViewer.
In the end, customers will not often change the label sizes and asking them to do this in the printer settings outside of our app is not great, but acceptable.
Thanks
Hi
Thanks for the followup.
I need to spend a lot more time on this than I have available right now but mostly we just need to be able to specify any paper size without having to create this in the printer driver settings manually. If we can do that via the PDFViewer printer settings this would be better, but using the DefaultPrinterSettings on the print queue will probably works - as long as that doesnt create a permanent change.
I'll add more detail next week probably.
Thanks again