WinUI3+C++20下如何打印NavigationView中的指定XAML元素
一、确认CLSID与依赖配置
首先确保你使用的CLSID_PrintManager是正确的,其值为{1B8E2F1F-6D97-441B-802B-699F000A6CE2}。同时检查项目配置:
- 必须包含头文件:
<winrt/Windows.Graphics.Printing.h>和<printmanagerinterop.h> - 链接器输入中添加
windowsapp.lib(Windows App SDK核心库) - 目标平台版本设置为10.0.19041.0或更高
二、正确初始化IPrintManagerInterop
WinUI3中不能直接实例化PrintManager,必须通过IPrintManagerInterop绑定到窗口HWND。以下是可行的初始化代码:
#include <winrt/Windows.UI.WindowManagement.h> #include <printmanagerinterop.h> // 获取当前WinUI窗口的HWND auto currentAppWindow = winrt::Windows::UI::WindowManagement::AppWindow::GetCurrent(); HWND hwnd = winrt::Windows::UI::WindowManagement::GetWindowFromWindowId(currentAppWindow.Id()); // 创建IPrintManagerInterop实例 winrt::com_ptr<IPrintManagerInterop> printManagerInterop; HRESULT hr = CoCreateInstance(CLSID_PrintManager, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&printManagerInterop)); if (SUCCEEDED(hr)) { winrt::Windows::Graphics::Printing::PrintManager printManager; hr = printManagerInterop->GetForWindow(hwnd, IID_PPV_ARGS(&printManager)); if (SUCCEEDED(hr)) { // 注册打印请求事件 printManager.PrintRequested([this](const auto&, const winrt::Windows::Graphics::Printing::PrintRequestedEventArgs& args) { auto printTask = args.Request().CreatePrintTask(L"选中页面打印", [this](const auto& taskArgs) { // 这里传入选中页面的打印数据源 taskArgs.SetSource(GetSelectedPagePrintSource()); }); }); } }
注意:这段代码必须在UI线程执行,WinUI3的主线程默认已初始化COM,无需额外调用CoInitializeEx。
三、实现仅打印选中页面
不要直接打印整个窗口,需单独处理选中页面的内容:
- 捕获页面内容:将选中的NavigationView页面渲染到
RenderTargetBitmapwinrt::Windows::UI::Xaml::Controls::Page selectedPage = /* 获取选中的页面实例 */; winrt::Windows::UI::Xaml::Media::RenderTargetBitmap renderBitmap; co_await renderBitmap.RenderAsync(selectedPage); - 转换为打印源:将渲染后的位图转换为
PrintDocument可使用的数据源,或直接使用页面的可视化元素作为打印预览源:winrt::Windows::UI::Xaml::Printing::PrintDocument printDoc; printDoc.SetPreviewPage(1, selectedPage); // 返回printDoc.DocumentSource()作为打印源
四、错误排查
- 接口未注册:更新Windows App SDK到最新稳定版,确认项目的“Windows App SDK版本”配置正确
- IPrintManagerInterop创建失败:检查
CoCreateInstance的CLSCTX参数,使用CLSCTX_ALL而非其他受限值 - 打印无响应:确保打印事件处理逻辑在UI线程执行,避免阻塞或跨线程调用UI元素
内容的提问来源于stack exchange,提问作者Tirsvad
相关产品推荐
相关产品推荐

