Совершенствование возможностей печати в Windows 8

При переосмыслении Windows мы воспользовались возможностью заново обдумать все аспекты печати — удобство для пользователей, платформу для разработчиков и широкую экосистему устройств, а также их взаимодействие — чтобы создать условия для еще более эффективной работы. В этой статье я расскажу о таких аспектах печати в Windows 8, как удобство для пользователей и платформа для разработчиков. Я также расскажу, как привести взаимодействие с пользователем в соответствие с требованиями приложения.

Печать из приложений для Windows 8

Сначала давайте рассмотрим, как работает печать в Windows 8, а затем перейдем к особенностям печати в разных типах приложений.

Печать в Windows 8 зависит от контекста соответствующего приложения. Приложение поддерживает печать благодаря регистрации контракта "Печать". Вы сами решаете, когда ваше приложение поддерживает печать, а когда — нет. Не у всех приложений есть необходимость в печати. Например, если вы разрабатываете игру, вы можете решить, что для нее печать не нужна. Но если вы разрабатываете приложение для бронирования авиабилетов, возможность распечатки посадочного талона очень пригодится для последующей регистрации на рейс. Вы сами решаете, нужна ли в приложении печать и в каких случаях она требуется, однако вы должны учитывать и ожидания пользователей. Если пользователи ожидают поддержку печати в вашем приложении, мы рекомендуем оснастить его этой функцией.

Для печати в Windows 8 быстро проведите пальцем от правого края экрана, чтобы увидеть чудо-кнопки. Если приложение поддерживает печать, вы увидите все принтеры, установленные на вашем компьютере, коснувшись чудо-кнопки "Устройства". Выбрав желаемый принтер, вы увидите такое же окно печати, как представлено здесь.

Поток задания печати

Поток задания печати

Окно печати дает возможность предварительного просмотра печатаемого документа и отображает несколько основных параметров печати. Работая над функцией печати, мы часто слышали от пользователей пожелание иметь возможность увидеть печатаемый контент до печати. Платформа печати поддерживает предварительный просмотр печатаемого контента в окне печати, освобождая вас от необходимости создавать функцию предварительного просмотра в своем приложении. Платформа печати позволяет также обновлять изображение в окне предварительного просмотра, если были изменены параметры печати.

Чтобы упростить стандартный процесс печати, в окне печати по умолчанию отображаются только три параметра печати: число копий, ориентация страницы и цветность. Наши исследования показывают, что чаще всего пользователи меняют именно эти параметры печати. Мы отобразили эти параметры, чтобы пользователи могли быстро изменять их при настройке задания печати. Вы как разработчик приложения можете задавать параметры, которые будут отображаться в окне печати, с учетом особенностей вашего приложения. Вы можете также задавать значения по умолчанию для каждого параметра.

Во всех приложениях для Windows 8 печать контента реализована одинаковым образом. Поэтому пользователь, умеющий выполнять печать из одного приложения, сможет выполнить печать из любого другого. Это означает, что при работе с каждым следующим приложением пользователям не придется осваивать функцию печати заново.

Контракт "Печать"

Для связи с платформой печати ваше приложение использует контракт "Печать". Приложение предоставляет контент для печати, а Windows обеспечивает интерфейс печати и сопутствующие функции. Когда ваше приложение регистрирует контракт "Печать", доступ к печати становится простым и удобным благодаря чудо-кнопке "Устройства".

Контракт "Печать", как и все API WinRT, предназначен для работы с языком и средой пользовательского интерфейса по вашему выбору — независимо от того, используете ли вы для разметки контента HTML или XAML. Если вам нужны более развитые возможности управления печатью контента в своем приложении, вы можете воспользоваться технологиями D2D или XPS.

Добавляя поддержку печати в свое приложение, необходимо учитывать два ключевых момента:

  • Предоставление контента для печати.
  • Определение параметров печати, наиболее подходящих для вашего приложения.

Давайте рассмотрим каждый из них.

Предоставление контента для печати

Разрабатывая приложение, не забудьте продумать для него сценарии печати. Какой контент пользователь скорее всего захочет взять с собой в дорогу? Какой контент пользователь скорее всего захочет иметь в виде бумажной копии? Если в вашем приложении фигурируют фотографии, будут ли пользователи рады возможности распечатать их, поместить в рамку и повесить у себя дома? Продуманные сценарии приложения помогут вам определить, для какого именно контента нужна функция печати, и спроектировать соответствующие возможности оптимальным образом.

Определив, для какого именно контента требуется печать, продумайте, откуда будет исходить контент для печати. Прежде всего, важно понимать, что контент, который хорошо выглядит на экране, может не столь удачно смотреться на бумаге. Вам действительно нужно продумать оптимальное форматирование контента для обоих случаев. Это означает, что на печать скорее всего будет выводиться несколько иное изображение, чем в главном представлении вашего приложения (контент на экране). Это относится ко всем типам приложений, даже к таким простым, как новостные. Контент, аккуратно размещенный в столбцах на экране, может при той же разметке не столь же хорошо смотреться на бумаге. Следует учитывать все эти соображения при работе над приложением. Причем проще учесть их на ранней стадии проектирования, чем впоследствии возвращаться и вносить изменения в уже готовые компоненты.

Нелишне также подумать, как вписать печать в рабочий процесс приложения. Во многих приложениях печать — это просто элемент меню. Например, пользователю может потребоваться распечатать просматриваемую фотографию. В этом случае будет правильно сделать первым шагом к печати обращение к чудо-кнопке "Устройства". Иными словами, было бы неправильно добавлять в приложение специальную возможность для запуска печати — вместо этого применяйте соответствующую чудо-кнопку. С другой стороны, бывают случаи, когда печать является важной частью общего рабочего процесса приложения. Рассмотрим приложение для покупок с функцией распечатки чеков. В представлении на экране могут отображаться подтверждение заказа и благодарность клиенту за покупку, а также кнопка Распечатать чек, с которой как раз и начинается процесс печати. Когда пользователь касается кнопки Распечатать чек, открывается окно печати, дающее возможность предварительного просмотра чека и вывода его на печать именно в этом виде, например, как здесь:

Печать контента в ином виде, чем в представлении на экране

Печать контента в ином виде, чем в представлении на экране

Печать из приложений на HTML/JavaScript

Чтобы добавить поддержку печати в приложение, достаточно добавить в него эти строки кода.

 // Register for print contract
var printManager = Windows.Graphics.Printing.PrintManager.getForCurrentView();
printManager.onprinttaskrequested = onPrintTaskRequested;
    function onPrintTaskRequested(printEvent) {
        printEvent.request.createPrintTask("Print Sample", function (args) {
            args.setSource(MSApp.getHtmlPrintDocumentSource(document));
        });
    } 

Эти строки кода регистрируют для вашего приложения контракт "Печать". Когда пользователь выбирает функцию печати, приложение просто распечатывает текущий документ — то, что отображается на экране. Теперь можно печатать контент из вашего приложения с помощью чудо-кнопки "Устройства". Приложение отображает интерфейс печати со стандартными параметрами печати. Механизм визуализации Windows 8 выполняет разбивку на страницы и обновляет изображение в окне предварительного просмотра.

В других сценариях вам требуется выбирать, что именно печатать и как размечать контент для печати. Например, вам может потребоваться распечатать контент, который в данный момент не отображается на экране, например контент, не являющийся текущим объектом DOM (наподобие чека, который мы сейчас рассматривали). Самый простой способ — указать альтернативный контент как часть элемента head в вашем HTML-коде, как показано ниже.

 <! -- Add this to the head element of your html file -->
<link rel="alternate" href="https://go.microsoft.com/fwlink/?linkid=240076" media="print"/>  

При этом обращение к getHtmlPrintDocumentSource(document) правильно использует указанный альтернативный контент.

А если хочется проявить более творческий подход? К счастью, направив документ HTML на обработку методом getHtmlPrintDocumentSource, вы можете распечатать документ HTML, полученный откуда угодно: созданный локально, загруженный из Интернета в элемент IFrame или полученный любым иным способом, который вы захотите применить для создания печатного документа.

Вы можете также использовать в интерфейсе своего приложения сложные элементы управления разметкой, такие как разметка в несколько столбцов, горизонтальная прокрутка и группировка элементов. В таких случаях разметка может нарушаться при печати. Очень важно упростить разметку перед отправкой ее на платформу печати для упрощения разбивки контента на страницы и предварительного просмотра, и этого можно достичь с помощью правил CSS. Определение правил CSS для средств печати помогает создать иную разметку, чем та, которую пользователь видит в процессе работы с вашим приложением. С помощью CSS вы можете скрывать контент, менять размер элементов, регулировать поля, удалять такие элементы, как фон и полоса прокрутки, изменять шрифты и цвета и многое другое. Рассмотрим пример.

Представим приложение, позволяющее распечатывать рецепты ваших любимых блюд. Это приложение основано на шаблоне приложения таблицы (Файл->Создать проект-><Язык>->Магазин Windows->Приложение таблицы).

Приложение для рецептов

Приложение для рецептов

Прежде всего, необходимо продумать, для какой части контента действительно нужна печать. Допустим, что пользователь, напечатав документ, добавит его в книгу рецептов — тогда такие сведения, как рейтинги и отзывы, вряд ли важны. Итак, нам нужно распечатать заголовок, изображение, описание, список ингредиентов и указания по приготовлению. Мы не станем распечатывать остальной контент, например рейтинги, отзывы и прочее.

Вот как выглядит CSS-файл для отображения контента на экране.

 .itemdetailpage .content {
-ms-grid-row: 1;
-ms-grid-row-span: 2;
display: block;
height: 100%;
overflow-x: auto;
position: relative;
    width: 100%;
z-index: 0;}

.itemdetailpage .content article {
/* Define a multi-column, horizontally scrolling article by default. */
column-fill: auto;
column-gap: 80px;
column-width: 480px;
height: calc(100% - 183px);
margin-left: 120px;
margin-top: 133px;
width: 480px;}

.itemdetailpage .content article header .item-title {
margin-bottom: 19px;}

.itemdetailpage .content article .item-image {
height: 240px;
width: 460px;}

.itemdetailpage .content article .item-rating {
height: 40px;
margin-top: 0px}

.itemdetailpage .content article .item-review {
height: 100px;
margin-top: 20px }

.itemdetailpage .content article .item-content p {
margin-top: 10px;
margin-bottom: 20px;
margin-right: 20px;}

А вот что вы увидите в окне предварительного просмотра.

Печать без форматирования контента

Печать без форматирования контента

Предварительный просмотр выявил несколько проблем. Вы видите кнопку "Назад" рядом с заголовком, а также полосу прокрутки. Более того, в окне предварительного просмотра отображается только первая страница. В результате изображение в окне предварительного просмотра — неправильное.

Происходит следующее: когда контент приложения на помещается на экране, свойство overflow добавляет полосу прокрутки, чтобы с помощью нее можно было просмотреть скрытый контент. При отправке контента на печать такое поведение сохраняется, что приводит к усечению контента. Чтобы контент выводился на печать с правильной разметкой, его необходимо отформатировать с помощью правил CSS.

Чтобы разметить контент для печати, нужно создать CSS-файл (print.css) и добавить его к файлу html.

 <link rel="stylesheet" type="text/css" href="/css/print.css" media="print" />
 Print.css
/* Hide the back button */
.win-backbutton {
display: none;}

/* Remove the grid layout */
.fragment {
display: block;
height: auto;
width: 100%;
position: relative;
margin: 0px;
overflow: visible;}

/* Remove the header */
.fragment header[role=banner] {
display: none;}

/* Remove multicolumn layout */
/* Resize the content to take up available space*/
/* Remove scrolling behavior */
.itemdetailpage .content {
display: block;
height: 100%;
overflow: visible;
width: 100%;}

.itemdetailpage .content article {
height: 100%;
width: 100%;
margin: 0px;
overflow: visible;}

/* Adjust margins */
/* Increase font sizes */
.itemdetailpage .content article header .item-title {
margin-bottom: 29px;
font-size: 450%;}

.itemdetailpage .content article .item-image {
height: 480px;
width: 920px;
margin-top: 20px;
margin-bottom: 40px;}

/* Remove rating and review controls */
.itemdetailpage .content article .item-rating {
display: none;}
.itemdetailpage .content article .item-review {
display: none; }

.itemdetailpage .content article .item-content p {
height: auto;
width: 100%;}

Тогда изображение в окне предварительного просмотра и на печати получится таким, как здесь.

Печать с форматированием контента

Печать с форматированием контента

Обратите внимание, что те проблемы, которые мы видели ранее, устранены. В окне предварительного просмотра больше не видна кнопка "Назад" рядом с заголовком, не видна и полоса прокрутки. При переходе на следующую страницу в окне предварительного просмотра будет видно, что контент аккуратно размещен на странице. С помощью CSS можно эффективно размечать контент для печати именно так, как это нужно вам.

Подробнее о печати из приложений, написанных на HTML и JavaScript, можно прочитать в статье, посвященной поддержке печати в приложениях на JavaScript и HTML.

Печать из приложений на XAML

Если вы пишете приложение на XAML, вам предстоит проработать больше вопросов, касающихся печати из приложения. Вам нужно определить, как размечается контент для вашего приложения, и разобраться с разбиением на страницы. Таким образом вы сможете управлять контентом каждой страницы, чтобы точно определять, какой именно контент требуется печатать. Как и можно было ожидать, XAML используется для определения разметки печатаемого контента вашего приложения подобно тому, как вы используете XAML для определения разметки изображения на экране.

XAML — это отличный язык описания, обеспечивающий гибкость для отображения контента на экране, особенно когда в приложении требуется применять масштабирование для адаптации под разные размеры экрана. Но достоинства XAML при отображении контента на экране не всегда оказываются таковыми при печати контента на бумаге. Например, в разметках XAML шрифты и изображения часто масштабируются согласно размеру экрана в пикселях по вертикали и горизонтали. На экране все отлично, но пользователи вовсе не хотят, чтобы и напечатанный документ был масштабирован. Поэтому вам нужно продумать, как должен выглядеть контент приложения в напечатанном виде, на бумаге, и проследить, чтобы ваша разметка XAML была выполнена соответствующим образом.

Возвращаясь к приложению для рецептов, давайте посмотрим, как осуществить разметку контента с помощью XAML. В XAML интересующий нас контент находится в пределах ItemDetailPage в элементе управления richTextColumns. Чтобы получить информацию, которую нам нужно распечатать (т. е. заголовок, изображение, описание, список ингредиентов и указания по приготовлению), определим страницу рецепта как список связанных контейнеров.

 <Grid VerticalAlignment="Center" x:Name="grid">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    
    <Grid.RowDefinitions>
        <RowDefinition Height="3*"/>
        <RowDefinition Height="7*"/>
    </Grid.RowDefinitions>
    
    <RichTextBlock x:Name="txtContent" OverflowContentTarget="{Binding ElementName=link}" Grid.Row="0" Grid.Column="0">
        <Paragraph TextAlignment="Center">
            <Run x:Name="txtRecipe" Text="{Binding Title}" FontSize="30" Foreground="Black"></Run>
        </Paragraph>
        <Paragraph>
            <InlineUIContainer>
                <Image x:Name="imgRecipe" Stretch="Uniform" Source="{Binding Image}"/>
            </InlineUIContainer>
        </Paragraph>
        <Paragraph>
            <Run Text="Ingredients:" FontSize="30" Foreground="Black"/>
            <Run x:Name="txtIngredients" Text="{Binding RecipeIngredients}" FontSize="20" Foreground="Black"/>
        </Paragraph>
        <Paragraph>
            <Run Text="Details:" FontSize="30" Foreground="Black"/>
            <Run x:Name="txtDetails" Text="{Binding Content}" FontSize="20" Foreground="Black"/>
        </Paragraph>
    </RichTextBlock>
    
    <RichTextBlockOverflow x:Name="link" Grid.Row="1" Grid.Column="0"/>
</Grid>

В тех случаях, когда относящийся к рецепту контент не помещается на странице печати, приложение должно создавать дополнительные страницы. Тогда дополнительная страница просто будет содержать элемент RichTextBlockOverlow, связанный с элементом блока форматированного текста с предыдущей страницы, чтобы не помещающийся текст переходил на новую страницу.

 <Grid x:Name="grid">
    <RichTextBlockOverflow x:Name="link"/>
</Grid>

Что касается разбивки на страницы, алгоритм деления на страницы можно задать так:

 void printDocument_Paginate(object sender, PaginateEventArgs e)
{
    PrintDocument printDocument = (PrintDocument)sender;

    // get printer page description
    PrintPageDescription pageDesc = e.PrintTaskOptions.GetPageDescription(0);
    
    // clear previous generated print content
    pages.Clear();
    printingRoot.Children.Clear();

    RecipePage page = new RecipePage(pageDesc)
    {
        DataContext = flipView.SelectedItem
    };

    UIElement element = null;
    RichTextBlockOverflow rtbo = page.Link;

    do
    {
// check if this is the first page
        if (element != null)
        {
            var continuation = new ContinuationPage(rtbo, pageDesc);
            element = continuation;
            rtbo = continuation.Link;
        }
        else
        {
            element = page;
        }

        // add the page to the visual tree to forece content flow
        printingRoot.Children.Add(element);
        printingRoot.InvalidateMeasure();
        printingRoot.UpdateLayout();

        pages.Add(element);

    } while (rtbo.HasOverflowContent);

    // set the current number of pages
    printDocument.SetPreviewPageCount(pages.Count, PreviewPageCountType.Intermediate);
}

Подробнее о печати из приложений, написанных на XAML, можно прочитать в статье, посвященной печати из приложений на C#/VB/C++ и XAML.

Определение параметров печати, наиболее подходящих для вашего приложения

Когда вы определите, для какого именно контента вашего приложения потребуется печать и как должен выглядеть напечатанный контент, продумайте, какие возможности печати следует добавить в приложение.

Может выясниться, что доступных по умолчанию трех параметров печати недостаточно. Возможно, вы захотите отобразить в окне печати дополнительные параметры или добавить свои собственные. В таком случае вы можете настроить функции печати в соответствии с требованиями вашего приложения.

Рассмотрим несколько примеров.

Добавление параметров печати

Вернемся к приложению для рецептов. Мы знаем, что рецепты могут занимать по несколько страниц. Вероятно, вам захочется добавить возможность двусторонней печати. Это можно сделать, добавив в окно печати параметр "Двусторонняя печать".

Теперь окно печати выглядит так:

Печать с дополнительными параметрами печати

Печать с дополнительными параметрами печати

Вот как добавить параметр "Двусторонняя печать" в JavaScript:

 printTask.options.displayedOptions.append
   (Windows.Graphics.Printing.StandardPrintTaskOptions.duplex);

А вот как добавить параметр "Двусторонняя печать" в C#:

 printTask.options.displayedOptions.Add (Windows.Graphics.Printing.StandardPrintTaskOptions.Duplex);

"Двусторонняя печать" — лишь один из многих параметров печати, которые можно выбрать. Но даже если вы хотите выполнить двустороннюю печать, этот параметр может и не отобразиться. Если принтер не поддерживает двустороннюю печать, Windows скроет эту настройку от пользователя. Подробнее о добавлении параметров печати можно прочитать в статьях, посвященных изменению стандартных параметров в окне печати для HTML/JavaScript и XAML.

Добавление настраиваемых параметров в приложения на XAML

Для приложений на XAML можно выполнить дополнительную настройку. Для таких приложений вы можете добавить настраиваемые параметры в окно печати. Рассмотрим пример.

Рассмотрим приложение, позволяющее распечатывать карты с проложенными маршрутами. Возможно, вы подумаете: "Распечатка карт может оказаться затратной, поскольку чернила дорогие. Как мне дать пользователям возможность выбирать, что печатать?" Вам может пригодиться такой параметр, как Тип маршрута:

Печать с настраиваемыми параметрами

Печать с настраиваемыми параметрами

В этом примере в приложение был добавлен параметр "Тип маршрута" с тремя вариантами: "Карта и текст", "Только карта" и "Только текст". Таким образом, пользователи могут выбирать, в каком виде распечатать карту.

Вот как добавить настраиваемый параметр наподобие этого:

 PrintCustomItemListOptionDetails pageFormat = printDetailedOptions.CreateItemListOption 
   ("PageContent", "Pictures");
pageFormat.AddItem ("MapText", "Map and text");
pageFormat.AddItem ("MapOnly", "Map only");
pageFormat.AddItem ("TextOnly", "Text only");

// Add the custom option to the option list
displayedOptions.Add ("PageContent");

printDetailedOptions.OptionChanged += printDetailedOptions_OptionChanged;

Подробнее об этом компоненте можно прочитать в статье, посвященной добавлению пользовательских параметров в окно печати.

Заключение

Контракт "Печать" дает вам гибкие возможности для принятия решений о том, что и в каком виде печатать из вашего приложения.При этом пользователи могут выполнять печать таким же образом, как из любого другого приложения для Windows 8. Можно использовать для печати стандартный интерфейс или настроить интерфейс печати в соответствии с требованиями вашего приложения. Вам всегда предоставляются гибкие возможности для управления печатью из вашего приложения.

Справочные материалы

Ссылка

Типы

Образец контракта "Печать"

Образец

Регистрация контракта "Печать" в HTML/JavaScript

Документ

Регистрация контракта "Печать" в XAML

Документ

Справочник по пространству имен Windows.Graphics.Printing

Документ

Справочник по пространству имен Windows.Graphics.Printing.OptionDetails

Документ

Санджита Ранджит (Sangeeta Ranjit), старший руководитель программы, устройства и сетевые возможности Windows

Соавторы: Даррен Дэвис (Darren Davis), Дэниел Алекс Вольчинский (Daniel Alex Volcinschi), Саумья Джайн (Saumya Jain), Трэвис Иби (Travis Eby)