Issue how to print a xaml element
How to access printer and print an xaml element. A page choose from navigation view.
I am using winui-3 and c++20. Created a blank app
The idea is only to print my page not the hole window
Tried
I have tried to use PrintManager but it seem not to work with winui3. See source code. I am blank what to do now!
Source code
file: MainWindow.xaml
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="PrintingFrameworkElement.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PrintingFrameworkElement"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="PrintingFrameworkElement">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="I should not be printed" Margin="10"/>
<Button x:Name="myButton" Click="myButton_Click">Print</Button>
</StackPanel>
<NavigationView
x:Name="NavControl"
PaneDisplayMode="LeftCompact"
IsSettingsVisible="False"
ItemInvoked="OnNavigationViewItemInvoked">
<NavigationView.MenuItems>
<NavigationViewItem Content="Page 1" Icon="Page" Tag="PrintingFrameworkElement.PageOne"/>
</NavigationView.MenuItems>
<Frame x:Name="NavContent" Margin="0, 0, 0, 0">
<!-- NavigationView Content that shpuold be printable-->
</Frame>
</NavigationView>
</StackPanel>
</Window>
file: MainWindow.xaml.h
#pragma once
#include "MainWindow.g.h"
namespace winrt::PrintingFrameworkElement::implementation
{
struct MainWindow : MainWindowT<MainWindow>
{
MainWindow()
{
// Xaml objects should not call InitializeComponent during construction.
// See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent
}
void myButton_Click(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args);
void OnNavigationViewItemInvoked(winrt::Windows::Foundation::IInspectable const& /*sender*/, winrt::Microsoft::UI::Xaml::Controls::NavigationViewItemInvokedEventArgs const& e);
void NavigateToPage(hstring const& pageName);
};
}
namespace winrt::PrintingFrameworkElement::factory_implementation
{
struct MainWindow : MainWindowT<MainWindow, implementation::MainWindow>
{
};
}
file: MainWindow.xaml.cpp
#include "pch.h"
#include "MainWindow.xaml.h"
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif
#include <winrt/Microsoft.UI.Xaml.Printing.h>
#include <winrt/Microsoft.UI.Xaml.Media.Imaging.h>
//#include <winrt/Microsoft.UI.Xaml.Printing.PrintManager.h>
//#include <winrt/Windows.Graphics.Printing.h>
using namespace winrt;
using namespace Microsoft::UI::Xaml;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace winrt::PrintingFrameworkElement::implementation
{
void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&)
{
// Do printing of the FrameworkElement here
using namespace winrt::Microsoft::UI::Xaml;
using namespace winrt::Microsoft::UI::Xaml::Printing;
// Create PrintDocument
PrintDocument printDoc = PrintDocument();
// Create a XAML element to print
auto content = NavContent().Content().as<FrameworkElement>();
// FIXME: This is not working
// Exception thrown at 0x00007FFBAD0BFB4C (KernelBase.dll) in PrintingFrameworkElement.exe: WinRT originate error - 0x80040155 : 'Interface not registered'.
// Exception thrown at 0x00007FFBAD0BFB4C in PrintingFrameworkElement.exe: Microsoft C++ exception: winrt::hresult_error at memory location 0x000000F8A09D9DA8.
//auto printManager = Windows::Graphics::Printing::PrintManager::GetForCurrentView();
//// Register for PrintTaskRequested event
//printManager.PrintTaskRequested([=](Windows::Graphics::Printing::PrintManager const&, Windows::Graphics::Printing::PrintTaskRequestedEventArgs const& args)
// {
// Windows::Graphics::Printing::PrintTask task = args.Request().CreatePrintTask(L"Print Document",
// [](Windows::Graphics::Printing::PrintTask const& sender, Windows::Graphics::Printing::PrintTaskSourceRequestedArgs const& e)
// {
// e.SetSource(sender.Source());
// });
// });
// Start the print process
//Windows::Graphics::Printing::PrintManager::ShowPrintUIAsync();
// New approach
printDoc.Paginate([](IInspectable const&, PaginateEventArgs const& args)
{
// Create custom print logic
});
printDoc.GetPreviewPage([](IInspectable const&, GetPreviewPageEventArgs const& args)
{
// Provide preview page logic
});
printDoc.AddPages([](IInspectable const&, AddPagesEventArgs const& args)
{
// Add content pages to print
});
}
void MainWindow::OnNavigationViewItemInvoked(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::NavigationViewItemInvokedEventArgs const& e)
{
auto invokedItemContainer = e.InvokedItemContainer().as<winrt::Microsoft::UI::Xaml::Controls::NavigationViewItem>();
auto tag = winrt::unbox_value_or<hstring>(invokedItemContainer.Tag(), L"");
auto type = winrt::Windows::UI::Xaml::Interop::TypeName{ tag, winrt::Windows::UI::Xaml::Interop::TypeKind::Metadata };
NavContent().Navigate(type);
}
void MainWindow::NavigateToPage(hstring const& pageName)
{
// Find the NavigationViewItem with the specified tag
for (auto const& item : NavControl().MenuItems())
{
if (auto navItem = item.try_as<winrt::Microsoft::UI::Xaml::Controls::NavigationViewItem>())
{
if (winrt::unbox_value_or<hstring>(navItem.Tag(), L"") == pageName)
{
// Set the selected item
NavControl().SelectedItem(navItem);
// Navigate to the page
auto type = winrt::Windows::UI::Xaml::Interop::TypeName{ pageName, winrt::Windows::UI::Xaml::Interop::TypeKind::Metadata };
NavContent().Navigate(type);
return;
}
}
}
}
}
Updated
I have tried this also bot it’s not working
// file: MainWindow.xaml.cpp
#include <Printmanagerinterop.h>
...
void printFrameworkElement(FrameworkElement const& element)
{
using namespace winrt::Windows::Graphics::Printing;
using namespace winrt::Microsoft::UI::Xaml::Printing;
HWND hwnd = GetActiveWindow();
// Create a PrintManager
com_ptr<IPrintManagerInterop> printManagerInterop;
PrintManager printManager = nullptr;
// Get the PrintManager for the current window
check_hresult(printManagerInterop->GetForWindow(hwnd, __uuidof(IPrintManagerInterop), winrt::put_abi(printManager)));
// Register for the PrintTaskRequested event
printManager.PrintTaskRequested({ this, &MainWindow::OnPrintTaskRequested });
}
Gives runtime error: printManagerInterop.m_ptr was nullptr.
3