问题: 高手请近:要使在纸上打印出字的实际高度为5mm,如何设定打印机的字体大小 ( 积分: 100 )
分类: 打印
来自: yqdragon, 时间: 2004-10-31 12:49:00, ID: 2873661
知道实际打印出的字的高度,比如我要想使打印出来的字的高度为5mm,通过PRINTER画布打印,怎样计算PRINTER的FONT.SIZE的值呢。请高手帮忙,甚谢,分不够再加。
来自: 池龙, 时间: 2004-10-31 13:16:16, ID: 2873679
对于你的问题,有两种处理方法:
1. 设置Printer.Canvas.Font.Height
用以下两行代码可以取得打印机在X和Y方向上的分辨率。
ResX := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
ResY := GetDeviceCaps(Printer.Handle, LOGPIXELSY);
对于分辨率,计算机使用的单位是 像素 / 英寸,1英寸 = 25.4毫米。所以你要的5毫米高度的文字,其实际(像素作单位)的高度就是:ResY / 25.4 * 5。比如,对于一个600dpi的打印机,你在其画布上绘制118像素高度的文字,输出的实际尺寸就是5毫米。
2. 设置Printer.Canvas.Font.Size
通常我们说的字体的“Size”,其单位是“磅”,这是由实际印刷时的计量单位而引入的。1磅 = 1/72英寸,同样的,1英寸 = 25.4毫米。也就是说,1磅 约合 1 / 72 * 25.4 = 0.3528毫米,要输出5毫米的文字,只需要设置其字体尺寸为:5 / ( 1 / 72 * 25.4 ) 约为14磅就可以了。
来自: yqdragon, 时间: 2004-10-31 15:38:42, ID: 2873790
楼上的方法对吗,按照处理方法2:设置Printer.Canvas.Font.Size的大小,该值固定不变了,也就是要想打印出的大小为X,除以(1/72*25.4)就行了。按照处理方法1:设置设置Printer.Canvas.Font.Height的大小,然后若将其转换为Printer.Canvas.Font.Size的大小,同样是固定的。这样就不依赖于打印机的分辨率了。而实际上与打印机的分辨率是有关系的吧,请大家继续讨论。。。。。。。。。
来自: 池龙, 时间: 2004-10-31 19:19:08, ID: 2873918
晕,你有没有试过这两种方法?
确实如你所怀疑的,字体的Size是与设备的分辨率无关的。也就是说,你只要设置字体的Size为14,那么不管在什么打印机上,输出的字差不多都会是5毫米这么大。这个换算不需要我们进行干预的原因,在下面会讲到。
而Font.Height是根据实际输出设备的dpi经过计算得到的数值,你可以试试看,同样将设备的Font.Size设置为9,在Form的Canvas上,Font.Height是-12,而在600dpi的打印机的Canvas上,Font.Height是-75。
注意,要在BeginDoc之后,打印机的Canvas的Font.Height才会根据Font.Size重新计算。
所以在代码里,建议你使用字体的字号,因为这个度量单位相对来说更为通用,也更为安全。
你可以在系统里面添加一个打印机,然后试试看下面这段代码:
procedure TForm1.Button1Click(Sender: TObject);
var
ResY: integer;
begin
ResY := GetDeviceCaps(Canvas.Handle, LOGPIXELSY);
ShowMessage(format('屏幕的分辨率是:%d,9号字在打印机上的高度是:%d', [ResY, Canvas.Font.Height]));
Printer.BeginDoc;
Printer.Canvas.Font.Size := 9;
ResY := GetDeviceCaps(Printer.Handle, LOGPIXELSY);
ShowMessage(format('打印机的分辨率是:%d,9号字在打印机上的高度是:%d', [ResY, Printer.Canvas.Font.Height]));
Printer.EndDoc;;
end;
你可以通过察看TFont和TPrinter的代码来了解更为细节的东西。
procedure TFont.SetSize(Value: Integer);
begin
Height := -MulDiv(Value, FPixelsPerInch, 72);
end;
MulDiv是一个API函数,相当于
Result := A * B div C
A、B、C是依次三个参数
在TFont类中,设置Size的时候,Height会经由Size和FPixelPerInch经过换算而得到新的数值。
procedure TPrinter.BeginDoc;
var
DocInfo: TDocInfo;
begin
CheckPrinting(False);
SetState(psHandleDC);
Canvas.Refresh;
//注意这一行
TPrinterCanvas(Canvas).UpdateFont;
FPrinting := True;
FAborted := False;
FPageNumber := 1;
FillChar(DocInfo, SizeOf(DocInfo), 0);
with DocInfo do
begin
cbSize := SizeOf(DocInfo);
lpszDocName := PChar(Title);
end;
SetAbortProc(DC, AbortProc);
StartDoc(DC, DocInfo);
StartPage(DC);
end;
而TPrinter类,在调用BeginDoc的过程中,会将设备的分辨率设置给字体。此时就会涉及到上面,TFont.SetSize的过程。
//UpdateFont的实际代码
procedure TPrinterCanvas.UpdateFont;
var
FontSize: Integer;
begin
//注意这一行,取得了打印机设备上下文的Y方向的逻辑分辨率
if GetDeviceCaps(Printer.DC, LOGPIXELSY) <> Font.PixelsPerInch then
begin
//如果与字体的原有分辨率不同。
//则先保存字体的Size
FontSize := Font.Size;
//设置新的分辨率
Font.PixelsPerInch := GetDeviceCaps(Printer.DC, LOGPIXELSY);
//重新设置Size,在此处计算了新的Height
Font.Size := FontSize;
end;
end;
顺便说一下,不要用Acrobat的PDF Writer作试验,虽然这个虚拟打印机在配置的时候显示是600dpi,但在实际操作时,它的分辨率是96dpi,与屏幕的分辨率一致。
另外,Delphi在处理的时候将Height和Size设置为一个正值一个负值。除了符号不同之外,似乎对绘制没有影响,目前我还没有找到它这样设计的原因。
来自: xebaobei, 时间: 2004-10-31 19:22:49, ID: 2873920
都是高人回帖子啊!
LQ有打印指令,可以自己定义字符
当然包括汉字。
直接发指令可以实现无驱动打印!打印机没硬字库也可以!
来自: 池龙, 时间: 2004-10-31 19:35:46, ID: 2873933
ESC/P和ESC/P-K是Epson自己搞的,印象中好像没有什么其它地方得到支持。还是用通用一点的方法好。
来自: yqdragon, 时间: 2004-11-01 12:06:32, ID: 2874692
是这样吗,谢谢池龙!我原本认为FONT.size肯定与分辨率有关的。先结贴。。。
来自: yqdragon, 时间: 2004-11-01 12:07:23, ID: 2874697
接受答案了.
得分大富翁: 池龙