locked
Windows 8.1 3d Printing Sample

    Question

  • So, I got my app almost done. I am starting to integrate 3d printing into the app using the 3d printing sample here http://code.msdn.microsoft.com/windowsapps/3D-Printing-Sample-b5b75c86 . While I got the export to the 3MF format working I am stuck at generating the print preview. The Documentation found here http://msdn.microsoft.com/en-us/library/windows/apps/dn263137.aspx is really sparse. So my question is how can I generate a preview Image for printing from my d3d renderer? Thanks
    Wednesday, November 06, 2013 9:48 PM

Answers

  • Here is the doc part.

    //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
    //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
    //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
    //// PARTICULAR PURPOSE.
    ////
    //// Copyright (c) Microsoft Corporation. All rights reserved
    
    #include "pch.h"
    #include "docsource.h"
    #include "documentsource.h"
    using namespace Microsoft::WRL;
    using namespace Windows::Graphics::Printing;
    
    #pragma region IDocumentPageSource Methods
    
    IFACEMETHODIMP
    CDocumentSource::GetPreviewPageCollection(
        _In_  IPrintDocumentPackageTarget*  docPackageTarget,
        _Out_ IPrintPreviewPageCollection** docPageCollection
        )
    {
        HRESULT hr = (docPackageTarget != nullptr) ? S_OK : E_INVALIDARG;
    
        // Get for IPrintPreviewDxgiPackageTarget interface.
        if (SUCCEEDED(hr))
        {
            hr = docPackageTarget->GetPackageTarget(
                ID_PREVIEWPACKAGETARGET_DXGI,
                IID_PPV_ARGS(&m_dxgiPreviewTarget)
                );
        }
    
        ComPtr<IPrintPreviewPageCollection> pageCollection;
        if (SUCCEEDED(hr))
        {
            ComPtr<CDocumentSource> docSource(this);
            hr = docSource.As<IPrintPreviewPageCollection>(&pageCollection);
        }
    
        if (SUCCEEDED(hr))
        {
            hr = pageCollection.CopyTo(docPageCollection);
        }
    
        return hr;
    }
    
    IFACEMETHODIMP
    CDocumentSource::MakeDocument(
        _In_ IInspectable*                docOptions,
        _In_ IPrintDocumentPackageTarget* docPackageTarget
        )
    {
        if (docOptions == nullptr || docPackageTarget == nullptr)
        {
            return E_INVALIDARG;
        }
    
        // Get print settings from PrintTaskOptions for printing, such as page description, which contains page size, imageable area, DPI.
        // User can obtain other print settings in the same way, such as ColorMode, NumberOfCopies, etc., which are not shown in this sample.
        PrintTaskOptions^ option = reinterpret_cast<PrintTaskOptions^>(docOptions);
        PrintPageDescription pageDesc = option->GetPageDescription(1); // Get the description of the first page.
    
        // Create a print control properties and set DPI from PrintPageDescription.
        D2D1_PRINT_CONTROL_PROPERTIES printControlProperties;
    
        printControlProperties.rasterDPI  = (float)(min(pageDesc.DpiX, pageDesc.DpiY)); // DPI for rasterization of all unsupported D2D commands or options
        printControlProperties.colorSpace = D2D1_COLOR_SPACE_SRGB;                  // Color space for vector graphics in D2D print control.
        printControlProperties.fontSubset = D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT;    // Subset for used glyphs, send and discard font resource after every five pages
    
        HRESULT hr = S_OK;
    
        try
        {
            // Create a new print control linked to the package target.
            m_renderer->CreatePrintControl(
                docPackageTarget,
                &printControlProperties
                );
    
            // Calculate imageable area and page size from PrintPageDescription.
            D2D1_RECT_F imageableRect = D2D1::RectF(
                pageDesc.ImageableRect.X,
                pageDesc.ImageableRect.Y,
                pageDesc.ImageableRect.X + pageDesc.ImageableRect.Width,
                pageDesc.ImageableRect.Y + pageDesc.ImageableRect.Height
                );
    
            D2D1_SIZE_F pageSize = D2D1::SizeF(pageDesc.PageSize.Width, pageDesc.PageSize.Height);
    
            // Loop to add page command list to d2d print control.
            for (uint32 pageNum = 1; pageNum <= m_totalPages; ++pageNum)
            {
                m_renderer->PrintPage(
                    pageNum,
                    imageableRect,
                    pageSize,
                    nullptr // If a page-level print ticket is not specified here, the package print ticket is applied for each page.
                    );
            }
        }
        catch (Platform::Exception^ e)
        {
            hr = e->HResult;
    
            if (hr == D2DERR_RECREATE_TARGET)
            {
                // In case of device lost, the whole print job will be aborted, and we should recover
                // so that the device is ready when used again. At the same time, we should propagate
                // this error to the print UI.
                m_renderer->HandleDeviceLost();
            }
        }
    
        // Make sure to close d2d print control even if AddPage fails.
        HRESULT hrClose = m_renderer->ClosePrintControl();
    
        if (SUCCEEDED(hr))
        {
            hr = hrClose;
        }
    
        return hr;
    }
    
    
    
    void CDocumentSource::SetPrintTask(
        _In_ PrintManager^ /*sender*/,
        _In_ PrintTaskRequestedEventArgs^ args
        )
    {
        PrintTaskSourceRequestedHandler^ sourceHandler =
            ref new PrintTaskSourceRequestedHandler([this](PrintTaskSourceRequestedArgs^ args)-> void{
                Microsoft::WRL::ComPtr<CDocumentSource> documentSource;
                DX::ThrowIfFailed(
    				Microsoft::WRL::MakeAndInitialize<CDocumentSource>(&documentSource, reinterpret_cast<IUnknown*>(m_renderer))
                    );
    
                // Here CDocumentSource is inherited from IPrintDocumentSource, cast it back to an object.
                Windows::Graphics::Printing::IPrintDocumentSource^ objSource(
                    reinterpret_cast<Windows::Graphics::Printing::IPrintDocumentSource^>(documentSource.Get())
                    );
    
                args->SetSource(objSource);
            });
    
        // Request initializing print task.
        PrintTask^ printTask = args->Request->CreatePrintTask(
            L"Direct2D Windows Store app printing sample",
            sourceHandler
            );
    }
    
    
    #pragma endregion IDocumentPageSource Methods
    
    #pragma region IPrintPreviewPageCollection Methods
    
    IFACEMETHODIMP
    CDocumentSource::Paginate(
        _In_   uint32           currentJobPage,
        _In_   IInspectable*    docOptions
        )
    {
        HRESULT hr = (docOptions != nullptr) ? S_OK : E_INVALIDARG;
    
        if (SUCCEEDED(hr))
        {
            // Get print settings from PrintTaskOptions for preview, such as page description, which contains page size, imageable area, DPI.
            // User can obtain other print settings in the same way, such as ColorMode, NumberOfCopies, etc., which are not shown in this sample.
            PrintTaskOptions^ option = reinterpret_cast<PrintTaskOptions^>(docOptions);
            PrintPageDescription pageDesc = option->GetPageDescription(currentJobPage);
    
            hr = m_dxgiPreviewTarget->InvalidatePreview();
    
            // Set the total page number.
            if (SUCCEEDED(hr))
            {
                hr = m_dxgiPreviewTarget->SetJobPageCount(PageCountType::FinalPageCount, m_totalPages);
            }
    
            if (SUCCEEDED(hr))
            {
                m_width = pageDesc.PageSize.Width;
                m_height = pageDesc.PageSize.Height;
    
                m_imageableRect = D2D1::RectF(
                    pageDesc.ImageableRect.X,
                    pageDesc.ImageableRect.Y,
                    pageDesc.ImageableRect.X + pageDesc.ImageableRect.Width,
                    pageDesc.ImageableRect.Y + pageDesc.ImageableRect.Height
                    );
    
                // Now we are ready to let MakePage to be called.
                m_paginateCalled = true;
            }
        }
    
        return hr;
    }
    
    // Here, desiredWidth/desiredHeight is the desired size of preview surface by print mananger in system.
    // The final size of the preview surface must have the same proportion as that of the desired width/height.
    // In this sample, we just use it as preview size and return the scale variant for surface drawing.
    // The size here is in DIPs.
    float
    CDocumentSource::TransformedPageSize(
        _In_  float                         desiredWidth,
        _In_  float                         desiredHeight,
        _Out_ Windows::Foundation::Size*    previewSize
        )
    {
        float scale = 1.0f;
    
        if (desiredWidth > 0 && desiredHeight > 0)
        {
            previewSize->Width  = desiredWidth;
            previewSize->Height = desiredHeight;
    
            scale = m_width / desiredWidth;
        }
        else
        {
            previewSize->Width = 0;
            previewSize->Height = 0;
        }
    
        return scale;
    }
    
    // This sample only acts upon orientation setting for an example. The orientation is read from the user selection
    // in the Print Experience and is then used to reflow the content in a different way.
    IFACEMETHODIMP
    CDocumentSource::MakePage(
        _In_ uint32 desiredJobPage,
        _In_ float  width,
        _In_ float  height
        )
    {
        HRESULT hr = (width > 0 && height > 0) ? S_OK : E_INVALIDARG;
    
        // When desiredJobPage is JOB_PAGE_APPLICATION_DEFINED, it means a new preview begins. If the implementation here is by an async way,
        // for example, queue MakePage calls for preview, app needs to clean resources for previous preview before next.
        // In this sample, we will reset page number if Paginate() has been called.
        if (desiredJobPage == JOB_PAGE_APPLICATION_DEFINED && m_paginateCalled)
        {
            desiredJobPage = 1;
        }
    
        if (SUCCEEDED(hr) && m_paginateCalled)
        {
            // Calculate the size of preview surface, according to desired width and height.
            Windows::Foundation::Size previewSize;
            float scale = TransformedPageSize(width, height, &previewSize);
    
            try
            {
                m_renderer->DrawPreviewSurface(
                    previewSize.Width,
                    previewSize.Height,
                    scale,
                    m_imageableRect,
                    desiredJobPage,
                    m_dxgiPreviewTarget.Get()
                    );
            }
            catch (Platform::Exception^ e)
            {
                hr = e->HResult;
    
                if (hr == D2DERR_RECREATE_TARGET)
                {
                    // In case of device lost, we should recover so that the device is ready to render
                    // the next preview page when requested. At the same time, we should propagate this
                    // error to the print UI.
                    m_renderer->HandleDeviceLost();
                }
            }
        }
    
        return hr;
    }
    
    
    
    
    
    #pragma region IPrintPreviewPageCollection Methods
    
    
    
    
    


    n.Wright

    Thursday, November 07, 2013 9:35 PM

All replies

  • I used the same printing example and I get a preview ok.

    I guess you must have missed a bit somewhere.


    n.Wright

    Wednesday, November 06, 2013 9:55 PM
  • How did you incorporate the sample into your own code? I want to draw part of my backbuffer to the IPrintPreviewDxgiPackageTarget. Did you try something like that?
    Wednesday, November 06, 2013 10:10 PM
  • Its a while since I did it so cant remember much about it but here is my code.

    printrender2 just calls my directx rendering routine.

    I also have a little bit of code thats sets up the print area.

    d2drenderer.cpp

    //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A //// PARTICULAR PURPOSE. //// //// Copyright (c) Microsoft Corporation. All rights reserved #include "pch.h" #include "D2DPageRendererContext.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace Windows::Foundation; using namespace Windows::UI::Core; using namespace Windows::Graphics::Display; PageRendererContext::PageRendererContext( _In_ D2D1_RECT_F targetBox, _In_ ID2D1DeviceContext* d2dContext, _In_ DrawTypes type, _In_ ref class SimpleTextRenderer^ ff ) { m_margin = 96.0f; m_d2dContext = d2dContext; m_type = type; UpdateTargetBox(targetBox); DX::ThrowIfFailed( d2dContext->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Black), &m_blackBrush ) ); // Pull out all the immutable resources from the PageRenderer that we will need. m_textFormat = ff->GetTextFormatNoRef(); m_messageFormat = ff->GetMessageFormatNoRef(); } void PageRendererContext::UpdateTargetBox(_In_ D2D1_RECT_F& targetBox) { m_targetBox = targetBox; } // Draws the scene to a rendering device context or a printing device context. void PageRendererContext::Draw(_In_ float scale) { // Clear rendering background with CornflowerBlue and clear preview // background with white color. For the printing case (command list), it // is recommended not to clear because the surface is clean when created. if (m_type == DrawTypes::Rendering) { m_d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue)); } else if (m_type == DrawTypes::Preview) { m_d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::White)); } // We use scale matrix to shrink the text size and scale is only available // for preview. For on-screen rendering or printing, scale is 1.f, that // is, the Identity is the transform matrix. m_d2dContext->SetTransform(D2D1::Matrix3x2F(1/scale, 0, 0, 1/scale, 0, 0)); int fred =ff2->Getmodeforprinter(); if (fred==0) { return; } ff2->PrintRender2(m_d2dContext); } // Draws a string to a rendering device context or a printing device context. void PageRendererContext::DrawMessage(_In_ Platform::String^ string) { // Clear rendering background with CornflowerBlue. m_d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue)); m_d2dContext->DrawText( string->Data(), string->Length(), m_messageFormat.Get(), m_targetBox, m_blackBrush.Get() ); }


    docsource.cpp
    //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
    //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
    //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
    //// PARTICULAR PURPOSE.
    ////
    //// Copyright (c) Microsoft Corporation. All rights reserved
    
    
    #include "pch.h"
    #include "D2DPageRendererContext.h"
    
    using namespace Microsoft::WRL;
    using namespace Microsoft::WRL::Wrappers;
    using namespace Windows::Foundation;
    using namespace Windows::UI::Core;
    using namespace Windows::Graphics::Display;
    
    	
    
    
    
    
    
    PageRendererContext::PageRendererContext(
        _In_ D2D1_RECT_F targetBox,
        _In_ ID2D1DeviceContext* d2dContext,
        _In_ DrawTypes type,
        _In_ ref class SimpleTextRenderer^ ff
        )
    {	
        m_margin = 96.0f;
    
        m_d2dContext = d2dContext;
    
        m_type = type;
    
        UpdateTargetBox(targetBox);
    
        DX::ThrowIfFailed(
            d2dContext->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::Black),
                &m_blackBrush
                )
            );
    
        // Pull out all the immutable resources from the PageRenderer that we will need.
        m_textFormat = ff->GetTextFormatNoRef();
        m_messageFormat = ff->GetMessageFormatNoRef();
    }
    
    void PageRendererContext::UpdateTargetBox(_In_ D2D1_RECT_F& targetBox)
    {
        m_targetBox = targetBox;
    }
    
    // Draws the scene to a rendering device context or a printing device context.
    void PageRendererContext::Draw(_In_ float scale)
    {
        // Clear rendering background with CornflowerBlue and clear preview
        // background with white color. For the printing case (command list), it
        // is recommended not to clear because the surface is clean when created.
        if (m_type == DrawTypes::Rendering)
        {
            m_d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
        }
        else if (m_type == DrawTypes::Preview)
        {
            m_d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::White));
        }
    
        // We use scale matrix to shrink the text size and scale is only available
        // for preview.  For on-screen rendering or printing, scale is 1.f, that
        // is, the Identity is the transform matrix.
        m_d2dContext->SetTransform(D2D1::Matrix3x2F(1/scale, 0, 0, 1/scale, 0, 0));
    
    
    
    	int fred =ff2->Getmodeforprinter();
    
    
    	if (fred==0)
    	{
    		
    
    		return;
    	}
    
    
    	ff2->PrintRender2(m_d2dContext);
    
           
    }
    
    // Draws a string to a rendering device context or a printing device context.
    void PageRendererContext::DrawMessage(_In_ Platform::String^ string)
    {
        // Clear rendering background with CornflowerBlue.
        m_d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
    
        m_d2dContext->DrawText(
            string->Data(),
            string->Length(),
            m_messageFormat.Get(),
            m_targetBox,
            m_blackBrush.Get()
            );
    }
    
    
    
    


    n.Wright

    Wednesday, November 06, 2013 10:21 PM
  • Thanks alot, but I am using d3d and it looks like it isn't so easy. I am stuck at how to "transfer" the backbuffer to the print preview somehow.
    Wednesday, November 06, 2013 10:31 PM
  • If you look at my code at printrender2 part. All that does is call the code to render the drawing in my main program.


    n.Wright

    Thursday, November 07, 2013 12:42 AM
  • Thank you for your help! Above you posted the same code twice was that intended?
    Thursday, November 07, 2013 3:51 PM
  • No it should have been the doc part and the d2drenderer part.


    n.Wright

    Thursday, November 07, 2013 4:54 PM
  • Here is the doc part.

    //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
    //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
    //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
    //// PARTICULAR PURPOSE.
    ////
    //// Copyright (c) Microsoft Corporation. All rights reserved
    
    #include "pch.h"
    #include "docsource.h"
    #include "documentsource.h"
    using namespace Microsoft::WRL;
    using namespace Windows::Graphics::Printing;
    
    #pragma region IDocumentPageSource Methods
    
    IFACEMETHODIMP
    CDocumentSource::GetPreviewPageCollection(
        _In_  IPrintDocumentPackageTarget*  docPackageTarget,
        _Out_ IPrintPreviewPageCollection** docPageCollection
        )
    {
        HRESULT hr = (docPackageTarget != nullptr) ? S_OK : E_INVALIDARG;
    
        // Get for IPrintPreviewDxgiPackageTarget interface.
        if (SUCCEEDED(hr))
        {
            hr = docPackageTarget->GetPackageTarget(
                ID_PREVIEWPACKAGETARGET_DXGI,
                IID_PPV_ARGS(&m_dxgiPreviewTarget)
                );
        }
    
        ComPtr<IPrintPreviewPageCollection> pageCollection;
        if (SUCCEEDED(hr))
        {
            ComPtr<CDocumentSource> docSource(this);
            hr = docSource.As<IPrintPreviewPageCollection>(&pageCollection);
        }
    
        if (SUCCEEDED(hr))
        {
            hr = pageCollection.CopyTo(docPageCollection);
        }
    
        return hr;
    }
    
    IFACEMETHODIMP
    CDocumentSource::MakeDocument(
        _In_ IInspectable*                docOptions,
        _In_ IPrintDocumentPackageTarget* docPackageTarget
        )
    {
        if (docOptions == nullptr || docPackageTarget == nullptr)
        {
            return E_INVALIDARG;
        }
    
        // Get print settings from PrintTaskOptions for printing, such as page description, which contains page size, imageable area, DPI.
        // User can obtain other print settings in the same way, such as ColorMode, NumberOfCopies, etc., which are not shown in this sample.
        PrintTaskOptions^ option = reinterpret_cast<PrintTaskOptions^>(docOptions);
        PrintPageDescription pageDesc = option->GetPageDescription(1); // Get the description of the first page.
    
        // Create a print control properties and set DPI from PrintPageDescription.
        D2D1_PRINT_CONTROL_PROPERTIES printControlProperties;
    
        printControlProperties.rasterDPI  = (float)(min(pageDesc.DpiX, pageDesc.DpiY)); // DPI for rasterization of all unsupported D2D commands or options
        printControlProperties.colorSpace = D2D1_COLOR_SPACE_SRGB;                  // Color space for vector graphics in D2D print control.
        printControlProperties.fontSubset = D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT;    // Subset for used glyphs, send and discard font resource after every five pages
    
        HRESULT hr = S_OK;
    
        try
        {
            // Create a new print control linked to the package target.
            m_renderer->CreatePrintControl(
                docPackageTarget,
                &printControlProperties
                );
    
            // Calculate imageable area and page size from PrintPageDescription.
            D2D1_RECT_F imageableRect = D2D1::RectF(
                pageDesc.ImageableRect.X,
                pageDesc.ImageableRect.Y,
                pageDesc.ImageableRect.X + pageDesc.ImageableRect.Width,
                pageDesc.ImageableRect.Y + pageDesc.ImageableRect.Height
                );
    
            D2D1_SIZE_F pageSize = D2D1::SizeF(pageDesc.PageSize.Width, pageDesc.PageSize.Height);
    
            // Loop to add page command list to d2d print control.
            for (uint32 pageNum = 1; pageNum <= m_totalPages; ++pageNum)
            {
                m_renderer->PrintPage(
                    pageNum,
                    imageableRect,
                    pageSize,
                    nullptr // If a page-level print ticket is not specified here, the package print ticket is applied for each page.
                    );
            }
        }
        catch (Platform::Exception^ e)
        {
            hr = e->HResult;
    
            if (hr == D2DERR_RECREATE_TARGET)
            {
                // In case of device lost, the whole print job will be aborted, and we should recover
                // so that the device is ready when used again. At the same time, we should propagate
                // this error to the print UI.
                m_renderer->HandleDeviceLost();
            }
        }
    
        // Make sure to close d2d print control even if AddPage fails.
        HRESULT hrClose = m_renderer->ClosePrintControl();
    
        if (SUCCEEDED(hr))
        {
            hr = hrClose;
        }
    
        return hr;
    }
    
    
    
    void CDocumentSource::SetPrintTask(
        _In_ PrintManager^ /*sender*/,
        _In_ PrintTaskRequestedEventArgs^ args
        )
    {
        PrintTaskSourceRequestedHandler^ sourceHandler =
            ref new PrintTaskSourceRequestedHandler([this](PrintTaskSourceRequestedArgs^ args)-> void{
                Microsoft::WRL::ComPtr<CDocumentSource> documentSource;
                DX::ThrowIfFailed(
    				Microsoft::WRL::MakeAndInitialize<CDocumentSource>(&documentSource, reinterpret_cast<IUnknown*>(m_renderer))
                    );
    
                // Here CDocumentSource is inherited from IPrintDocumentSource, cast it back to an object.
                Windows::Graphics::Printing::IPrintDocumentSource^ objSource(
                    reinterpret_cast<Windows::Graphics::Printing::IPrintDocumentSource^>(documentSource.Get())
                    );
    
                args->SetSource(objSource);
            });
    
        // Request initializing print task.
        PrintTask^ printTask = args->Request->CreatePrintTask(
            L"Direct2D Windows Store app printing sample",
            sourceHandler
            );
    }
    
    
    #pragma endregion IDocumentPageSource Methods
    
    #pragma region IPrintPreviewPageCollection Methods
    
    IFACEMETHODIMP
    CDocumentSource::Paginate(
        _In_   uint32           currentJobPage,
        _In_   IInspectable*    docOptions
        )
    {
        HRESULT hr = (docOptions != nullptr) ? S_OK : E_INVALIDARG;
    
        if (SUCCEEDED(hr))
        {
            // Get print settings from PrintTaskOptions for preview, such as page description, which contains page size, imageable area, DPI.
            // User can obtain other print settings in the same way, such as ColorMode, NumberOfCopies, etc., which are not shown in this sample.
            PrintTaskOptions^ option = reinterpret_cast<PrintTaskOptions^>(docOptions);
            PrintPageDescription pageDesc = option->GetPageDescription(currentJobPage);
    
            hr = m_dxgiPreviewTarget->InvalidatePreview();
    
            // Set the total page number.
            if (SUCCEEDED(hr))
            {
                hr = m_dxgiPreviewTarget->SetJobPageCount(PageCountType::FinalPageCount, m_totalPages);
            }
    
            if (SUCCEEDED(hr))
            {
                m_width = pageDesc.PageSize.Width;
                m_height = pageDesc.PageSize.Height;
    
                m_imageableRect = D2D1::RectF(
                    pageDesc.ImageableRect.X,
                    pageDesc.ImageableRect.Y,
                    pageDesc.ImageableRect.X + pageDesc.ImageableRect.Width,
                    pageDesc.ImageableRect.Y + pageDesc.ImageableRect.Height
                    );
    
                // Now we are ready to let MakePage to be called.
                m_paginateCalled = true;
            }
        }
    
        return hr;
    }
    
    // Here, desiredWidth/desiredHeight is the desired size of preview surface by print mananger in system.
    // The final size of the preview surface must have the same proportion as that of the desired width/height.
    // In this sample, we just use it as preview size and return the scale variant for surface drawing.
    // The size here is in DIPs.
    float
    CDocumentSource::TransformedPageSize(
        _In_  float                         desiredWidth,
        _In_  float                         desiredHeight,
        _Out_ Windows::Foundation::Size*    previewSize
        )
    {
        float scale = 1.0f;
    
        if (desiredWidth > 0 && desiredHeight > 0)
        {
            previewSize->Width  = desiredWidth;
            previewSize->Height = desiredHeight;
    
            scale = m_width / desiredWidth;
        }
        else
        {
            previewSize->Width = 0;
            previewSize->Height = 0;
        }
    
        return scale;
    }
    
    // This sample only acts upon orientation setting for an example. The orientation is read from the user selection
    // in the Print Experience and is then used to reflow the content in a different way.
    IFACEMETHODIMP
    CDocumentSource::MakePage(
        _In_ uint32 desiredJobPage,
        _In_ float  width,
        _In_ float  height
        )
    {
        HRESULT hr = (width > 0 && height > 0) ? S_OK : E_INVALIDARG;
    
        // When desiredJobPage is JOB_PAGE_APPLICATION_DEFINED, it means a new preview begins. If the implementation here is by an async way,
        // for example, queue MakePage calls for preview, app needs to clean resources for previous preview before next.
        // In this sample, we will reset page number if Paginate() has been called.
        if (desiredJobPage == JOB_PAGE_APPLICATION_DEFINED && m_paginateCalled)
        {
            desiredJobPage = 1;
        }
    
        if (SUCCEEDED(hr) && m_paginateCalled)
        {
            // Calculate the size of preview surface, according to desired width and height.
            Windows::Foundation::Size previewSize;
            float scale = TransformedPageSize(width, height, &previewSize);
    
            try
            {
                m_renderer->DrawPreviewSurface(
                    previewSize.Width,
                    previewSize.Height,
                    scale,
                    m_imageableRect,
                    desiredJobPage,
                    m_dxgiPreviewTarget.Get()
                    );
            }
            catch (Platform::Exception^ e)
            {
                hr = e->HResult;
    
                if (hr == D2DERR_RECREATE_TARGET)
                {
                    // In case of device lost, we should recover so that the device is ready to render
                    // the next preview page when requested. At the same time, we should propagate this
                    // error to the print UI.
                    m_renderer->HandleDeviceLost();
                }
            }
        }
    
        return hr;
    }
    
    
    
    
    
    #pragma region IPrintPreviewPageCollection Methods
    
    
    
    
    


    n.Wright

    Thursday, November 07, 2013 9:35 PM