Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

принтер - точное позиционирование


Urvin ©   (2006-06-08 16:54:00) 

Необходимо совершить точное позиционирование рисованных объектов на принтере, т.е., например, вывести прямоугольник  размером сантиметр на сантиметр на расстоянии по два сантиметра с верохнего и левого края листа.

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

printer.BeginDoc;
SetMapMode(printer.Canvas.Handle, MM_LOMETRIC);
printer.Canvas.rectangle(200,-200,300,-300);
printer.EndDoc;


как добиться правильного размещения этого прямоугольника на листе?


Urvin   (2006-06-09 09:11:00) [1]

Реализация в коде получилась следующая:

procedure TForm1.Button1Click(Sender: TObject);
var
 logX, logY,offX,offY,phsX,phsY,dpiX,dpiY: integer;
 DZLeft,DZTop,DZRight, DZBottom: integer;
const
 mmpi: single = 25.4; //Константа количества миллиметров в дюйме
begin
 printer.Title:='Printer test page';
 printer.BeginDoc;

 //Устанавливаем логическую единицу размера
 //Одна единица - 0.1 миллиметра
 //Координаты отсчитываются с верхнего левого края
 //вправо и вверх (!)
 SetMapMode(printer.Canvas.Handle, MM_LOMETRIC);

 //Вычисление количества пикселей на дюйм
 dpiX :=GetDeviceCaps(Printer.Handle, LogPixelsX);
 dpiY :=GetDeviceCaps(Printer.Handle, LogPixelsY);

 //Логические размеры печатаемой области
 logX :=GetDeviceCaps(Printer.Handle, HORZRES);
 logY :=GetDeviceCaps(Printer.Handle, VERTRES);

 //мертвая зона левого и верхнего краев листа
 offX :=GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX);
 offY :=GetDeviceCaps(Printer.Handle, PHYSICALOFFSETY);

 //физические размеры листа в пикселях
 phsX :=GetDeviceCaps(Printer.Handle, PHYSICALWIDTH);
 phsY :=GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT);

 //вычисленная в логических единицах мертвая зона
 DZLeft:=  round(10 * mmpi * offX / dpiX);
 DZTop:=   round(10 * mmpi * offY / dpiY);
 DZRight:= round(10 * mmpi * (phsX-logX-offX) / dpiX);
 DZBottom:=round(10 * mmpi * (phsY-logY-offY) / dpiY);

 with printer.Canvas do
 begin
   //Выводим четыре квадрата по краям листа с поправкой на мертвую зону
   rectangle(0   -DZLeft, 0    +DZTop, 200-DZLeft, -200+DZTop);
   rectangle(1900-DZLeft ,0    +DZTop ,2100-DZLeft,-200 +DZTop);
   rectangle(0   -DZLeft ,-2770+DZTop ,200 -DZLeft,-2970+DZTop);
   rectangle(1900-DZLeft ,-2770+DZTop ,2100-DZLeft,-2970+DZTop);

   //И проведем через их середины линии
   MoveTo(100-DZLeft,-100+DZTop); LineTo(2000-DZLeft,-100+DZTop);
   MoveTo(100-DZLeft,-100+DZTop); LineTo(100-DZLeft,-2870+DZTop);
   MoveTo(2000-DZLeft,-100+DZTop); LineTo(2000-DZLeft,-2870+DZTop);
   MoveTo(100-DZLeft,-2870+DZTop); LineTo(2000-DZLeft,-2870+DZTop);

   //Установим шрифт высотой 5 миллиметров
   Font.Height := 50;
   Font.Name   := 'Verdana';

   //Выведем текст позиционируя без поправки на мертвую зону
   TextOut(250, - 110, 'Printer test page ' + printer.Printers[printer.PrinterIndex]);
   TextOut(250, - 180, 'Death zone: Upper(' +  FloatToStr(DZLeft/10) + ', ' + FloatToStr(DZTop/10) + ') '
                                 + 'Lower(' + FloatToStr(DZRight/10) + ', ' + FloatToStr(DZBottom/10) + ')' );

   //Нарисуем линию длиной в 7.5 сантиметров без поправки на мертвую зону
   MoveTo(250, - 240);
   LineTo(1000, - 240);
 end;
 printer.EndDoc;
end;


Джо   (2006-06-08 21:55:00) [2]

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


Джо   (2006-06-08 21:52:00) [3]

> [7] Sergey Masloff   (08.06.06 21:35)
> Да это все хорошо. Относительно того что драйвер тебе рассказал
> ты отпозиционируешься. А что у принтера лоток кривой и смещен
> тоже он сообщит?
> К сожалению как показывает мой опыт (печать пары миллионов
> полисов страхования туристов и почти столько же автострахования
> на типографских бланках в тысячах точек извините за попытку
> мерянья) - не хватает программных настроек. Всегда нужно
> пользователю давать возможность подкорректировать.

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


Sergey Masloff   (2006-06-08 21:35:00) [4]

Urvin   (08.06.06 20:38) [6]
>тот же ворд работает без запросов пользователя на вбивание смещений
Извини, но это можешь бабушке своей рассказывать

Джо ©   (08.06.06 20:27) [5]
>Отчего же? Определяешь с помощью GetDeviceCaps PHYSICALOFFSET'ы
Да это все хорошо. Относительно того что драйвер тебе рассказал ты отпозиционируешься. А что у принтера лоток кривой и смещен тоже он сообщит?
К сожалению как показывает мой опыт (печать пары миллионов полисов страхования туристов и почти столько же автострахования на типографских бланках в тысячах точек извините за попытку мерянья) - не хватает программных настроек. Всегда нужно пользователю давать возможность подкорректировать.


Urvin   (2006-06-08 20:38:00) [5]

Sergey Masloffтот же ворд работает без запросов пользователя на вбивание смещений!

всем спасибо! иду прововать!


Джо   (2006-06-08 20:27:00) [6]

> [4] Sergey Masloff   (08.06.06 20:23)

Отчего же? Определяешь с помощью GetDeviceCaps PHYSICALOFFSET'ы и их уже можешь вычитать из координат для печати.


Sergey Masloff   (2006-06-08 20:23:00) [7]

Да без разницы зоны. Принтеры разные все равно если в точные бланки надо впечатывать автоматом не получится. Все равно придется в настройках пользователя дельту хранить - смещения левого верхнего угла по x и y


Virgo_Style   (2006-06-08 18:29:00) [8]

см. в эту сторону (кусок из старой программы... могу что-то забыть или напутать)

 //dpi:
  dpiX :=GetDeviceCaps(Printer.Handle, LogPixelsX);
 dpiY :=GetDeviceCaps(Printer.Handle, LogPixelsY);

 //размеры логические:
logX :=GetDeviceCaps(Printer.Handle, HORZRES);
 logY :=GetDeviceCaps(Printer.Handle, VERTRES);

 //мертвая зона в... в чем? afair, пиксели
offX :=GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX);
 offY :=GetDeviceCaps(Printer.Handle, PHYSICALOFFSETY);

 //физические размеры... вроде тоже пиксели
 phsX :=GetDeviceCaps(Printer.Handle, PHYSICALWIDTH);
 phsY :=GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT);


 // итого мертвая зона (поля т.е.) в пикселях:
DZLeft:=offX ;
 DZTop:= offY;
 DZRight:= phsX-logX-offX;
 DZBottom:=phsY-logY-offY;


еще раз предупреждаю - проверь... но общее направление вроде такое. И вроде даже получалось %-)


Urvin   (2006-06-08 17:27:00) [9]

Amoeba, дык в том и вопрос! не пользователю же с линейкой ползать по листу и вбивать значения полей!


Amoeba   (2006-06-08 17:21:00) [10]

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


Наверх

Титульная страница Поиск, карта сайта Написать письмо