告别繁琐打印代码:UWP应用零门槛打印功能实现指南
你是否还在为UWP应用添加打印功能而编写冗长代码?是否想让用户轻松打印文档却苦于复杂的API调用?本文将通过Windows-universal-samples项目中的打印模块,带你用最少代码实现专业打印功能,覆盖基础设置、高级选项到图片打印全场景。读完本文,你将掌握从打印任务注册到自定义打印选项的完整流程,让应用打印体验媲美原生程序。
打印功能核心架构
Windows-universal-samples项目的打印模块(Samples/Printing)提供了完整的UWP打印解决方案,核心基于PrintManager(打印管理器)和PrintDocument(打印文档)两个组件。项目结构清晰,包含C#和C++两种实现,其中C#示例更适合快速集成:
- 基础组件:PrintHelper.cs封装了打印任务注册、文档准备和页面生成的核心逻辑
- 场景示例:提供6个场景,从基础打印到高级图片打印,覆盖绝大多数业务需求
- 共享资源:shared/目录包含打印相关的SVG图标和图片资源
快速集成:三步实现基础打印
步骤1:初始化打印助手
首先创建PrintHelper实例并注册打印任务,这一步骤在页面导航时完成,确保应用启动即支持打印:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// 检查设备是否支持打印
if (PrintManager.IsSupported())
{
// 初始化打印助手并注册打印任务
printHelper = new PrintHelper(this);
printHelper.RegisterForPrinting();
// 准备打印内容
printHelper.PreparePrintContent(new PageToPrint());
}
else
{
// 隐藏打印按钮并提示用户
InvokePrintingButton.Visibility = Visibility.Collapsed;
}
}
步骤2:设计打印内容页面
创建专用的打印页面(PageToPrint.xaml),包含页眉、正文和页脚三部分。PrintHelper会自动处理内容分页,无需担心内容溢出:
<Page>
<StackPanel x:Name="PrintableArea">
<StackPanel x:Name="Header" Visibility="Collapsed">
<TextBlock Text="文档标题" FontSize="24"/>
</StackPanel>
<RichTextBlock x:Name="TextContent">
<!-- 打印正文内容 -->
</RichTextBlock>
<StackPanel x:Name="Footer" Visibility="Collapsed">
<TextBlock x:Name="PageNumber" HorizontalAlignment="Right"/>
</StackPanel>
</StackPanel>
</Page>
步骤3:触发打印对话框
在打印按钮点击事件中调用ShowPrintUIAsync方法,显示系统打印对话框:
private async void OnPrintButtonClick(object sender, RoutedEventArgs e)
{
await printHelper.ShowPrintUIAsync();
}
完成这三步后,应用已具备基础打印能力。PrintHelper会自动处理打印任务的创建、页面预览和打印完成事件,Scenario1Basic.xaml.cs展示了完整实现。
高级功能:自定义打印选项
标准选项配置
通过PrintTaskOptions可以配置打印份数、纸张方向、介质大小等标准选项。Scenario2StandardOptons.xaml.cs示例演示了如何自定义显示的打印选项:
protected override void PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs e)
{
PrintTask printTask = e.Request.CreatePrintTask("打印任务名称", sourceRequestedArgs =>
{
// 配置显示的打印选项
var displayedOptions = printTask.Options.DisplayedOptions;
displayedOptions.Clear();
displayedOptions.Add(StandardPrintTaskOptions.Copies); // 份数
displayedOptions.Add(StandardPrintTaskOptions.Orientation); // 方向
displayedOptions.Add(StandardPrintTaskOptions.MediaSize); // 纸张大小
displayedOptions.Add(StandardPrintTaskOptions.Duplex); // 双面打印
// 设置默认纸张大小
printTask.Options.MediaSize = PrintMediaSize.NorthAmericaLegal;
sourceRequestedArgs.SetSource(printDocumentSource);
});
}
自定义打印选项
对于特殊业务需求,可以添加自定义打印选项。例如在图片打印场景中添加"图片大小"和"缩放方式"选项(Scenario5Photos.xaml.cs):
// 创建自定义选项
PrintCustomItemListOptionDetails photoSize = printDetailedOptions.CreateItemListOption("photoSize", "照片尺寸");
photoSize.AddItem("Size4x6", "4x6英寸");
photoSize.AddItem("Size5x7", "5x7英寸");
photoSize.AddItem("Size8x10", "8x10英寸");
// 添加到显示选项
printDetailedOptions.DisplayedOptions.Add("photoSize");
处理选项变更事件,实时更新预览内容:
printDetailedOptions.OptionChanged += (sender, args) =>
{
if (args.OptionId.ToString() == "photoSize")
{
// 根据选项更新预览
printDocument.InvalidatePreview();
}
};
场景化解决方案
文档分页打印
对于长文档,PrintHelper自动处理内容分页,但有时需要控制页码范围。Scenario4PageRange.xaml.cs实现了页面范围选择功能,允许用户指定打印页码:
protected override void AddPrintPages(object sender, AddPagesEventArgs e)
{
IList<PrintPageRange> customPageRanges = e.PrintTaskOptions.CustomPageRanges;
if (customPageRanges.Count == 0)
{
// 打印全部页面
foreach (UIElement page in printPreviewPages)
{
printDocument.AddPage(page);
}
}
else
{
// 打印指定范围页面
foreach (PrintPageRange range in customPageRanges)
{
for (int i = range.FirstPageNumber; i <= range.LastPageNumber; i++)
{
printDocument.AddPage(printPreviewPages[i - 1]);
}
}
}
}
图片打印优化
打印图片需要考虑缩放和裁剪,Scenario5Photos.xaml.cs提供了专业的图片打印解决方案:
- 缩放模式:支持"适应"和"裁剪"两种模式
- 尺寸选择:预设4x6、5x7等常用照片尺寸
- 方向自动调整:根据纸张方向旋转图片
核心代码如下:
private async Task<WriteableBitmap> LoadBitmapAsync(Uri source, bool landscape)
{
// 加载图片并根据打印方向调整
var file = await StorageFile.GetFileFromApplicationUriAsync(source);
using (var stream = await file.OpenAsync(FileAccessMode.Read))
{
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
BitmapTransform transform = new BitmapTransform();
// 根据纸张方向旋转图片
if (landscape && decoder.PixelWidth < decoder.PixelHeight)
{
transform.Rotation = BitmapRotation.Clockwise270Degrees;
}
// 解码并返回位图
var pixelData = await decoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Straight,
transform,
ExifOrientationMode.RespectExifOrientation,
ColorManagementMode.DoNotColorManage);
// 创建WriteableBitmap并返回
// ...
}
}
高级配置与最佳实践
禁用打印预览
某些场景下需要直接打印而不显示预览,Scenario6DisablePreview.xaml.cs演示了如何实现:
protected override void PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs e)
{
PrintTask printTask = e.Request.CreatePrintTask("无预览打印", sourceRequestedArgs =>
{
// 禁用预览
printTask.Options.PreviewPageCount = 0;
sourceRequestedArgs.SetSource(printDocumentSource);
});
}
错误处理与状态提示
完善的错误处理提升用户体验,PrintHelper已经包含基本错误处理,但建议根据业务需求扩展:
printTask.Completed += async (s, args) =>
{
if (args.Completion == PrintTaskCompletion.Failed)
{
await scenarioPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
MainPage.Current.NotifyUser("打印失败: " + args.Completion, NotifyType.ErrorMessage);
});
}
};
总结与扩展
Windows-universal-samples的打印模块提供了开箱即用的UWP打印解决方案,通过PrintHelper封装了复杂的打印API,使开发者能在几分钟内为应用添加专业打印功能。核心优势包括:
- 低代码集成:三步实现基础打印,无需深入了解打印API细节
- 场景全覆盖:从简单文档到复杂图片打印,满足各种业务需求
- 高度可定制:支持自定义打印选项和页面布局,打造品牌化打印体验
官方文档:README.md
完整代码:Samples/Printing/cs/
进阶场景:Scenario5Photos.xaml.cs
建议根据实际需求选择合适的场景进行集成,并关注打印选项的用户体验设计。对于复杂文档,可考虑添加打印样式设置,允许用户调整字体大小和页面边距,进一步提升打印体验。
点赞收藏本文,关注后续UWP高级打印技巧分享!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




