88 lines
2.9 KiB
C#
88 lines
2.9 KiB
C#
|
|
using CloudPrint.Client.Models;
|
||
|
|
using System.Drawing;
|
||
|
|
using System.Drawing.Printing;
|
||
|
|
using System.IO;
|
||
|
|
|
||
|
|
namespace CloudPrint.Client.Services.Printing;
|
||
|
|
|
||
|
|
public sealed class ImagePrintJobExecutor : IPrintJobExecutor
|
||
|
|
{
|
||
|
|
private readonly IWindowsPrintQueueService _queueService;
|
||
|
|
|
||
|
|
private static readonly HashSet<string> SupportedExtensions = new(StringComparer.OrdinalIgnoreCase)
|
||
|
|
{
|
||
|
|
".jpg", ".jpeg", ".png", ".bmp", ".gif"
|
||
|
|
};
|
||
|
|
|
||
|
|
public ImagePrintJobExecutor(IWindowsPrintQueueService queueService)
|
||
|
|
{
|
||
|
|
_queueService = queueService;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool CanHandle(PrintJob job)
|
||
|
|
{
|
||
|
|
return SupportedExtensions.Contains(Path.GetExtension(job.FilePath));
|
||
|
|
}
|
||
|
|
|
||
|
|
public Task ExecuteAsync(PrintJob job, IProgress<int>? progress, CancellationToken cancellationToken = default)
|
||
|
|
{
|
||
|
|
PrintFileGuards.EnsurePrintableFile(job);
|
||
|
|
|
||
|
|
return Task.Run(() =>
|
||
|
|
{
|
||
|
|
cancellationToken.ThrowIfCancellationRequested();
|
||
|
|
using var image = Image.FromFile(job.FilePath);
|
||
|
|
using var document = new PrintDocument
|
||
|
|
{
|
||
|
|
DocumentName = string.IsNullOrWhiteSpace(job.FileName) ? job.JobNo : job.FileName,
|
||
|
|
PrinterSettings =
|
||
|
|
{
|
||
|
|
PrinterName = job.PrinterName,
|
||
|
|
Copies = (short)Math.Clamp(job.Copies, 1, short.MaxValue)
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
if (document.PrinterSettings.CanDuplex)
|
||
|
|
{
|
||
|
|
document.PrinterSettings.Duplex = job.Duplex ? Duplex.Vertical : Duplex.Simplex;
|
||
|
|
}
|
||
|
|
|
||
|
|
document.DefaultPageSettings.Color = job.Color;
|
||
|
|
document.PrintPage += (_, args) => DrawImageToPage(image, args);
|
||
|
|
progress?.Report(20);
|
||
|
|
document.Print();
|
||
|
|
CaptureWindowsJob(job, document.DocumentName);
|
||
|
|
progress?.Report(100);
|
||
|
|
}, cancellationToken);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void CaptureWindowsJob(PrintJob job, string documentName)
|
||
|
|
{
|
||
|
|
var queueJob = _queueService.FindLatestJob(job.PrinterName, documentName);
|
||
|
|
if (queueJob is null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
job.WindowsJobId = queueJob.JobId;
|
||
|
|
job.WindowsJobStatus = queueJob.Status;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void DrawImageToPage(Image image, PrintPageEventArgs args)
|
||
|
|
{
|
||
|
|
if (args.Graphics is null)
|
||
|
|
{
|
||
|
|
throw new InvalidOperationException("打印图形上下文不可用");
|
||
|
|
}
|
||
|
|
|
||
|
|
var bounds = args.MarginBounds;
|
||
|
|
var ratio = Math.Min(bounds.Width / (double)image.Width, bounds.Height / (double)image.Height);
|
||
|
|
var width = (int)(image.Width * ratio);
|
||
|
|
var height = (int)(image.Height * ratio);
|
||
|
|
var x = bounds.Left + (bounds.Width - width) / 2;
|
||
|
|
var y = bounds.Top + (bounds.Height - height) / 2;
|
||
|
|
|
||
|
|
args.Graphics.DrawImage(image, x, y, width, height);
|
||
|
|
args.HasMorePages = false;
|
||
|
|
}
|
||
|
|
}
|