Отправлено: 14.03.13 18:00. Заголовок: PAGESCRIPT 32 FOR (X)HARBOUR
Пытаюсь прикрутить PageScript 32 к проге на Harbour и облом. К проге на Xharbour прикрутил нормально (работает) Есть в TPSCRIPT.PRG (поставляется вместе с библой)
Harbour естественно не находит Xbp.ch , Dll.ch , не пойму что делать.
=============================================== PAGESCRIPT 32 FOR (X)HARBOUR ===============================================
This file contains important supplementary and late-breaking information that may not appear in the main product documentation. We recommend that you read this file in its entirety.
In order to use PageScript 32 with (x)Harbour, you'll need to distribute PSCRIPT.DLL with your programs. We recommand that PSCRIPT.DLL be copied in the application's folder in order to avoid DLL versions conflicts.
Three files needs to be included in your (x)Harbour projects :
1 - DLLCALL.C 2 - TPSCRIPT.PRG 3 - PSCRIPT.CH
DLLCALL.C gives PageScript a way to call DLL functions in the same way as Xbase++ does. This interface is contributed by Paul Tucker, Ontario, Canada. Many thanks to him for this great contribution.
TPSCRIPT.PRG contains all the PageScript 32 functions and one class, named TPageScript. You may either choose to call PS functions or instantiate TPageScript and use its methods. When you use functions, calling PSInit() automaticaly instanciates a Static TPageScript object.
PSCRIPT.CH contains constants used by PageScript 32.
Отправлено: 18.03.15 18:52. Заголовок: Кто то работает Page..
Кто то работает с PageScript под Harbour , или только я один ? Есть вопросик. Функция PSBitmap нормально растягивает картинку по заданным координатам. Но понадобилось печать выводить в PDF формате. В PageScript есть такая возможность через PSSetDevice(3) , все выводится красиво но вот с PSBitmap проблема и изображение не растягивается как следует по горизонтали. То есть грубо говоря если я хочу вписать картинку в прямоугольник шириной 100 мм , то картинка (при PSSetDevice(3)) впишется только в ширину 90 мм. По высоте все чётко. Если выводить на просмотр средствами PageScript или сразу на печать , такой проблемы нет.
Отправлено: 15.08.17 10:41. Заголовок: Dima пишет: Кто то ..
Dima пишет:
цитата:
Кто то работает с PageScript под Harbour
В продолжение темы - PageScript теперь живет по адресу http://pagescript32.com/ и поддержка PDF в его движке существенно переработана и исправлена. Новые владельцы этого продукта обещают уже скоро анонсировать новую версию этой DLL. Кстати, будет обеспечена поддержка 64-битной версии также.
Если это будет интересно, то смогу включить их базовый тестовый пример в новую сборку Минигуи. Ваши комментарии приветствуются
Отправлено: 15.08.17 12:46. Заголовок: Dima пишет: где то ..
Dima пишет:
цитата:
где то есть страница с загрузкой самого PS32
Они обещают первую бету раздавать бесплатно, когда она будет готова (адрес выложат на сайте выше). А последующие версии будут платные Я сейчас тестирую такую предварительную версию, и впечатления - приятные, но размер подключаемой DLL увеличился примерно на 1 МБайт за счет полной переработки поддержки PDF формата.
PAGESCRIPT 32 FOR (X)HARBOUR =============================================== Скрытый текст
This file contains important supplementary and late-breaking information that may not appear in the main product documentation. We recommend that you read this file in its entirety.
In order to use PageScript 32 with (x)Harbour, you'll need to distribute PSCRIPT.DLL with your programs. We recommand that PSCRIPT.DLL be copied in the application's folder in order to avoid DLL versions conflicts.
Three files needs to be included in your (x)Harbour projects :
1 - DLLCALL.C 2 - TPSCRIPT.PRG 3 - PSCRIPT.CH
DLLCALL.C gives PageScript a way to call DLL functions in the same way as Xbase++ does. This interface is contributed by Paul Tucker, Ontario, Canada. Many thanks to him for this great contribution.
TPSCRIPT.PRG contains all the PageScript 32 functions and one class, named TPageScript. You may either choose to call PS functions or instantiate TPageScript and use its methods. When you use functions, calling PSInit() automaticaly instanciates a Static TPageScript object.
PSCRIPT.CH contains constants used by PageScript 32.
Правда мне пришлось подправить сырец , вот так Скрытый текст
METHOD TPageScript:Init()
::bWaterMark := NIL // Codeblock for Watermark function ::nWaterMark := AWM_NONE // Indicates if the WaterMark is to be printed foreground or background ::lFromDialog := .f. // Indicates if printer selected from printer dialog ::lClipper := .f. // Indicates if calls to TextOut and TextBox should be compatible with PageScript for Clipper ::nUnit := APS_MILL // Default unit is MILLIMETERS ::aPrinters := {} // List of available printers ::nError := PSE_NOERROR // Indicates an error condition, such as no printer available ::aDocInfo := {0, "", "", APS_PORTRAIT, 1, APS_COURIER} // Print job info array
::hDll := DllLoad("PScript.dll") // Handle of the .DLL
// No error, set the coordinate system to TOP/LEFT (Default) if ::nError == PSE_NOERROR DllCall(::hDll, DLL_STDCALL, "PSSetCoorSystem", APS_TOPLEFT) endif endif
1) Взял бету с pagescript32.com, погонял тестовый пример - обратил внимание, что после закрытия Print Preview теряется фокус основного окна программы. Приходится возвращаться щелчком мыши или ALT+TAB. Это только у меня? Windows 7 x64. Можно вылечить?
2) Окно Print Preview можно как-то вызывать БЕЗ диалога выбора принтера? Долго искал, как посмотреть результат, не тратя бумагу, сохранял/переоткрывал pdf, пока не понял, что окно выбора принтера выскакивает, но вместо печати за ним идет просмотр...
3) На форуме _https://groups.google.com/forum/#!topic/harbour-users/gnUs9XMBygg некто Richard Visscher утверждает, что PageScript32 будет бесплатным для зарегистрированных пользователей. Что-то изменилось в ценовой политике с августа? Если нет - какие ждать цены, есть информация по предыдущим версиям ?
Отправлено: 30.12.17 23:08. Заголовок: Sergy пишет: после ..
Sergy пишет:
цитата:
после закрытия Print Preview теряется фокус основного окна программы
По-видимому, это проблемы взаимодействия с консолью. Для GUI-приложений такой проблемы нет.
Sergy пишет:
цитата:
вызывать БЕЗ диалога выбора принтера?
Нет, вызов этого диалога намертво зашит в pagescript DLL
Sergy пишет:
цитата:
Richard Visscher утверждает
Это новый собственник и разработчик PageScript32 Как он и обещал, он раздает первую публичную бетку DLL версии 3.4.0.105 бесплатно (как рождественский подарок ) Последующие версии, вероятнее всего, будут платными
Отправлено: 03.01.18 17:27. Заголовок: С некоторыми вопроса..
С некоторыми вопросами немного разобрался:
+ Если использовать gtwvg - с фокусом окна Preview все ок. Гуд
+ Посмотрел внимательнее - Preview вызывается без диалога принтера. Ничего там не "зашито".
? Сколько все-таки стоил PageScript в "свое время" и как лицензировался: по разработчику или по рабочим местам ?
Возник следующий:
Как-то уже "привык", что сначала я формирую какой-то отчет, а потом предлагаю юзеру - куда его вывести: на экран/принтер/в файл. Без разницы, что это: простой текст, XLS, PDF, DOC. PageScript заставляет указать устройство вывода заранее - ДО СОЗДАНИЯ самого тела документа. Логически я это понимаю: у разных устройств может быть разное разрешение, разные рабочие шрифты, соотв. документ МОЖЕТ выглядеть по-иному. Кто как решал данный вопрос?
Пока что приходит в голову: вместо "прямых" вызовов PSSetFontSize(), PSLine(), PSFrame() и тп... накапливать их некий массив блоков кода, например так:
вместо PSSetFontSize(5) => AADD(aQueue, {||PSSetFontSize(5)}) вместо PSLine(x1,y1,x2,y2) => AADD(aQueue, {||PSLine(x1,y1,x2,y2)}) и тп... после чего = запросить юзера, чего он хочет и "циклом по массиву" выполнить все вызовы.
Но в этой идее не будут "работать" переменные - нужно заменить их конкретным значением в момент помещения в очередь... Коряво как-то... И непонятно, как тогда обрабатывать необходимые значения некоторых функций - например, ширину текста в пикселях...
Что-бы придумать в такой ситуации? Хочется сохранить привычную логику работы программы, вне зависимости от типа документа.
PageScript заставляет указать устройство вывода заранее - ДО СОЗДАНИЯ самого тела документа
Это можно обойти (если я верно понял вопрос) , так как устройство задается в PSBeginDoc , первым параметром. Поэтому можно до формирования тела документа , запросить доступные принтера + туда же в менюху сунуть и устройство (предпросмотра). На вскидку так , выкинь лишнее :) Скрытый текст
#include "pscript.ch" Func Aprints(nm) local aprinters local bppm:=0 local i hb_default(@nm,"Выберите принтер")
if Psinit()==0 aprinters:=APSGetPrinter()
for i=1 to len(aprinters) aprinters[ i ]:=" "+aprinters[ i ]+" " next
if len(aprinters)>1 bppm:=boxmenu(aprinters,; 10,20,11,21,nm,; Psgetdefprinter(),3,"bg+/b,n/gr*,,,w/b*") elseif len(aprinters)==1 bppm:=1 else soob("Не найдено ни одного принтера.....","r/r","gr+/r") endif else soob("PageScript не загружен...........","r/r","gr+/r") endif return bppm ************ Func APSGetPrinter() local ret:={} local nn:=PSGetPrinterCount() local i for i=1 to nn aadd(ret,PSGetPrinterNames(i)) next
Отправлено: 03.01.18 21:55. Заголовок: Dima пишет: Это мож..
Dima пишет:
цитата:
Это можно обойти (если я верно понял вопрос) , так как устройство задается в PSBeginDoc , первым параметром.
Я не очень понятно объяснил, сорри...
До знакомства с PageScript у меня было так: Сначала создается сам документ в виде файла (txt, xls, doc, pdf), а затем вызывается диалог с юзером, где предлагается: "куда его выводить: экран/принтер/файл". Стандартно и единообразно. Обработчик вывода на экран, скажем для txt и xls, разумеется, разные. Вот и сижу чешу репу, как быть: вместе с каждым документом, которые планирую готовить через PageScript придется переделывать логику диалога с юзером: сначала "куда выводить", потом формирование тела и собственно, вывод. А если юзер захочет сначала "на экран", а потом "на принтер" - тогда тело документа будет пересоздаваться дважды.
А по ходу создания некоторых отчетов открываются/закрываются таблицы, устанавливаются фильтры/relation и куча прочей мути...
Сначала создается сам документ в виде файла (txt, xls, doc, pdf)
У меня иначе , для отчетов (к примеру) , вызывается диалог в котором задаются условия формирования и там же указывается формат отчета (txt, xls, doc, pdf) Надо будет мне доку полистать нового PS32 , может что то есть в этом плане , что тебе нужно.
Отправлено: 03.01.18 22:44. Заголовок: Кстати заметил, что ..
Кстати заметил, что при любой ошибке в программе во время подготовки документа, дело завершается не только стандартным RTE, но и полным крэшем с созданием "hb_out.log", а Windows "пытается найти способ решения проблемы и предлагает обратиться к разработчику"...
Почему половинчатое? Потому что недокументировано. Фиг с ним, с частично заполненным листом бумаги, вылезающим из принтера после RTE. Странно другое - PSAbort() в данном случае не помогает, программа точно так-же крэшится, как и без EXIT PROCEDURE.
Получил BASE 1086 , неверный аргумент ++ И далее как ты описал
Значит дело не в "новизне" версии.
цитата:
А не бывает такого у меня так как код отлажен.
Круто. У кого нет ошибок в коде - пусть кинет в меня камень ?
Развивать дальше ты его не собираешься? Уверен на 200% в отсутствии своих ошибок в дальнейшем? Даже если нет ошибок в твоем коде - их нельзя исключать в окружении: драйвер/память/сеть - неужели не глючат никогда ? А под столом кто-нить пнет ногой системник и из него вывалится на соплях державшийся кабель?
Не то, чтобы я жути нагоняю, но RTE - это предсказуемый и контролируемый ядром Harbour процесс корректного (по возможности) завершения всех запущенных процессов, закрытия таблиц, устройств и тд и тп... Крэш, аналогичный вызываемому - это пздц с точки зрения сохранности данных и стабильности работы с системой. Возникает в узле внешнего устройства (принтера в данном случае). К чему приведет - никто не знает. Уверен, что нужно всеми средствами избегать подобной ситуации.
Не смог найти форума поддержки PageScript32. Такой есть в природе?
Отправлено: 04.01.18 17:12. Заголовок: Sergy пишет: Не смо..
Sergy пишет:
цитата:
Не смог найти форума поддержки PageScript32
Можно пробнуть сюда написать support@pagescript32.com
Sergy пишет:
цитата:
Крэш, аналогичный вызываемому - это пздц с точки зрения сохранности данных и стабильности работы с системой
Ты в этом уверен ? Мне кажется что после RTE Harbour , сама прога нормально завершается (ну типа с закрытием баз и тд и тп) а далее начинает завершаться сама DLL со своими ошибками , она ж вроде на делфи. Как вариант можно обернуть у себя весь код PS32 начиная с PSINIT в Begin Seguence
PS Что то мне кажется что FastReport поведет себя так же в случае RTE в консольной Harbour проге.
Отправлено: 04.01.18 18:26. Заголовок: Dima пишет: Что то ..
Dima пишет:
цитата:
Что то мне кажется что FastReport поведет себя так же в случае RTE в консольной Harbour проге.
Часто при отладке в МиниГуи форма FastReport ведёт себя непредсказуемо (я писал об этом здесь), приходиться снимать задачу через менеджер задач. Базы после этого ни разу не портились. На терминалке, при отладке формы тоже при ошибках вываливалась прога. Поставил простой обработчик ошибок для вывода функций для FastReport
BEGIN SEQUENCE WITH { |e|break( e ) } RECOVER USING oError END SEQUENCE
и всё... проблемы исчезли...
Если форму FastReport отладил - то работает как часы, пока никто не жаловался. Единственно FastReport критичен для принтеров Херокс на ХР, у меня такое было на одном пользователе. Там что то с печатью хитро получилось, со всех программ печатает, а с FastReport нет.
Отправлено: 05.01.18 21:50. Заголовок: Dima пишет: Ты в эт..
Dima пишет:
цитата:
Ты в этом уверен ? Мне кажется что после RTE Harbour , сама прога нормально завершается (ну типа с закрытием баз и тд и тп) а далее начинает завершаться сама DLL со своими ошибками , она ж вроде на делфи.
Могу быть уверен только в том коде, который сам написал. Или имеющий исходники. А когда есть "черный ящик" в виде DLL - можно предполагать всё, что угодно.
Сегодня вот вообще с вероятностью 1к5 стал ловить GPF на ровном месте:
/*----------------------------------------------------------------------------- Method .....: #GetPrinterCaps() -> aCaps Description : Retreive the printer capabilities of the selected printer -----------------------------------------------------------------------------*/ METHOD TPageScript:GetPrinterCaps()
Local cDllTemplate Local nAreaWidth Local nAreaHeight Local nTopMargin Local nLeftMargin Local nPaperWidth Local nPaperHeight // Local nMAreaWidth // Local nMAreaHeight Local nHPixelsInch Local nVPixelsInch Local nBitDepth
nAreaWidth := DllExecuteCall(cDllTemplate, HORZRES) // Printable Horz area (Width) Pixels nAreaHeight := DllExecuteCall(cDllTemplate, VERTRES) // Printable Vert area (Height) Pixels nTopMargin := DllExecuteCall(cDllTemplate, PHYSICALOFFSETY) // Top margin Pixels nLeftMargin := DllExecuteCall(cDllTemplate, PHYSICALOFFSETX) // Left margin Pixels nPaperWidth := DllExecuteCall(cDllTemplate, PHYSICALWIDTH) // Total paper width Pixels nPaperHeight := DllExecuteCall(cDllTemplate, PHYSICALHEIGHT) // Total paper height Pixels // nMAreaWidth := DllExecuteCall(cDllTemplate, HORZSIZE) // Printable Horz area mm // nMAreaHeight := DllExecuteCall(cDllTemplate, VERTSIZE) // Printable Vert area mm nHPixelsInch := DllExecuteCall(cDllTemplate, LOGPIXELSX) // Number of Horz pixels/Inch Pixels nVPixelsInch := DllExecuteCall(cDllTemplate, LOGPIXELSY) // Number of Vert pixels/Inch Pixels nBitDepth := DllExecuteCall(cDllTemplate, NUMCOLORS) // Bit depth (number of bits per pixel)
Modules: ... Called from DLLCALL(0) Called from TPAGESCRIPT:ENDDOC(470) Called from PSENDDOC(2475) Called from (b)PS32(38) Called from PS32:FINISH(0) Called from MAIN(148)
Хотя еще вчера все работало норм. PSGetPrinterCaps() заменил вот на такой огород:
А вот что случилось с PDF - вообще не могу понять... Единственное, что из серьезного изменилось - утром винда захотела обновиться и попросила установить 100500 мегабайт ежемесячных обновлений. Я не возражал - слышал, там закрывают какой-то серьезный косяк с защитой на уровне ядра процессоров Intel, выпущенных а последние 10 лет...
Отправлено: 07.01.18 00:17. Заголовок: Честно говоря, даже ..
Честно говоря, даже не понял, как это "всё" заработало у меня. Скачал файл из pagescript32.com, потыкал по hbp, prg по очереди... что-то скомпилировалось как библиотека и "куда-то" упали *.a и *.о файлы...
Скомпилировался ли dllcall.c - я не в курсе. Нигде ж ничего про это не написано...
Пока адаптировал свою библиотеку печати под вызовы pscript.dll, на след неделе в боевом режиме с админом потестируем, что это за зверь... Если что - отключить его и вернуться на hpdf - дело трех секунд: если программа не "видит" dll - будет использовать harupdf.
In order to use PageScript 32 with (x)Harbour, you'll need to distribute PSCRIPT.DLL with your programs. We recommand that PSCRIPT.DLL be copied in the application's folder in order to avoid DLL versions conflicts.
Three files needs to be included in your (x)Harbour projects :
1 - DLLCALL.C 2 - TPSCRIPT.PRG 3 - PSCRIPT.CH
DLLCALL.C gives PageScript a way to call DLL functions in the same way as Xbase++ does. This interface is contributed by Paul Tucker, Ontario, Canada. Many thanks to him for this great contribution.
TPSCRIPT.PRG contains all the PageScript 32 functions and one class, named TPageScript. You may either choose to call PS functions or instantiate TPageScript and use its methods. When you use functions, calling PSInit() automaticaly instanciates a Static TPageScript object.
PSCRIPT.CH contains constants used by PageScript 32.
Отправлено: 07.01.18 12:08. Заголовок: Это конечно хорошо, ..
Это конечно хорошо, но как его компилировать-то ? Куда девать или где искать соотв. dllcall.а, dllcall.o ??? У себя я их не нашел... Ни в одном из *.hbp/hbc в текущей поставке о нем нет упоминаний... Ты уверен, что этот файл нужен для актуальной версии Harbour ?
Хочу избавиться от наличия ps32.hbc, содержащего такие строки:
Отправлено: 09.01.18 02:05. Заголовок: Спасибо за наводку, ..
Спасибо за наводку, попробовал прямую линковку tpscript.prg - получилось. Поковыряю ещё немного, добью, я думаю... Хочу типа "addon" оформить, чтобы чужого кода у меня в папке с сырцами приложения вообще не было. И чтобы в случае выхода новой версии pscript не вычищать из дебрей ничего, а просто накатить в hb\addon\ps32 свежие файлы и вуаля. Как, например, это сделано в LetoDB(f).
Нескромный вопрос: а зачем сейчас использовать PageScript ? Я понимаю, лет 15 назад еще в клиппере это был способ windows печати. А сейчас в hbwin есть соответствующие средства печати, да и любая gui-библиотека имеет такие возможности. Зачем сейчас печатать через стороннее приложение ?
Нескромный вопрос: а зачем сейчас использовать PageScript ?
1. Привычка :) 2. Меньше кода 3. Вывод в PDF , EMF 4. Предпросмотр печати (под WVT самое то) 5. На вскидку есть ряд функций которых нет в Hbwin и нужно писать и тестить свое под Hbwin 6. Достаточно много форм и отчетов реализовано (у меня) под PS32 , переделывать под Hbwin не хочется так как и так нормально работает. 7. Не плохо документировано.
Нескромный вопрос: а зачем сейчас использовать PageScript ?
Практически до 2016 года для печати бухгалтерских документов хватало имеющихся внутренних средств печати наподобие txt2gdi, txt2win и им подобных, которые одним шрифтом/размером фигачат целиком документ, разворачивая по необходимости страницу из портрета в ландшафт. Для разнообразных отчетов - все красивости Excel. Для ценников (повторяющаяся информация по заранее заданным шаблонам) - давно написана безотказно работающая утилита.
Когда настал вопрос с печатью доверенностей (где половина текста идет под 90 градусов), стало понятно, что в этом разнообразии пора что-то менять.
Сделал свой класс с набором примитивов: начать документ, задать толщину, нарисовать прямоугольник, выбрать шрифт, размер вывести в такую-то координату xy, завершить документ и тп.
Из-за того, что PageScript был заброшен создателями, начал вывод через HPDF, всё заработало супер-гуд, кроме собственно печати документов. Sumatra-PDF прекрасно выводит его на экран, но печатает с дикими тормозами - пересылая на принтер как bitmap-картинку. Adobe Reader - имеет задокументированную опцию командной строки /t - распечатать и завершить работу. Печатает без проблем, но несколько лет назад разработчики решили, что этого мало и программа должна предложить юзеру что-нибудь ещё: аннотировать документ, послать его... в облако. Наваял процедуру, которая запускает процесс, ждет некоторое время, одновременно пытаясь удалить pdf файл - и... грохает порожденный процесс. Работает быстро, но... как-то коряво...
После того, как в декабре проект PageScript "ожил" - за пару дней подключил его к своему классу. С точки зрения программы - вообще ничего не поменялось. Те-же самые примитивы, те-же самые координаты, те-же самые документы выводятся, только теперь иным способом. Все работает быстро и удобно, только бесплатный "черный ящик" в виде dll напрягает. Если будет поддерживаться и не будет глючить - оставлю его.
Если нет - можно поковыряться и с печатью через wingdi, но там отдельно нужно будет думать, как делать preview на экране.
Было-бы идеальное решение - все-бы давно сидели на нем...
Отправлено: 09.01.18 17:29. Заголовок: Dima пишет: чем pdf..
Dima пишет:
цитата:
чем pdfFactory Pro не устраивает ?
Пока искал варианты печати, много что перепробовал, все без особого успеха: STDU Viewer, 3nity PDF viewer, Nitro PDF, PDFLite, PDF X-change и много много других...
Возможно и PDFfactory был в том списке. Посмотрел на него только что - 100$ за рабочее место только чтобы печатать?
Отправлено: 21.01.18 17:39. Заголовок: Дабы не плодить кучу..
Дабы не плодить кучу тем, продолжу тут.
PageScript обязывает указать одно/или двустороннюю печать в самом начале документа: PSBeginDoc(nPrinter, cTitle, nOrientation, nCopies, nPageSize, nDuplex, nPaperBin) -> nError
Сначала никакой параметр туда не передавал, соотв. по умолчанию была односторонняя печать: DMDUP_SIMPLEX. При печати документа с более чем одной странице - из принтера с двусторонней печатью выходили несколько листов, распечатанных с одной стороны. При настройке SetDevice(DEV_PREVIEW) опция "выбрать двустороннюю печать" становилась серой, соотв. там включить ее вручную - тоже нельзя.
Думаю, делов-то - включил всем принудительно DMDUP_VERTICAL или DMDUP_HORIZONTAL (в зависимости от Portrait/Landscape документа) и думать забыл про это.
Через пару недель эксплуатации возникли вопросы иного рода: 1) каждая "односторонняя" бумажка сначала вылезает из принтера, потом снова в него засасывается и печатается с другой стороны. А это доооолго. 2) при печати мелких документов (например, складская накладная на выдачу 1-2 артикулов) обычно использовались "половинки" листов А4, скармливаемых через переднюю щель принтера. Теперь это нельзя делать, тк при двусторонней печати некоторые принтеры спотыкаются (из-за того, что лист короткий), а некоторые вообще отказываются брать любую бумагу через переднюю щель.
В PSSetDevice(DEV_PREVIEW) опция "двусторонняя или односторонняя печать" по-прежнему серая. PSSetDuplex() тоже не поможет: to set the desired Duplex mode for printers that support Duplex printing. Call this procedure before starting a new document.
Как-бы грамотно подступить к этому вопросу? Ведь до создания документа еще не ясно, сколько страниц на нем будет.
"Заставить юзера при печати каждого документа указать, что ему нужно" - вариант какой-то... корявый...
Отправлено: 22.09.18 21:12. Заголовок: Sergy Я так понял т..
Sergy Я так понял ты плотно подсел на новый Pagescript. Пока сижу на старом от abbylabs. Скажи плиз , новый PS32 стабилен и работает без глюков ? Я о версии 3.0.4.119
Отправлено: 24.09.18 15:57. Заголовок: Да, работаю на верси..
Да, работаю на версии 4.119 Работает стабильно, но по необъяснимым причинам иногда на одном-двух рабочих местах возникает GPF с кодом ошибки 6005 - DLL модуль вываливается при вызове BeginDoc(). Как понимаю, какая-то беда с драйвером принтера на конкретной машине. Была, к примеру, такая фигня на вроде-бы "спокойной" машине после замены на ней принтера (вместе с драйверами, разумеется).
Переписывался с автором - он не может ничем помочь, тк хочет самодостаточный пример...
Пока заставил админа пройти по всем проблемным машинам и обновить драйвера. С прежних 1-2 ошибок в неделю число GPF уменьшилось до 1-2 в месяц. Не по фэн-шую, конечно, но пока других вариантов нет.
Отправлено: 24.09.18 19:52. Заголовок: Dima пишет: У меня ..
Dima пишет:
цитата:
У меня тоже бывает , одна из причин не хватка свободного места на системном диске + принтер HP , после чистки ошибка сразу уходит.
Нужно будет у меня посмотреть, что с этим параметром...
Еще заметил, что фигня происходит на RDP, когда юзеры подключаются со "своими" принтерами. Сказал админу, чтобы всем RDP-юзерам настроил по умолчанию MS XPS Writer. Кол-во GPF значительно уменьшилось.
Отправлено: 25.09.18 15:04. Заголовок: Sergy А как ты регу..
Sergy А как ты регулируешь поля при печати ? В основном у меня печать на всех принтерах идет нормально а вот на Hp1020 , съедает то левую сторону документа то правую
Отправлено: 25.09.18 16:27. Заголовок: Dima пишет: А как т..
Dima пишет:
цитата:
А как ты регулируешь поля при печати ?
Пока работал с HPDF - проблем не было вообще: задал размер документа 297*210 и не паришься ни о чем. 95% PDF-viewer'ов по умолчанию масштабируют итоговое изображение на конкретный принтер.
А вот вместе с PageScript32 я "пооооонял", что физический размер бумаги и область печати - это вообще совершенно разные значения. Сначала, как вариант, думал прочитать размер области печати из свойств принтера и внутри "своего" класса включить автомасштаб... Потом решил, что проще сразу ограничить ширину документа по узкой стороне на 199мм. Этого хватило на весь наш зоопарк. Заодно вопрос с оставшимися 5% PDF-viewer'ов закрылся сам собой.
Отправлено: 04.10.18 17:11. Заголовок: Sergy Вопрос такой ..
Sergy Вопрос такой по PS32... Номер принтера я сразу указываю в PSBeginDoc() У себя проверял дома (все принтера локальные) , при смене принтера в программе печать идет именно на него. А вот на оффисе не понятки , там есть сетевые принтера и после выбора одного из них , печать почему то уходит на Microsoft XPS Document Writer (как правило) . В новом PS32 есть такая проблема ?
Отправлено: 06.10.18 16:00. Заголовок: Dima, с того момента..
Dima, с того момента, как я узнал про win_PrinterList() - я перестал обращаться к принтерам по номерам. Совсем. Ибо давным-давно наступил на те самые грабли, о которых ты пишешь. Про PageScript я тогда даже и не слышал. Задаю принтер только по его имени. В одном из офисов, например, их целый зоопарк: один настольный (расшаренный), два сетевых. 5 компов. Проблем с переключением вообще никаких. Все печатают откуда угодно на какой угодно принтер.
Отправлено: 06.10.18 19:41. Заголовок: В настройках каждой ..
В настройках каждой рабочей копии программы сохраняю именно имя принтера, а не цифру.
1) При запуске печати по заданному имени проверяю - присутствует ли он в win_PrinterList() и является ли принтером по умолчанию - win_PrinterGetDefault(). 2) Если нет - переставляю перед началом печати документа через win_PrinterSetDefault(). 3) В PSBeginDoc() первым параметром всегда передаю NIL (печатать на дефолтный). 4) После печати - возвращаю дефолтный принтер "назад" (если было его изменение).
Отправлено: 10.10.18 21:22. Заголовок: Sergy А в проге у т..
Sergy А в проге у тебя какая кодировка , 866 ? Ведь все эти функции WIN_Printer* результат возвращают в кодировке 1251 , и если не сделать перекодировку то принтера имеющие в названиях кирилицу , вместо кирилицы покажут вопросики. С win_PrinterList() и win_PrinterGetDefault() я так и поступил. Примерно так
Func My_WIN_PRINTERLIST() local alist:={} local i hb_cdpSelect( "RU1251" ) alist:=WIN_PRINTERLIST() if len(alist)#0 for i=1 to len(alist) alist[ i ]:=hb_ansitooem(alist[ i ]) next endif hb_cdpSelect( "RU866" ) return alist
Вопрос такой , в win_PrinterSetDefault() тоже имя передавать в RU1251 c временной сменой кодировки ? Я конечно поиграюсь и выясню , просто если готовый ответ я сэкономлю некоторое время а его не так много при средней продолжительности жизни
Sergy Кстати твой фокус не сработал под Win7 + PS32 от AbbeLabs , упорно печатает на принтер по умолчанию который был при запуске программы , под XP возможно и сработает , проверить не где. Sergy пишет:
цитата:
3) В PSBeginDoc() первым параметром всегда передаю NIL (печатать на дефолтный).
Так и делал в тестах. Еще и проверил меняется ли принтер по умолчанию (если его менять с win_PrinterSetDefault) - да меняется , но печатает на тот что я описал выше.
Отправлено: 01.05.20 09:53. Заголовок: Что то глючит PSINIT..
Что то глючит PSINIT на Вин10
Called from DLLCALL(0) Called from TPAGESCRIPT:INIT(266) in TPSCRIPT.PRG
При чем первый раз может упасть а потом все работает ровно. Куда копать ? PS На винде ниже 10 все работает ровно
METHOD TPageScript:Init()
::bWaterMark := NIL // Codeblock for Watermark function ::nWaterMark := AWM_NONE // Indicates if the WaterMark is to be printed foreground or background ::lFromDialog := .f. // Indicates if printer selected from printer dialog ::lClipper := .f. // Indicates if calls to TextOut and TextBox should be compatible with PageScript for Clipper ::nUnit := APS_MILL // Default unit is MILLIMETERS ::aPrinters := {} // List of available printers ::nError := PSE_NOERROR // Indicates an error condition, such as no printer available ::aDocInfo := {0, "", "", APS_PORTRAIT, 1, APS_COURIER} // Print job info array
::hDll := DllLoad("PScript.dll") // Handle of the .DLL
if ::hDll == nil//0
::nError := PSE_DLLNOTLOADED // DLL not loaded error else ::nError := DllCall(::hDll, DLL_STDCALL, "PSInit") вот тут падает
// No error, set the coordinate system to TOP/LEFT (Default) if ::nError == PSE_NOERROR DllCall(::hDll, DLL_STDCALL, "PSSetCoorSystem", APS_TOPLEFT) endif endif
::nError := DllCall(::hDll, DLL_STDCALL, "PSInit") вот тут падает
Я с PS не работал, но имел похожую ошибку при работе с DllCall, когда в функцию передаются еще какие либо параметры и их размер менее требуемого в вызываемой функции. Глянь доку, может функция принимает какие либо параметры... передай пустые значения для строковых space(50) например
PageScript32 падает у меня с вероятностью 1:100 - под Win7 и Win10. Причем не RTE, а качественный крэш с hb_out.log. Либо в PSIniit, либо рядом - PSSetOrientation.
Если на одной машине два раза за одну неделю такая петрушка - прошу админа переустановить дрова принтера. Помогает. Писал разработчику - он говорит, что такого ни у кого не бывает. А если и будет, по дампу памяти и hb_out.log он помочь не в состоянии - нужна воспроизводимость ошибки. :(
Отправлено: 04.01.22 20:27. Заголовок: 31-12-2021 - Next u..
31-12-2021 - Next update will get the following new functions:
- PDF signing for new and existing PDF files - PDF printing from code and new preview window - New preview window which can be used seperate or used non-modal from PS
Check this page next month for the beta version, happy new year !
Отправлено: 19.04.23 18:41. Заголовок: Новое обновление
Dima пишет:
цитата:
Check this page next month for the beta version
14.04.2023 - Version 4 update :
- PDF signing for new and existing PDF files - PDF printing from code and new preview window - New preview window which can be used seperate or used non-modal from PS - Includes version 3(3.0.4.178) and version 4 ( 4.0.1.157) 32 and 64 bit DLL
Pagescript standalone PDF Viewer 1.2 ------------------------------------- Parameters : 1 -> PDF filename ( use full path if not in same directory as exe ) 2 -> (true -> Disable save/saveas/close in menu 3 -> left position viewer 4 -> top position viewer 5 -> formstyle top = alwaysonTop default = normal
* Fixed - starting position of viewer will be saved and used on next usage - if parameters 4 and 5 are used this will be the default
Отправлено: 22.03.25 19:49. Заголовок: В новой версии не мо..
В новой версии не могу понять , вьювер что был вшитый полностью похоронили и нужно теперь юзать внешний PsViewer. На домашней странице ни чего не нашел а хотелось бы иметь возможность предпросмотр делать по выбору как было или с ихним тормозным внешним PsViewer (VIEWER.EXE) Кто нибудь разбирался с этим вопросом ?
Отправлено: 22.03.25 20:54. Заголовок: Dima пишет: В новой..
Dima пишет:
цитата:
В новой версии не могу понять , вьювер что был вшитый полностью похоронили
Давно уже, лет около пяти назад. Последняя версия со встроенным просмотром, которая у меня есть - 3.0.4.125, могу поделиться. Сейчас, на сайте уже 3.0.4.178
Получается, чтобы просмотреть на экране результат, нужно переключать вывод в PDF. Раньше было удобнее - выводишь результат во "внутреннем формате" и потом - хоть на экран, хоть на принтер.
Отправлено: 22.03.25 21:40. Заголовок: Sergy У меня с сайт..
Sergy У меня с сайта сливал PS32-124.zip и там внутренний формат , скинь плиз куда тебе удобнее , сверю версии А на сайте счас фик поймёшь чего лежит...как то брал pagescript_4.0.1.157.zip одну из последних и это точно не 3.0.4.178 Где ты версию увидел на сайте ? Счас там всё куда то прибрали и не понять что за версия , внутри сырцов ни чего не пишут. Sergy пишет:
цитата:
Раньше было удобнее - выводишь результат во "внутреннем формате" и потом - хоть на экран, хоть на принтер.
Отправлено: 12.03.26 17:27. Заголовок: Имеем версию 3.0.4.1..
Имеем версию 3.0.4.124 Какая то лажа с формированием в PDF...кривой слегка выходит по сравнению с прежней версией 1.3.4.0 А если преобразовать этот PDF в PNG , то еще и кирилица становится не кирилицей )) Поюзал было PSSetPDFEmbeddedFonts(APS_PDF_FNT_FULL) PSSetPDFCharSet(ANSI_CHARSET) не помогло
облом короче, остаемся на версии AbeeLabs последней. а там последняя 3.x от PageScript32 , ведет себя странно при создании PDF , пол документа крякозяблами , другая часть кирилицей , да и работает этот продукт медленнее.
Отправлено: 26.03.26 23:33. Заголовок: Dima пишет: А мона ..
Dima пишет:
цитата:
А мона переналить ? Потерялось при переезде на вин 10
Если все еще нужно, будет лежать тут: https://cloud.mail.ru/public/RYeW/JdT44TtXf Скинул все версии, что у меня сохранились: 119, 125, 144, 178 И еще одна, не опознал какая. Возможно дубль.
Отправлено: 27.03.26 09:34. Заголовок: Sergy Сам какую вер..
Sergy Сам какую версию используешь ? На 3.0.4.178 бяка обнаружилась....все как бы относительно красиво , но при создании PDF , если там есть PSNewPage() то на нем падает с GPF То есть на самом первом падает.
Called from DLLCALL(0) Called from TPAGESCRIPT:NEWPAGE(1174) in tpscript.prg Called from PSNEWPAGE(3329) in tpscript.prg
Если тоже самое на печать отправлять или предпросмотр все норм.
Отправлено: 31.03.26 16:55. Заголовок: Я использую 3.0.4.12..
Я использую 3.0.4.125 - вообще никаких проблем с ним нет (тьфу*3). Перестал обновлять его в своем проекте после того, как разработчики вырезали встроенный просмотрщик документа.
А для формирования именно pdf использую hpdf. Ибо с него всё и началось. Но потом выяснилось, что рекомендованный на этом форуме SumatraPDF при печати тормозит просто невообразимо из-за того, что весь PDF перегоняет в растр и отправляет его на принтер.
Поэтому написал два объектных модуля-переходника, которые принимают "мою" разметку документа и для печати/просмотра вызывают PS32, а для сохранения файла - HDPF. Документы получаются идентичные. Возможно и через PS32 можно нормально делать pdf, но я толком не разбирался, потому что к этому моменту был написан код для HPDF.
Перестал обновлять его в своем проекте после того, как разработчики вырезали встроенный просмотрщик документа.
Так по ходу в 3.0.4.178 , это последняя от abeelabs , встроенный просмотровщик есть еще и его там можно закрывать по нажатию ESC и колесико мышки там работает.
Поэтому написал два объектных модуля-переходника, которые принимают "мою" разметку документа и для печати/просмотра вызывают PS32, а для сохранения файла - HDPF. Документы получаются идентичные.
можно чуть подробнее ? например как будет выглядеть переходник для Pstextbox
PS так...нашел HPDF_Page_TextRect аналог Pstextbox но там нельзя цвет фона задать... подожду твой ответ кстати есть дока на рус
VAR cDocType INIT "PS32" // признак, с чем работаем VAR hFont VAR nFontSize INIT 5 // in mm VAR nPenSize INIT 1 // in points = 1/72 inch VAR cFileName VAR nPageWidth VAR nPageHeight VAR lPortrait INIT TRUE VAR lWasPrinted INIT FALSE // признак: документ БЫЛ распечатан VAR nPageCounter INIT 1 VAR DPI VAR lTextMode INIT FALSE VAR bMessenger // блок кода, который будет выводиться в случае ошибки // METHOD New( cMode, cDocName, nNumCopies, lLandscape, lDuplex ) CONSTRUCTOR METHOD AddPage() METHOD Finish() // INLINE EVAL( { || PSEndDoc(), lDocInProgress := FALSE, TRUE } ) METHOD ShowError( cMessage ) // METHOD BeginText() INLINE (::lTextMode := TRUE) METHOD EndText() INLINE (::lTextMode := FALSE) // METHOD FontSet( cFontList ) // ==> hNewFont ready to use METHOD FontSize( nNewSize ) // get old / set new font size (mm) METHOD SetFontAndSize( hFont, nSize ) // set new font and its size METHOD TextOut( x, y, cText, nOrigin, lKeepCP ) METHOD TextOutDyn( x, y, cText, nWide, nOrigin ) METHOD TextRect( cText, x, y, nWide, nHigh, cHAlign, cVAlign ) METHOD TextRectDyn( cText, x, y, nWide, nHigh, cHAlign, cVAlign ) METHOD TextStream( x, y, cText, nLineHeight, bAddPage ) METHOD TextWidth( cText ) INLINE ::TextWide( Str2Ansi( cText ) ) // ширина текста в мм // METHOD DrawBox( x, y, nWide, nHigh, nPenSize, aFillRGB) METHOD DrawBox2( x, y, nWide, nHigh) METHOD DrawImage(x, y, nWide, nHigh, cImageFile) INLINE PSBitmap(::dy+y, ::dx+x, ::dy+y+nHigh, ::dx+x+nWide, cImageFile, 0xFFFFFF, TRUE) METHOD PageRulers() METHOD DrawBarCode(x, y, nLineWidePx, nCodeHeight, cType, cCode, nFlags, nOrigin, nShowTextMode, lVert, aEWA ) METHOD DrawEAN13( x, y, nLineWidePx, nCodeHeight, cCode, nOrigin ) METHOD Draw2DCode( x, y, nLineWidePx, cType, cCode, nFlags, nOrigin, lShowText ) // METHOD SetPenSize( nNewSize ) // in 1/72 inch = points! METHOD LineH( x, y, nWidth ) // mm METHOD MoveTo( x, y ) METHOD LineTo( x, y ) METHOD SetRGBFill( r, g, b ) METHOD SetRGBStroke( r, g, b ) METHOD Stroke() INLINE ( NIL ) METHOD Fill() INLINE ( NIL ) METHOD FillStroke() INLINE ( NIL ) // // PROTECTED: // VAR cDocMode // режим печати VAR dx // левое поле VAR dy // верхнее поле VAR nCurrentX // тек.позиция после MoveTo VAR nCurrentY // тек.позиция после MoveTo VAR nFontVShift INIT 0 // 0.1667 // font shift for vert.align in ::TextRectDyn() VAR nPageSize INIT DMPAPER_A4 VAR cEncoder INIT NIL // не используется VAR oPage INIT NIL // не используется // METHOD TextWide( cText ) INLINE ( PSGetTextWidth( cText ) ) // text wide in mm METHOD mm2px( mm ) INLINE ( mm * 0.03937 * ::DPI ) METHOD px2mm( px ) INLINE ( px / (::DPI * 0.03937) ) METHOD px2Font( px ) INLINE ( px * (::DPI / 72) ) METHOD ZebraDraw( hZebra, lVert, a, b, nLineWide, nCodeHeight ) // ENDCLASS
В зависимости от того, что нужно юзеру в данный момент (просмотр/печать или pdf файл), я вызываю либо oETF := PS32():New(...) либо oETF := EPDF():New(...) И дальше формирую документ только через методы oETF (extended text format - мое название переменной ).
Названия методов идентичные, но внутренности реализованы по своему. Вспомнил, что начал написание своего класса EPDF (extended pdf ) из-за дурацкого решения в HPDF, при котором координаты 0,0 - в левом нижнем углу страницы.
Я пока не понял как используя HPDF заюзать аналогичные параметры как в PS32 Про эти пишу: cFontName, nFontSize, nFontStyle, nFontFColor, nFontBColor, nThick Есть идеи ?
Отправлено: 02.04.26 13:44. Заголовок: Dima пишет: Есть ид..
Dima пишет:
цитата:
Есть идеи ?
Сейчас не могу вспомнить почему, но я вообще не использовал эти функции в своем коде. Возможно потому, что я начинал с HPDF и его разметка с началом координат в левом нижнем углу меня не устраивала. А возможно потому, что мне нужно было динамическое уменьшение размера шрифта, чтобы точно его вписать в прямоугольник.
* ------------------------------------------------------------------------ * METHOD TextRectDyn( cText, x, y, nWide, nHigh, cHAlign, cVAlign ) CLASS EPDF
STATIC cDividers := e" \t\r\n",; // stadard text dividers nSTEP := 0.975,; // font scale step nFILL_FACTOR := 0.75 // tex-in-rect fill factor, 1.0 == "full fill"
LOCAL nFontSize, nAreaBox, nAreaTxt, cTxt, nSaveFontSize, nCnt,; i, j, aText, nWordCnt, cWord, nWordWide, nLineWide, nSpaceWide,; nTextWide, cLine, nOrigin, nShift, nX, nY // hb_Default( @cHAlign, "<" ) // horizontal align = left hb_Default( @cVAlign, "-" ) // vertical align = center // cTxt := Str2Ansi( cText ) // 1st of all - change copdepage nFontSize := ::nFontSize // use local - may be changed! nSaveFontSize := ::nFontSize // save for further restore nAreaBox := nWide * nHigh * nFILL_FACTOR // площадь печати в кв.мм nAreaTxt := ::TextWide(cTxt)*nFontSize // площадь текста в кв.мм // IF (nAreaTxt > nAreaBox) nCnt := 0 DO WHILE TRUE nCnt++ // для отладки nFontSize := nFontSize * nSTEP // уменьшаем ::FontSize(nFontSize) // устанавливаем nAreaTxt := ::TextWide(cTxt) * nFontSize // новая площадь текста IF (nAreaTxt < nAreaBox) // fit ? EXIT // ok ENDIF ENDDO // ENDIF // // 1st check - to do not exceed "wide" parameter // nTextWide := ::TextWide(cTxt) IF (nTextWide > nWide) // exceed ? IF nFontSize > (nHigh / (1+INT(nTextWide / nWide))) nFontSize := nHigh / (1+INT(nTextWide / nWide)) nCnt := "1st" // just for info ::FontSize(nFontSize) ENDIF // // 2nd check - text may fit to one string // DO WHILE (::TextWide(cTxt) < nWide*0.99) // nFontSize := nFontSize / nSTEP // increase size nCnt := "2nd" // just for info ::FontSize(nFontSize) ENDDO // ENDIF // // text by words: // i := 1 aText := {} nWordCnt := NUMTOKEN(@cTxt,cDividers) nSpaceWide:= ::TextWide(" ") // wide of "space" - it known now nLineWide := 0 cLine := "" // buffer // DO WHILE (i <= nWordCnt) // all words cWord := " "+TOKEN(@cTxt,cDividers,i) // space+new word nWordWide := ::TextWide(cWord) // width in mm // IF (nWide + nSpaceWide) < (nLineWide + nWordWide) // exceed ? IF (nLineWide > 0) // not empty ? AADD(aText,LTRIM(cLine)) // добавляем набранную строку без пробела слева cLine := "" // новая строка начинается с этого слова nLineWide := 0 // сразу известна его длина i-- // еще раз разберем тек.слово в след. итерации ELSE // строка пустая, слово большое - впихнем по 1 символу пол-слова... j := 0 cWord := LTRIM(cWord) // убираем пробел слева DO WHILE TRUE j++ cLine += SUBSTR(cWord,j,1) // добавляем по одному символу IF ::TextWide(cLine) >= nWide cLine := LEFT(cLine,LEN(cLine)-1) // убираем лишний символ справа j-- // учитываем его EXIT ENDIF ENDDO // AADD(aText,cLine) // добавляем первую часть слова в массив cLine := SUBSTR(cWord,++j)+" " // начинаем от символа j и до конца строки+пробел nLineWide := ::TextWide(cLine) // ширина тек. строки - ненулевая! ENDIF ELSE cLine += cWord // добавляем слово к строке-накопителю nLineWide += nWordWide // наращиваем ширину в мм ENDIF // i++ ENDDO // IF LEN(cLine) > 0 // что-то накопилось ? AADD(aText,LTRIM(cLine)) // добавляем к хвосту текста ENDIF // // Третья проверка: если строк больше, чем влезет - еще раз уменьшаем: // IF LEN(aText) > (nHigh / nFontSize) nFontSize := nHigh / LEN(aText) ::FontSize(nFontSize) nCnt := "3rd " // признак ENDIF // // текст разбит на строки, начинаем вывод // IF LEN(aText) > 0 // есть текст ? // SWITCH cHalign CASE ">" // вправо ? nX := x+nWide // смещаемся вправо на ширину nOrigin := 7 // контр. точка = правый верхний угол текста EXIT CASE "|" // по центру ? nX := x+nWide/2 // смещаемся вправо на пол ширины nOrigin := 4 // контр. точка = верхний центр текста EXIT OTHERWISE nX := x // по умолчанию выравниваем влево nOrigin := 1 // контр. точка - top left END SWITCH // SWITCH cVAlign CASE "^" // вверх ? nY := y // просто верхний угол области EXIT CASE "v" // вниз ? nY := y + nHigh - LEN(aText)*nFontSize // top + высота - высота текста EXIT OTHERWISE nY := y + 0.5 * (nHigh - LEN(aText) * nFontSize) END SWITCH // nShift := ::nFontSize * ::nFontVShift // actually 0.1667 FOR i:=1 TO LEN(aText) ::TextOut(nX,nY-nShift,aText,nOrigin,TRUE) // TRUE = keep CP (codepage) nY += nFontSize // смещаемся на 1 строку вниз NEXT i // выводим диагностику #ifdef DEBUG IF !EMPTY(nCnt) HPDF_Page_SetRGBFill( ::oPage, 0, 0, 1) // blue color = diagnostic ::FontSize(2) ::TextOut(x+nWide-1,y+nHigh-1," ("+hb_ValToExp(nCnt)+" cnt > "+ALLTRIM(STR(nFontSize,15,2))+"mm)",9) HPDF_Page_SetRGBFill( ::oPage, 0, 0, 0) // black again ENDIF #endif // ENDIF // IF nCnt != NIL // изменялся размер текста ? ::FontSize(nSaveFontSize) // восстанавливаем ENDIF // RETURN (nCnt == NIL) // TRUE = всё влезло, FALSE = пришлось масштабировать.
* ------------------------------------------------------------------------ * METHOD TextRectDyn( cText, x, y, nWide, nHigh, cHAlign, cVAlign ) CLASS PS32 // дин. масштабирование
STATIC cDividers := e" \t\r\n",; // stadard text dividers nSTEP := 0.975,; // font scale step nFILL_FACTOR := 0.75 // tex-in-rect fill factor, 1.0 == "full fill"
LOCAL nFontSize, nAreaBox, nAreaTxt, cTxt, nSaveFontSize, nCnt,; i, j, aText, nWordCnt, cWord, nWordWide, nLineWide, nSpaceWide,; nTextWide, cLine, nOrigin, nX, nY, nShift // hb_Default( @cHAlign, "<" ) // horizontal align = left hb_Default( @cVAlign, "-" ) // vertical align = center // cTxt := Str2Ansi( cText ) // 1st of all - change copdepage nFontSize := ::nFontSize // use local - may be changed! nSaveFontSize := ::nFontSize // save for further restore nAreaBox := nWide * nHigh * nFILL_FACTOR // площадь печати в кв.мм nAreaTxt := ::TextWide( cTxt )*nFontSize // площадь текста в кв.мм // IF nAreaTxt > nAreaBox nCnt := 0 DO WHILE TRUE nCnt++ // для отладки nFontSize := nFontSize * nSTEP // уменьшаем ::FontSize( nFontSize ) // устанавливаем nAreaTxt := ::TextWide(cTxt) * nFontSize // новая площадь текста IF nAreaTxt < nAreaBox // fit ? EXIT // ok ENDIF ENDDO // // RawDebug2File( hb_ValToExp( cTxt )+" was exceed print area ("+hb_NTOS( nAreaBox )+"mm), changed size to "+hb_NTOS( ::FontSize ) ) // ENDIF // // 1st check - to do not exceed "wide" parameter // nTextWide := ::TextWide( cTxt ) IF nTextWide > nWide // exceed ? IF nFontSize > ( nHigh / ( 1+INT(nTextWide / nWide)) ) nFontSize := nHigh / ( 1+INT(nTextWide / nWide) ) nCnt := "1st" // just for info ::FontSize( nFontSize ) ENDIF // // 2nd check - text may fit to one string // DO WHILE (::TextWide( cTxt ) < nWide*0.99 ) // nFontSize := nFontSize / nSTEP // increase size nCnt := "2nd" // just for info ::FontSize( nFontSize ) ENDDO // // RawDebug2File( hb_ValToExp(cTxt)+" was exceed line wide ("+hb_NTOS(nWide)+"mm), changed size to "+hb_NTOS( ::FontSize ) ) // ENDIF // // text by words: // i := 1 aText := {} nWordCnt := NUMTOKEN( @cTxt, cDividers ) nSpaceWide := ::TextWide( " " ) // wide of "space" - it's known now nLineWide := 0 cLine := "" // buffer // DO WHILE (i <= nWordCnt) // all words // cWord := " "+TOKEN( @cTxt, cDividers, i ) // space+new word nWordWide := ::TextWide( cWord ) // width in mm // IF (nWide + nSpaceWide) < (nLineWide + nWordWide) // exceed ? IF nLineWide > 0 // not empty ? AADD( aText, LTRIM(cLine) ) // добавляем набранную строку без пробела слева cLine := "" // новая строка начинается с этого слова nLineWide := 0 // сразу известна его длина i-- // еще раз разберем тек.слово в след. итерации ELSE // строка пустая, слово большое - впихнем по 1 символу пол-слова... j := 0 cWord := LTRIM( cWord ) // убираем пробел слева DO WHILE TRUE j++ cLine += SUBSTR( cWord, j, 1 ) // добавляем по одному символу IF ::TextWide( cLine ) >= nWide cLine := LEFT( cLine, LEN( cLine )-1 ) // убираем лишний символ справа j-- // учитываем его EXIT ENDIF ENDDO // AADD( aText, cLine ) // добавляем первую часть слова в массив cLine := SUBSTR( cWord, ++j )+" " // начинаем от символа j и до конца строки+пробел nLineWide := ::TextWide( cLine ) // ширина тек. строки - ненулевая! ENDIF ELSE cLine += cWord // добавляем слово к строке-накопителю nLineWide += nWordWide // наращиваем ширину в мм ENDIF // i++ ENDDO // IF LEN(cLine) > 0 // что-то накопилось ? AADD( aText, LTRIM( cLine ) ) // добавляем к хвосту текста ENDIF // // Третья проверка: если строк больше, чем влезет - еще раз уменьшаем: // IF LEN(aText) > (nHigh / nFontSize) nFontSize := nHigh / LEN(aText) ::FontSize( nFontSize ) nCnt := "3rd " // признак ENDIF // // текст разбит на строки, начинаем вывод // IF LEN(aText) > 0 // есть текст ? // SWITCH cHalign CASE ">" // вправо ? nX := x+nWide // смещаемся вправо на ширину nOrigin := 7 // контр. точка = правый верхний угол текста EXIT CASE "|" // по центру ? nX := x+nWide/2 // смещаемся вправо на пол ширины nOrigin := 4 // контр. точка = верхний центр текста EXIT OTHERWISE nX := x // по умолчанию выравниваем влево nOrigin := 1 // контр. точка - top left END SWITCH // SWITCH cVAlign CASE "^" // вверх ? nY := y // просто верхний угол области EXIT CASE "v" // вниз ? nY := y + nHigh - LEN(aText)*nFontSize // top + высота - высота текста EXIT OTHERWISE nY := y + 0.5 * (nHigh - LEN(aText) * nFontSize) END SWITCH // nShift := ::nFontSize * ::nFontVShift // FOR i:=1 TO LEN( aText ) ::TextOut( nX, nY-nShift, aText, nOrigin, TRUE ) // TRUE == keep codepage nY += nFontSize // смещаемся на 1 строку вниз NEXT i // выводим диагностику #ifdef DEBUG IF !EMPTY( nCnt ) i := PSSetFontFColor( APS_BLUE ) // blue color = diagnostic ::FontSize( 2 ) ::TextOut( x+nWide-1, y+nHigh-1, " ("+hb_ValToExp(nCnt)+" cnt > "+ALLTRIM( STR( nFontSize, 15, 2 ) )+"mm)", 9 ) PSSetFontFColor( i ) // back again ENDIF #endif // ENDIF // IF nCnt # NIL // изменялся размер текста ? ::FontSize( nSaveFontSize ) // восстанавливаем ENDIF // RETURN (nCnt == NIL) // TRUE = всё влезло, FALSE = пришлось масштабировать.
В принципе, если тебе нужно, я скину тебе эти два модуля - они к любому проекту должны прикрутиться без проблем.
Отправлено: 02.04.26 13:54. Заголовок: Если конкретно по шр..
Если конкретно по шрифтам, то я использую эти методы:
METHOD FontSet( cFontList ) // ==> hNewFont ready to use METHOD FontSize( nNewSize ) // get old / set new font size (mm) METHOD SetFontAndSize( hFont, nSize ) // set new font and its size
То есть - сначала передаю все шрифты в виде списка, а потом переключаю их по мере формирования документа. В методы вывода текста
METHOD TextOut( x, y, cText, nOrigin, lKeepCP ) METHOD TextOutDyn( x, y, cText, nWide, nOrigin ) METHOD TextRect( cText, x, y, nWide, nHigh, cHAlign, cVAlign ) METHOD TextRectDyn( cText, x, y, nWide, nHigh, cHAlign, cVAlign ) METHOD TextStream( x, y, cText, nLineHeight, bAddPage )
Не передаю шрифт, они берут текущий по умолчанию. Например, если мне нужен заголовок таблицы, я один раз делаю SetFontAndSize( hFont, nSize ) После чего идет куча TextRect для заголовка Потом снова один SetFontAndSize( hFont, nSize ) и куча уже TextRectDyn для ячеек таблицы - на случай, если что-то не влезет, размер будет автоматически уменьшен.
LOCAL aFillSave,x,y,w,h // #ifdef DEBUG IF ::lTextMode ? "::DrawBox() - invalid call between ::BeginText() / ::EndText()" INKEY(0) RETURN -1 ENDIF #endif // x := ::x2pdf( xMM ) // х без изменений y := ::y2pdf( yMM+nHigh ) // y переводим координату из TL в BL w := ::mm2px( nWide ) // ширина - из мм в точки h := ::mm2px( nHigh ) // высота - из мм в точки // HPDF_Page_SetLineWidth( ::oPage, nPenSize ) // IF hb_IsARRAY( aFillRGB ) aFillSave := HPDF_Page_GetRGBFill( ::oPage ) HPDF_Page_SetRGBFill( ::oPage, aFillRGB[1], aFillRGB[2], aFillRGB[3] ) HPDF_Page_Rectangle( ::oPage, x, y, w, h ) // IF nPenSize > 0 HPDF_Page_FillStroke( ::oPage ) ::nPenSize := nPenSize // если задана толщина = сохраняем её в объекте ELSE HPDF_Page_Fill( ::oPage ) ENDIF HPDF_Page_SetRGBFill( ::oPage, aFillSave[1], aFillSave[2], aFillSave[3] ) ELSE HPDF_Page_Rectangle( ::oPage, x, y, w, h ) HPDF_Page_Stroke( ::oPage ) ENDIF // #ifdef DEBUG // отрисовка центральных линий по горизонтали и вертикали, если есть рамка IF hb_IsNumeric( nPenSize ) .AND. ( nPenSize > 0 ) IF (nHigh < ::nPageHeight/2) HPDF_Page_SetLineWidth( ::oPage, nPenSize / 2) HPDF_Page_Rectangle( ::oPage,x,y,w/2,h/2) HPDF_Page_Rectangle( ::oPage,x+w/2,y+h/2,w/2,h/2) HPDF_Page_Stroke( ::oPage ) ENDIF HPDF_Page_SetLineWidth( ::oPage, ::nPenSize ) // восст.толщину линии ENDIF #endif // RETURN ::ShowError( "DrawBox()" )
Все даты в формате GMT
3 час. Хитов сегодня: 1283
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет