Опубликован: 15.05.2013 | Доступ: свободный | Студентов: 265 / 9 | Длительность: 24:25:00
Специальности: Системный архитектор
Лекция 12:

Простая печать

< Лекция 11 || Лекция 12: 12 || Лекция 13 >

Источники документов для печати

Независимо от того, где пользователю понадобилось вывести данные на печать, главное – подготовить эти данные к печати. Основная функция, о которой вам нужно знать для выполнения такой подготовки, не относится к WinRT, вместо этого ее можно найти в объекте MSApp: MSApp.getHtmlPrintDocumentSource (http://msdn.microsoft.com/library/windows/apps/Hh831251.aspx). Мне нравится, как она определена в документации: "Этот метод используется как мост между HTML и печатью в приложениях для Магазина Windows. Другими словами, это способ, которым разработчик сообщает: "дайте мне что-нибудь для печати". Вы передаете ей HTML-документ, который содержит ваши данные для печати.

Я выделил здесь слово документ, так как то, что вы передаете getHtmlPrintDocumentSource не может быть произвольным элементом DOM. Это должно быть то же самое, на что всегда указывает переменная document, иначе вы получите исключение времени выполнения: "no such interface supported" ("нет такого поддерживаемого интерфейса").

Итак, где же взять такой объект?

Если то, что ваше приложение показывает на экране – это в точности то, что вы хотите вывести на печать, вы можете просто использовать объект document напрямую. Именно это делают Сценарии 1-3 примера "Печать" (http://code.msdn.microsoft.com/windowsapps/Print-Sample-c544cce6):

MSApp.getHtmlPrintDocumentSource(document);

Конечно, вам не нужно печатать все, что отображается на экране. Вы можете видеть, что то, что отображается на экране, показанное на рис. 10.4, и то, что выводится при предварительном просмотре перед печатью, на рис. 12.2 и рис. 12.3, различается. Здесь вступают в дело медиа-запросы print CSS:

@media print {
/* Стили только для печати */
}

Проще говоря, если есть что-то, чего не должно быть в данных, которые будут отправлены на печать, установить стиль display: none в данном медиа-запросе. Альтернативная стратегия, которую использует рассматриваемый пример, заключается в создании отдельного CSS-файла, такого как css/print.css, и связывание его с вашим HTML-файлом с атрибутом media, установленным в print (смотрите html/scenario1.html):

<link rel="stylesheet" type="text/css" href="/css/print.css" media="print" />

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

Но что, если содержимое, которое вы хотите напечатать, это совсем не ваш объект document? Как создать еще один? Здесь есть несколько возможностей:

  • В обработчике события document.body.onbeforeprint добавьте дополнительный дочерний элемент к документу и используйте событие document.body.onafterprint для того, чтобы его удалить (структура подобных обработчиков показана в Сценарии 2 примера о печати). Если вы выполняете печать, CSS оставляет видимым лишь эти только что добавленные элементы, видимыми, и это все, что выводится на печать. Это позволяет весьма эффективно управлять всеми выводимыми данными, например, добавлять дополнительные верхние и нижние колонтитулы, которые не видны в приложении. Вы можете предоставить пользователю возможность настройки этих колонтитулов.
  • Вызовите document.createDocumentFragment для получения фрагмента документа и затем заполните его данными, которые хотите вывести на печать. getHtmlPrintDocumentSource принимает подобные фрагменты.
  • Если у вас имеется iframe, src которого установлено на документ SVG (один из советов, которые мы упоминали для SVG в Главе 4 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript"), получите данный SVG-документ напрямую, с помощью свойства contentDocument объекта iframe. То, что вы получите, так же может быть напрямую передано в getHtmlPrintDocumentSource и на печать будет выведен лишь SVG. Например:
     
    <!-- В HTML -->
    < iframe id="diagram" src="/images/diagram.svg"></iframe>
    
    //В JavaScript
    var frame = document.getElementById("diagram");
    args.setSource(MSApp.getHtmlPrintDocumentSource(frame.contentDocument));
  • Если вы хотите напечатать содержимое другой HTML-страницы, создайте в элементе head документа элемент link, который указывает на ту страницу, которую нужно напечатать (смотрите ниже). Благодаря этому getHtmlPrintDocumentSource будет перенаправлен для обработки содержимого указанной страницы.

Последнее показано в Сценарии 4 примера "Печать", где элемент link добавлен к документу с помощью следующего кода (js/scenario4.js):

var alternateLink = document.createElement("link");
alternateLink.setAttribute("id", "alternateContent");
alternateLink.setAttribute("rel", "alternate");
alternateLink.setAttribute("href", "http://go.microsoft.com/fwlink/?LinkId=240076");

alternateLink.setAttribute("media", "print");
document.getElementsByTagName("head")[0].appendChild(alternateLink);

Здесь атрибут rel показывает, что это альтернативное содержимое, атрибут media указывает на то, что он предназначен только для печати, и href указывает на альтарнетивное содержимое (id не обязательно). Обратите внимание на то, что если на целевой странице есть какие-либо медиа-запросы, предназначенные для печати, они будут применены при создании источника данных для печати.

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

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

Для начала нужно получить объект Windows.Graphics.Printing.PrintManager(http://msdn.microsoft.com/library/windows/apps/windows.graphics.printing.printmanager.aspx) как показано ниже:

      var printManager = Windows.Graphics.Printing.PrintManager.getForCurrentView();

И затем – прослушивать его событие printtaskrequested (http://msdn.microsoft.com/library/windows/apps/windows.graphics.printing.printmanager.printtaskrequested.aspx) (событие WinRT), либо с помощью addEventListener , либо назначив обработчик, как это сделано в примере:

      printManager.onprinttaskrequested = onPrintTaskRequested;

Если вы не добавили обработчик для этого события, пользователь увидит сообщение, как в правой части рис. 12.1 при активации чудо-кнопки Устройства, если только вы не зарегистрировали приложение для обработки других событий, связанных с устройствами, как, например, Windows.Media.PlayTo.PlayToManager.sourceRequested (http://msdn.microsoft.com/library/windows/apps/windows.media.playto.playtomanager.sourcerequested.aspx), как мы видели в Главе 4 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript".

Если вы хотите инициировать печать с помощью команды приложения, такой, как кнопка Print (Печать) в Сценарии 2 примера, вызовите метод PrintManager.showPrintUIAsync (http://msdn.microsoft.com/library/windows/apps/windows.graphics.printing.printmanager.showprintuiasync.aspx). Это равносильно нажатию на чудо-кнопку Устройства, когда приложение зарегистрировано для события printtaskrequested.

Событие printtaskrequested вызывается, когда активируется чудо-кнопка Устройства. В ответ, ваш обработчик создает объект PrintTask (http://msdn.microsoft.com/library/windows/apps/windows.graphics.printing.printtask.aspx) с функцией обратного вызова, которая предоставляет, когда будет нужно, содержимое документа. Вот как это работает. Сначала ваш обработчик получает объект PrintTaskRequest (http://msdn.microsoft.com/library/windows/apps/windows.graphics.printing.printtaskrequest.aspx), который имеет три члена:

  • deadline Дата и время, указывающие на то, сколько времени у вас есть на то, чтобы предоставить запрошенные данные.
  • getDeferral Возвращает объект PrintTaskRequestedDeferral ( http://msdn.microsoft.com/library/windows/apps/windows.graphics.printing.printtaskrequesteddeferral.aspx) в том случае, если вам нужно выполнить какие-либо асинхронные операции для предоставления запрошенных данных. Как и в случае со всеми отложенными операциями, вы вызываете его метод complete когда асинхронная операции завершится.
  • createPrintTask Создает объект PrintTask с заданным заголовком и функцией, которая предоставляет документ-источник данных по запросу.

Структура createPrintTask немного необычна. Когда он возвращает объект PrintTask, с помощью которого вы можете задать параметры и прослушивать события, имеющие отношение к задаче, как мы скоро увидим, его свойство source предназначено только для чтения. Таким образом, вместо того, чтобы создавать задачу и сохранять ваш документ с содержимым в этом свойстве, вы, вместо этого, предоставляете функцию обратного вызова, которая выполняет это, когда будет нужно. Сама по себе функция проста: она просто принимает объект PrintTaskSourceRequestedArgs (http://msdn.microsoft.com/library/windows/apps/windows.graphics.printing.printtasksourcerequestedargs.aspx), метод setSource которого вы вызываете с тем, что хотите вернуть в MSApp.getHtmlDocumentPrintSource.

Здесь обычно можно выполнить и другие действия по настройке задачи, поэтому давайте взглянем на код из Сценария 3 примера "Печать" (где я для краткости добавил переменную пространства имен):

function onPrintTaskRequested(printEvent) {
var printTask = printEvent.request.createPrintTask("Print Sample", function (args) {
args.setSource(MSApp.getHtmlPrintDocumentSource(document));

// Выбор параметров принтера для показа. Порядок, в котором добавлены параметры
// определяют порядок, в котором они будут отображены в пользовательском интерфейсе
var options = Windows.Graphics.Printing.StandardPrintTaskOptions; 
printTask.options.displayedOptions.clear(); printTask.options.displayedOptions.append(options.copies); 
printTask.options.displayedOptions.append(options.mediaSize); 
printTask.options.displayedOptions.append(options.orientation);
printTask.options.displayedOptions.append(options.duplex);

// Устанавливает значения по умолчанию для параметров принтера
printTask.options.mediaSize =
Windows.Graphics.Printing.PrintMediaSize.northAmericaLegal;

// Регистрирует обработчик для события завершения задачи печати

printTask.oncompleted = onPrintTaskCompleted;
});
}

Обратите внимание на то, что PrintTaskSourceRequestedArgs так же содержит уже знакомый вам метод getDeferral и свойство deadline.

Совет. Если вы пошагово исполняете код в обработчике printtaskrequested, но пропустите время, заданное в deadline, пользовательский интерфейс печати сообщит о том, что нет данных для печати. Это может не быть ошибкой приложения – уберите точки останова и снова запустите программу для того, чтобы это проверить.

Вы можете управлять тем, как выглядит пользовательский интерфейс печати с помощью PrintTask.options, посмотрите материал на эту тему "Руководство по приложениям Магазина Windows с поддержкой печати" (http://msdn.microsoft.com/library/windows/apps/hh868178.aspx). Объект options типа PrintTaskOptions (http://msdn.microsoft.com/library/windows/apps/windows.graphics.printing.printtaskoptions.aspx), несколько из вполне очевидных числовых параметров, это maxCopies, minCopies, и numberOfCopies. Так же вы можете вызвать getPageDescription с номером страницы для получения PrintPageDescription с информацией о физических размерах данной страницы

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

Свойство PrintTaskOptions Windows.Graphics.Printing Enumeration
binding PrintBinding
collation PrintCollation
colorMode PrintColorMode
duplex PrintDuplex
holePunch PrintHolePunch
mediaSize PrintMediaSize
mediaType PrintMediaType
orientation PrintOrientation
printQuality PrintQuality
staple PrintStaple

PrintTaskOptions.displayedOptions (http://msdn.microsoft.com/library/windows/apps/windows.graphics.printing.printtaskoptions.displayedoptions.aspx) в свою очередь, это вектор строк, которые должны браться из класса StandardPrintOptions (http://msdn.microsoft.com/library/windows/apps/windows.graphics.printing.standardprinttaskoptions.aspx) как показано в коде выше. Каждый из них управляет видимостью параметра в пользовательском интерфейсе печати, если, конечно, принтер поддерживает этот параметр (в противном случае параметр не будет показан). Вот полный список параметров: binding, collation, colorMode, copies, duplex, holePunch, inputBin, mediaSize, mediaType, nUp, orientation, printQuality, и staple.

Обратите особое внимание на свойство mediaSize , для которого доступно 172 различных значения в перечислении PrintMediaSize, которые отражают все размеры форматов бумаги, конвертов и так далее. Когда вы размещаете в Магазине Windows приложение, предназначенное для разных регионов, вам может понадобиться включить mediaSize в displayedOptions и установить его значение во что-то, применяющееся в регионе (как сделано в вышеприведенном коде для бумаги формата legal size). Несмотря на это, размеры носителей обычно доступны в панели More Settings (Дополнительные параметры) пользовательского интерфейса печати, в зависимости от того, что поддерживает выбранный принтер, так что пользователи будут иметь доступ к этим настройкам.

Последнее, что хочется упомянуть в связи с вышеприведенным кодом, это то, что у PrintTask есть событие completed, вместе с previewing, progressing, и submitting. Вы можете использовать их для того, чтобы показывать состояние задач печати в вашем приложении, если вы решите это делать. Больше сведений о самой задаче можно получить из ей свойств, которые обычно содержит заданный вам заголовок задачи печати и уникальный ID. Среди всего этого, однако, вы можете отметить бросающееся в глаза отсутствие метода в PrintTask, с помощью которого можно отменить задание. На самом деле, так и есть. Это потому, что модель печати HTML, которую в настоящее время использую приложения для Магазина Windows, написанные на JavaScript, работает по принципу "все или ничего": как только задание попало в подсистему печати, программными средствами его не остановить. Однако, пользователь может пройти в традиционную панель управления принтером и отменить задание там, или вернуться к старому доброму методу вытаскивания бумаги из принтера, но в настоящее время приложения не могут предоставить подобных функций самостоятельно.

Что мы только что узнали

  • Хотя приложения для Магазина Windows в Windows 8 не могут получать доступ к произвольному аппаратному обеспечению, они могут получать доступ к большому количеству устройств посредством API WinRT и Win32 наподобие Xinput и к тем, что подерживают Переносными устройствами Windows (Windows Portable Devices). В случае с API Win32, компоненты WinRT являются посредниками во взаимодействии с ними приложений, написанных на JavaScript.
  • API Windows.Devices.Enumeration позволяет приложению обнаружить, какое аппаратное обеспечение установлено на компьютере, Если приложение может осуществлять доступ к специальным типам устройств, таким, как Bluetooth-устройства, оно может использовать перечисление для предоставления списка, из которого пользователь может выбрать устройство для использования.
  • API Windows.Networking.Proximity поддерживает обзор одноранговых устройств (через WiFi Direct и Bluetooth), а так же сценарии касания для соединения или касания для обмена данными на компьютерах, оснащенных NFC-контроллерами.
  • Соединение бесконтактного взаимодействия может использовать сокеты для сеансов длительного обмена данными (наподобие многопользовательских игр), или по нему можно просто отправить сообщение с одного устройства на другое, воспользовавшись механизмом публикации и подписки, что обычно для сценариев касания для обмена данными, включая работу с RFID-метками.
  • Печать полностью преображена в Windows 8, эту возможность сравнительно просто реализовать в приложениях для Магазина Windows. Реализация включает в себя прослушивание события начала печати при вызове интерфейса чудо-кнопки Устройства и предоставление Windows HTML-содержимого.
  • Содержимое, подходящее для печати, может поступать из документа приложения, фрагмента документа, SVG-документа или из удаленного источника. Подобное содержимое может быть настроено с использованием медиа-запросов CSS для печати, Windows берет на себя задачи по обеспечению передачи данных для печати на целевой принтер.
< Лекция 11 || Лекция 12: 12 || Лекция 13 >