Руководство программиста в Photon (1037671), страница 56
Текст из файла (страница 56)
PpPrintContext_t *pc;
pc=PpCreatePC();
Модифицирование контекста печати
Сразу после того, как контекст создан, Вы должны выполнить его правильную установку в соответствии с Вашим принтером, и установить опции (ориентация, размер бумаги, прочая), которые Вы хотите использовать. Вы можете сделать это с помощью следующих функций:
-
PpLoadDefaultPrinter()
-
PpLoadPrinter()
-
PpSetPC()
-
PpPrintPropSelect()
-
PpPrintSelect()
-
PpPrintSelection()
Эти функции описаны в "Справочнике библиотечных функций Photon'а". Вы можете также использовать виджет PtPrintSel (см. "Справочник виджетов Photon'а").
Вы можете получить список доступных принтеров путём вызова функции PpLoadPrinterList(). Когда Вы завершите работу со списком, вызовите функцию PpFreePrinterList().
Запуск процесса печати
Если вы используете приложение, которому надо что-то знать о контексте печати, Вы можете использовать функцию PpGetPC(), с помощью которой можно получить соответствующую информацию. Например, Вам может понадобится узнать о выбранной ориентации (для того, чтобы правильно сориентировать Ваши виджеты). Если Вам понадобится узнать размеры полей, Вы можете вызвать функцию PpGetCanvas().
Перед началом печати Вы должны установить размер или разрешение источника. Например:
-
Если Вы хотите, чтобы виджет занял страницу, установите размер источника эквивалентным размерам виджета. Чтобы это сделать, можно вызвать функцию PpSetCanvas().
-
По умолчанию разрешение источника равно 100 пикселям/дюйм, так что шрифты печатаются в приближённом размере. Вы можете получить размер внутреннего холста, вызвав функцию PpGetCanvas(), которая даёт размеры c учётом размеров полей и непечатаемых зон.
При установке размера источника учитывайте непечатаемые зоны принтера. Все принтеры имеют поля по краям страницы, на которых они не в состоянии печатать, даже если поля страниц установлены в 0. Поэтому размер, установленный выше, в действительности несколько больше, чем размер страницы, и шрифт будет масштабирован в сторону уменьшения, так чтобы поместиться в доступной для печати части листа.
В следующем примере размер страницы и непечатаемые области получены из расчёта предоставления надлежащего размера источника и высоты текста. Попробуйте выполнить это и оцените результирующий вывод, чтобы удостовериться, что шрифт имеет высоту в 1 дюйм от асцендера (верхнего элемента литеры) к десцендеру (подстрочному элементу литеры):
#include <stdio.h>
#include <stdlib.h>
#include <Pt.h>
PtWidget_t *label, *window;
PpPrintContext_t *pc;
int quit_cb (PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo ) {
exit (EXIT_SUCCESS);
return (Pt_CONTINUE);
} // функции quit_cb()
int print_cb (PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo ) {
int action;
PhDim_t size;
PhRect_t const *rect;
PhDim_t const *dim;
action = PtPrintSelection(window, NULL, "Demo Print Selector", pc, Pt_PRINTSEL_DFLT_LOOK);
if (action != Pt_PRINTSEL_CANCEL) {
/* Получение непечатаемой зоны и размера страницы, всё - в 1/1000 дюйма */
PpGetPC(pc, Pp_PC_NONPRINT_MARGINS, &rect);
PpGetPC(pc, Pp_PC_PAPER_SIZE, &dim);
size.w = ((dim->w - (rect->ul.x + rect->lr.x)) * 72) / 1000;
size.h = ((dim->h - (rect->ul.y + rect->lr.y)) * 72) / 1000;
/* Установка размера источника */
PpSetPC( pc, Pp_PC_SOURCE_SIZE, &size, 0);
/* Начало печати надписи */
PpStartJob(pc);
PpContinueJob(pc);
/* Повреждение виджета */
PtDamageWidget(label);
PtFlush();
/* Закрытие печати */
PpSuspendJob(pc);
PpEndJob(pc);
}
return (Pt_CONTINUE);
} // функции print_cb()
int main(int argc, char *argv[]) {
PtArg_t args[10];
PtWidget_t *print, *quit;
PhDim_t win_dim = { 400, 200 };
PhPoint_t lbl_pos = {0, 0};
PhArea_t print_area = { {130, 170}, {60, 20} };
PhArea_t quit_area = { {210, 170}, {60, 20} };
PtCallback_t callbacks[2] = { {print_cb, NULL}, {quit_cb, NULL} };
if (PtInit(NULL) = = -1) PtExit(EXIT_FAILURE);
/* Создание главного окна */
PtSetArg (&args[0], Pt_ARG_DIM, &win_dim, 0);
PtSetArg (&args[1], Pt_ARG_WINDOW_TITLE, "Пример печати", 0);
if ((window = PtCreateWidget(PtWindow, Pt_NO_PARENT, 1, args)) = = NULL)
PtExit (EXIT_FAILURE);
/* Создание контекста печати */
pc = PpCreatePC();
/* Создание надписи для печати */
PtSetArg (&args[0], Pt_ARG_POS, &lbl_pos, 0);
PtSetArg (&args[1], Pt_ARG_TEXT_STRING, "Моя высота 1 дюйм", 0);
PtSetArg (&args[2], Pt_ARG_TEXT_FONT, "swiss72", 0);
PtSetArg (&args[3], Pt_ARG_MARGIN_HEIGHT, 0, 0);
PtSetArg (&args[4], Pt_ARG_MARGIN_WIDTH, 0, 0);
PtSetArg (&args[5], Pt_ARG_BEVEL_WIDTH, 0, 0);
label = PtCreateWidget (PtLabel, window, 6, args);
/* Создание кнопки печати */
PtSetArg(&args[0], Pt_ARG_AREA, &print_area, 0);
PtSetArg(&args[1], Pt_ARG_TEXT_STRING, "Печать", 0);
PtSetArg(&args[2], Pt_CB_ACTIVATE, &callbacks[0], 0);
print = PtCreateWidget (PtButton, window, 3, args);
/* Создание кнопки завершения */
PtSetArg(&args[0], Pt_ARG_AREA, &quit_area, 0);
PtSetArg(&args[1], Pt_ARG_TEXT_STRING, "Конец", 0);
PtSetArg(&args[2], Pt_CB_ACTIVATE, &callbacks[1], 0);
quit = PtCreateWidget (PtButton, window, 3, args);
PtRealizeWidget(window);
PtMainLoop();
return (EXIT_SUCCESS);
} // main()
Вы должны также установить смещение источника – верхний левый угол того, что печатается. Например, если у Вас есть кнопка, нарисованная на (20,20) от верхнего левого угла панели и Вы хотите, чтобы на странице она рисовалась на (0,0), установите в (20,20) смещение источника. Любые другие виджеты рисуются на своих позициях относительно этого начального значения виджетов. Виджет, расположенный на (40,40), будет прорисован на странице в позиции (20,20). Код для этого следующий:
PhPoint_t offset = {20, 20};
...
PpSetPC( pc, Pp_PC_SOURCE_OFFSET, &offset, 0 );
Сразу же после установки размеров источника и смещения, Вы можете запустить печать:
PpStartJob(pc);
PpContinueJob(pc);
Функция PpStartJob(pc) устанавливает контекст печати для процесса печати и функция PpContinueJob(pc) делает контекст печати активным, в результате чего все команды рисования Photon'а перенаправляются на адресата, заданного в контексте печати.
Печать требуемых виджетов
После того как Вы сделали контекст печати активным, Вы можете запустить печать виджетов и всё такое прочее. Это может быть сделано путём вызова любой комбинации следующих функций:
-
Функции Pg*
-
Функция PpPrintWidget() – Вы можете напечатать даже виджет, который не был нереализован (unrealise).
Если вы можете напечатать всё содержание скроллируемого виджета, Вам понадобится выполнить определённые подготовительные операции. См. раздел "Печать скроллирующихся виджетов" ниже.
Печать новой страницы
Вы можете в любой точке выполнить принудительный конец страницы, вызвав функцию PpPrintNewpage():
PpPrintNewPage(pc);
Заметьте, что как только Вы вызвали функцию PpStartJob(), какие-либо изменения контекста печати будут иметь эффект только после следующего вызова функции PpPrintNewPage().
Photon предполагает, что номера страниц увеличиваются по 1. Если это не так, вручную установите член Pp_PC_PAGE_NUM контекста печати для установки нужного номера страницы. Не делайте номер страницы уменьшающимся, так как в этом случае драйверы печати могут не работать должным образом.
Печать скроллирующихся виджетов
Если Вы хотите напечатать всё содержание скроллирующегося виджета, Вам надо выполнить некую особую обработку.
PtList
Единственным способом заставить PtList напечатать (или нарисовать) все пункты – это изменить его размеры так, чтобы высота была равна общей высоте всех пунктов. Простейшим решением этого является, вероятно, использование политики изменения размеров:
Это будет работать только в том случае, если общая высота меньше чем 65К пикселей.
-
Открыть и запустить контекст печати.
-
Получить для виджета PtList текущие значения флагов изменения размеров (Pt_ARG_RESIZE_FLAGS).
-
Установить флаги изменения размеров в значение Pt_RESIZE_XY_ALWAYS, в результате изменяя размер списка так, чтобы он вместил весь свой текст.
-
Вызвать функцию PpPrintWidget() для виджета или родительского виджета.
-
Переустановить флаги изменения размеров для виджета PtList.
-
Остановить и закрыть контекст печати.
PtMultiText
Из-за программного дефекта в флагах изменения размеров в многострочном виджете, метод, используемый для виджета PtList, работает неверно с виджетом PtMultiText.
Чтобы напечатать весь текст виджета PtMultiText:
-
Откройте и запустите контекст печати.
-
Получите текущие значения ресурсов Pt_ARG_MULTITEXT_NUM_LINES и Pt_ARG_MULTITEXT_NUM_LINES_VISIBLE виджета.
-
Сохраните значение ресурса Pt_ARG_MULTITEXT_NUM_LINES_VISIBLE в локальной переменной (помните, что PtGetResources() даёт Вам указатель во внутренней памяти виджета – не расчитывайте, что в нём можно хранить число видимых строк).
-
Установите Pt_ARG_MULTITEXT_ROWS в значение Pt_ARG_MULTITEXT_NUM_LINES.
-
Вызовите PpPrintWidget() для виджета или родительского виджета.
-
Переустановите значение Pt_ARG_MULTITEXT_ROWS, чтобы в нём хранилось число видимых строк.
-
Остановите и закройте контекст печати.
Вот ответная реакция, которая распечатывает виджет PtMultiText:
int prt_multi( PtWidget_t *widget, ApInfo_t *apinfo, PtCallbackInfo_t *cbinfo ) {
int action;
PhDim_t size = { 850, 1100 };
long *num_lines;
short *num_lines_visible;
long vis_lines;
PtArg_t args[2];
/* предотвращает предупреждения (варнинги) об отсутствии ссылок */
widget = widget, apinfo = apinfo, cbinfo = cbinfo;
/* Вы можете выполнить эти вызовы PpSetPC() просто после создания контекста печати
Его наличие позволяет Вам повторно использовать контекст печати */
/* Установка разрешения источника пропорционально размеру страницы */
PpSetPC( pc, Pp_PC_SOURCE_SIZE, &size, 0 );
action = PtPrintSelection(ABW_base, NULL, "Демонстрационный селектор печати", pc,
Pt_PRINTSEL_DFLT_LOOK);
if (action != Pt_PRINTSEL_CANCEL) {
/* Запуск печати панели окна. Заметьте, что мы используем
один и тот же контекст печати для всех печатных работ */
PpStartJob(pc);
PpContinueJob(pc);
/* Получение числа строк и количества видимых строк */
PtSetArg (&args[0], Pt_ARG_MULTITEXT_NUM_LINES, &num_lines, 0);
PtSetArg (&args[1], Pt_ARG_MULTITEXT_NUM_LINES_VISIBLE, &num_lines_visible, 0);
PtGetResources (ABW_multi, 2, args);
/* Сохранение числа видимых строк в локальной переменной;
помните, что num_lines_visible указывает на внутреннюю память виджета */
vis_lines = *num_lines_visible;
/* Установка числа строк равным числу строчек текста */
PtSetResource( ABW_multi, Pt_ARG_MULTITEXT_ROWS, *num_lines, 0);
/* Печать виджета */
PpPrintWidget(pc, ABW_multi, NULL, NULL, 0);
/* Закрытие контекста печати */
PpSuspendJob(pc);
PpEndJob(pc);
/* Переустановка числа строк в сохранённое значение количества видимых строчек */
PtSetResource (ABW_multi, Pt_ARG_MULTITEXT_ROWS, vis_lines, 0);
}
return( Pt_CONTINUE );
}
PtScrollArea
Для PtScrollArea Вам необходимо печатать его виртуальный холст, в котором размещены все виджеты, созданные внутри него или перемещаемые по зоне прокрутки:
-
Получите указатель на виртуальный холст, вызвав:
PtValidParent(ABW_Scroll_area, PtWidget);
-
Получите зону Pt_ARG_AREA) виртуального холста, и используйте его член member как размер источника в контексте печати;
-
Установите смещение контекста печати источника в:
PtWidgetOffset(PtValidParent(ABW_Scroll_area, PtWidget));
-
Напечатайте виртуальный холст области прокрутки, вызвав
PpPrintWidget(pc, PtValidParent(ABW_Scroll_area, PtWidget), NULL, NULL, 0);
Приостановка и возобновление работы печати
Чтобы приостановить работу печати и направить все события рисования обратно на графический драйвер в любой момент после вызова PpStartJob(), вызовите
PpSuspendJob(pc);
Чтобы возобновить работу печати, вновь активизировав контекст печати, так чтобы направить события прорисовки в направлении адресата, заданного в контексте печати, вызовите
PpContinueJob(pc);
Завершение работы печати
Когда Вы завершили печать Ваших виджетов, необходимо деактивировать и закрыть контекст печати. Это выполняется вызовами: