WinUI3: How to print framework element using cpp

Jens Tirsvad Nielsen 0 Reputation points
2024-12-24T23:57:15.6233333+00:00

My app have to windows. Depending on which the print is called from we getting the actual hWnd.
My issue is how to to get an instance of printManager or is there another way to print from winui 3?

// file: MainWindow.xaml.cpp
...
#include <Printmanagerinterop.h>
...
// Manually define CLSID_PrintManager
DEFINE_GUID(CLSID_PrintManager, 0x92788047, 0x3b5e, 0x41c7, 0x86, 0x2e, 0x4c, 0xd3, 0x0d, 0x45, 0xa3, 0x10);
...    

	void MainWindow::printFrameworkElement(FrameworkElement const& element)
    {
        using namespace winrt::Windows::Graphics::Printing;
        using namespace Windows::Graphics::Printing;
        using namespace winrt::Microsoft::UI::Xaml::Printing;
        // Retrieve the window handle (HWND) of the current WinUI 3 window.
        // @see https://learn.microsoft.com/en-us/windows/apps/develop/ui-input/retrieve-hwnd
        auto windowNative{ this->m_inner.as<::IWindowNative>() };
        HWND hWnd{ nullptr };
        windowNative->get_WindowHandle(&hWnd);
        if (!hWnd)
        {
            OutputDebugStringW(L"Failed to retrieve the window handle of the current WinUI 3 window.");
            return;
        }
        // Initialize COM library
        HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
        if (FAILED(hr))
        {
            OutputDebugString(L"Failed to initialize COM library.\n");
            return;
        }
        // Create an instance of IPrintManagerInterop
        com_ptr<IPrintManagerInterop> printManagerInterop;
        hr = CoCreateInstance(CLSID_PrintManager, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(printManagerInterop.put()));
        if (FAILED(hr))
        {
            OutputDebugString(L"Failed to create instance of IPrintManagerInterop.\n");
            return;
        }

Its failing to create an instance of IPirntManagerInterop

Windows App SDK
Windows App SDK
A set of Microsoft open-source libraries, frameworks, components, and tools to be used in apps to access Windows platform functionality on many versions of Windows. Previously known as Project Reunion.
807 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,818 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Darran Rowe 1,321 Reputation points
    2024-12-30T00:48:36.9066667+00:00

    This is exposed through the IPrintManagerInterop interface in the PrintManagerInterop.h header.

    What makes these awkward is that this is an interface exposed on the activation factory.

    	winrt::Windows::Foundation::IAsyncAction main_window::on_lbuttonup(mouse_vkey, int32_t, int32_t)
    	{
    		HWND my_hwnd = get_handle();
    		auto af = winrt::get_activation_factory<winrt::Windows::Graphics::Printing::PrintManager, IPrintManagerInterop>();
    		winrt::Windows::Graphics::Printing::PrintManager print_manager{ nullptr };
    		winrt::check_hresult(af->GetForWindow(my_hwnd, winrt::guid_of<winrt::Windows::Graphics::Printing::IPrintManager>(), winrt::put_abi(print_manager)));
    
    		//Set the PrintTaskRequested event here.
    
    		winrt::Windows::Foundation::IAsyncOperation<bool> print_manager_show{ nullptr };
    
    		winrt::check_hresult(af->ShowPrintUIForWindowAsync(my_hwnd, winrt::guid_of<winrt::Windows::Foundation::IAsyncOperation<bool>>(), winrt::put_abi(print_manager_show)));
    
    		co_await print_manager_show;
    
    		co_return;
    	}
    

    It is also an ABI interface, so it is a bit of a pain to use, but it is easy enough to wrap it if desired. The important parts of this are the use of this one particular winrt::get_activation_factory template overload. The first template parameter provided is the C++/WinRT projection type that we wish to get the activation factory for, and the second template parameter is the interface that we wish to query for. IPrintManagerInterop::GetForWindow is called, to get an instance of Windows.Graphics.Printing.PrintManager, and we place it in the C++/WinRT projection type using winrt::put_abi. The interface that this queries for, IPrintManager, is important. This is the default interface for the PrintManager runtime class and it is what C++/WinRT expects.

    Once the PrintTaskRequested event handler has been set, IPrintManagerInterop::ShowPrintUIForWindowAsync is called. Again, this is an ABI member, so the C++/WinRT ABI compatibility functionality is used to place it in a C++/WinRT projection type. We then await on the async type.

    This should work, but I admit that didn't have a printable document available. This is the kind of code that should be expected. As a side note, this is in a Windows API application, not a WinUI 3 application. So this code shouldn't just be copied as is. But this is an idea as to how any event handlers should be formed. The return is required in C++ to make this into a coroutine, this allows the use of co_await.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.