![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
принтер - точное позиционирование
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]Чтобы этого добиться, надо при расчете координат вводить поправку на размер полей на листе, которые недоступны принтеру для печати (координаты отсчитываются относительно области листа, на которую принтер можнт что-либо печатать).