怎样控制打印页面设置,解决马上给分 (100分)

  • 主题发起人 主题发起人 李崇文
  • 开始时间 开始时间

李崇文

Unregistered / Unconfirmed
GUEST, unregistred user!
我想打印时,打印左边空白=0,打印顶部空白=0,请问用Delphi的
TPrinter提供的类能实现吗,或则用API能实现吗?请帮我指点。
怎么才能找到TDeviceMode结构的帮助,请帮我解释这个结构的成员
 
TDeviceMode是对DEVMODE的封装,在msdn中查DEVMODE就行了
打印时边上的空白是有程序来实现的,不是改DeviceMode的成员实现的
 
to Kang:
怎么通过程序来实现空白设置,能详细点吗?
 
看看这个行不行。
procedure TForm3.BitBtn4Click(Sender: TObject);
const
LeftBlank=0;
//定义页边距,单位厘米
RightBlank=0;
TopBlank=0;
BottomBlank=0;
var
PointX,PointY:integer;
PointScale,PrintStep:integer;
s:string;
x,y:integer;
i:integer;
begin
//获取当前打印机的分辨率
PointX:=Trunc(GetDeviceCaps(Printer.Handle,LOGPIXELSX)/2.54);
PointY:=Trunc(GetDeviceCaps(Printer.Handle,LOGPIXELSY)/2.54);
//根据打印机和屏幕的分辨率计算出从屏幕转换到打印机的比例 
PointScale:=Trunc(GetDeviceCaps(Printer.Handle,LOGPIXELSX)/Screen.PixelsPerInch+0.5);
//横向打印
printer.Orientation:=poPortrait;
//打印的字体和大小
printer.Canvas.Font.Name:='宋体';
printer.canvas.Font.Size:=12;
//根据字体的大小确定每行的高度
s:='出货分类统计表';
PrintStep:=printer.canvas.TextHeight(s)+16;
//打印的起点位置
x:=PointX*LeftBlank;
y:=PointY*TopBlank;
//DataSource1是DBGrid1所连接的数据源
if ((DM1.ds2.DataSet).Active=true) and ((DM1.ds2.DataSet).RecordCount>0) then

begin

printer.begin
Doc;
(dm1.ds2.DataSet).First;
while not (dm1.ds2.DataSet).Eofdo

begin
//打印DBGrid中的所有列
for i:=0 to DBGrid1.FieldCount-1do

begin

//假如所要打印的列超出了打印范围,则忽略该列
if (x+DBGrid1.Columns.Items.Width*PointScale)<=(Printer.PageWidth-PointX*RightBlank) then

begin
//画表格线
//每页的第一行打印表头
Printer.Canvas.Rectangle(x,y+200,x+DBGrid1.Columns.Items.Width*PointScale,y+200+PrintStep);
if y=PointY*TopBlank then
begin

printer.Canvas.Font.Name:='黑体';
printer.canvas.Font.Size:=16;
Printer.Canvas.TextOut((Printer.PageWidth-printer.Canvas.TextWidth(s)) div 2,y+8,s);
printer.Canvas.Font.Name:='宋体';
printer.canvas.Font.Size:=12;
Printer.Canvas.TextOut(x+8,y+8+200,DBGrid1.Columns.Title.Caption);
end
else

Printer.Canvas.TextOut(x+8,y+200+8,DBGrid1.Fields.asString);
end;

//计算下一列的横坐标
x:=x+DBGrid1.Columns.Items.Width*PointScale;
end;


if not (y=PointY*TopBlank) then

(dm1.ds2.DataSet).next;
x:=PointX*LeftBlank;
y:=y+PrintStep;
//换页
if (y+PrintStep)>(Printer.PageHeight-PointY*BottomBlank) then

begin

Printer.NewPage;
y:=PointY*TopBlank;
end;

end;


printer.EndDoc;
(dm1.ds2.DataSet).First;
Application.MessageBox('打印完成','打印',32);
end;

end;


 
比如你在 x,y位置打印字符串可以Printer.Canvas.TextOut(x+dx,y+dy,'sss')
改变dx,dy的值就可以改变上边空白和左边空白,
当然,你得按楼上的计算mm到Pix先
 
to mlzhou,Kang:
你们两个的答案可能不符合我这种情况
我的打印机输出时,左边和顶部都默认有一段空白,但我想设置打印机,使它
默认打印时左边=0,顶部=0,如下列代码,我本想输出在左上角(0,0)的位置:
Printer.begin
Doc;
Printer.Canvas.TextOut(0,0,'请在纸张的(0,0)位置给我输出');
Printer.EndDoc;
但输出时不是在纸张(0,0)位置输出,而是偏离dx,dy的一个值,要想在(0,0)位置输出
我还的人为的减去这个偏差值,如下:
Printer.begin
Doc;
Printer.Canvas.TextOut(-dx,-dy,'请在纸张的(0,0)位置给我输出');
Printer.EndDoc;
但我不想这样,因为可能每种打印机的默认偏差dx,dy都不同,而且我可能也没法得到
dx,dy偏差值,那么对于不同的打印机,可能又不能在纸张的(0,0)输出,
因此,我想有什么方法可以设置打印头的位置自动移到纸张的(0,0)位置打印,
或则通过程序能得到打印机的LeftBlank,TopBlank的值也行

 
Margin.x :=GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX);{页边距X}
Margin.y :=GetDeviceCaps(Printer.Handle, PHYSICALOFFSETY);{页边距y}
可以得到页边距,
 
to mlzhou:
我看了一下帮助,
Margin.x :=GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX);{页边距X}
Margin.y :=GetDeviceCaps(Printer.Handle, PHYSICALOFFSETY);{页边距y}
确实使用来得到页边距的,但得到的数据和我输出的实际位置缺差别很大,
下面是我测试的数据
求得数据:
Margin.x = 23
Margin.y = 60
实际数据 我的打印机 180Pixels/inch
左边空白 = 17mm 大约是120Pixels(打印机的像素)
顶部空白 = 10mm 大约是70Pixels(打印机的像素)
不知道是什么原因,能给我解释一下吗?回答这个问题我将给分了
 
通常针式打印机没有不可打印区域,而激光或喷墨打印机都有不可打印区域,即
左上部分和右下部分有一定区域不可打印
下面该函数功能是将给出的具体长度的边界值转化为打印机左上角和右下交的相应的DPI数
并且考虑了不可对应的边界问题
请试用
//其中Rect给出的是左边界,上边距,右边距,下边距,单位为0.1毫米
procedure GenerateRect(var outRect : PRect);
var
changeTopY,changeleftX,ChangeRightX,ChangeBottomY : Real;
nTotalPixelsY,nTotalm,tmpPageHeight,tmpPageWidth,nTotalPixelsX : longint;
nPerPixels100mm : longint;//每100毫米的象素数
begin

Screen.Cursor := crHourGlass;

try
Printer.begin
Doc;

//设置打印字体
With Printer.Canvasdo

begin

Font.Name:='宋体';
Font.Size:=10;

Font.Style:=[];
end;

////////////////////////////////调节边界
//设置映射方式
SetMapmode(printer.canvas.Handle,mm_Text);
nTotalPixelsY := GetDevicecaps(Printer.Canvas.handle,VERTRES);//打印机垂直象素数
nTotalPixelsX := GetDevicecaps(Printer.Canvas.handle,HORZRES);//打印机水平象素数
nTotalm := GetDevicecaps(Printer.Canvas.handle,VERTSIZE);//打印机可用长度,毫米为单位
nPerPixels100mm := Round(nTotalPixelsY*100/nTotalm);//每100毫米对应的象素数,取100主要是为了增加分辨率
tmpPageWidth := GetDevicecaps(Printer.Canvas.handle,PHYSICALWIDTH);//完全水平长度
tmpPageHeight := GetDevicecaps(Printer.Canvas.handle,PHYSICALHEIGHT);//完全竖直长度
changeTopY := GetDevicecaps(Printer.Canvas.handle,PHYSICALOFFSETY);//不可打印上边界
ChangeleftX := GetDevicecaps(Printer.Canvas.handle,PHYSICALOFFSETX);
//不可打印左边界
ChangeRightX := tmpPageWidth - nTotalPixelsX - ChangeleftX;//不可打印右边界
ChangeBottomY := tmpPageHeight - nTotalPixelsY - changeTopY;//不可打印下边界
//原RECT结构为0.1毫米结构,
//现在将其转化为左上角和右下角的DPI数
outRect^.left := Round((OutRect^.left*nPerPixels100mm/1000-ChangeLeftX));
OutRect^.Top := Round((OutRect^.Top*nPerPixels100mm/1000-ChangeTopY));
OutRect^.Right := Round((tmpPageWidth - OutRect^.Right*nPerPixels100mm/1000 - ChangeRightX));
OutRect^.Bottom := Round((tmpPageHeight-OutRect^.Bottom*nPerPixels100mm/1000 - ChangeBottomY));
//打印TCHART
Chart1.Printpartial(outRect^);
Printer.EndDoc;//打印结束
except
on Exceptiondo
// 如果出错
begin

Printer.Abort;
end;

end;

Screen.Cursor:=crDefault;
end;

 
to mlzhou:
非常感谢你的详细回答!你的程序和我的需求好像不太相关
你的OutRect参数还的我先赋一个值,我该赋给他什么值?
我的打印机是针式的,我用打印机控制码能控制左边距=0,
但我用Delphi中的Printer对象打印时,就会出现页空白,
但我不想用打印机控制码,因为我实现套打功能,有很多需要
套打的票据,用控制码显得太麻烦,而且不一定通用。因此我直接
用Printer对象,首先在Printer对象的画布上,按照测量的位置输出文字。
假如我要打印如下类容:
姓名
姓名在票据中的位置(矩形):
Left = 30mm(指离票据左边30mm)
Top = 16mm(离票据顶部16mm)
Width = 20mm(姓名输出栏所在矩形的宽度)
Height = 8mm(姓名输出栏所在矩形的高度)
下面我是我的代码:
procedure Print;
var
PixelsPerMmX,PixelsPerMmY:do
uble;
//为X,Y轴方向打印机的每毫米的像素点
//假设以求出
Point: TPoint;
beign
Printer.BeignDoc;
try
Point.X := Trunc(PixelsPerMm*30);
Point.Y := Trunc(PixelsPerMm*16);
Printer.Canvas.TextOut(Point.X,Point.Y,'姓名');
finally
Printer.EndDoc;
end;

end;

但打印时不是在票据的Left = 30 mm;Top = 16mm输出,而是在Left = (30+dx)mm
Top = (16+dy)mm输出,假如我已测的dx = 120pix/mm,dy = 70pix/mm,
那么我把代码该位如下,则输出结果很好:
procedure Print;
var
PixelsPerMmX,PixelsPerMmY:do
uble;
//为X,Y轴方向打印机的每毫米的像素点
//假设以求出
Point: TPoint;
beign
Printer.BeignDoc;
try
Point.X := Trunc(PixelsPerMm*30);
Point.Y := Trunc(PixelsPerMm*16);
Printer.Canvas.TextOut(Point.X-120,Point.Y-70,'姓名');
finally
Printer.EndDoc;
end;

end;

所以我想用Api函数实现用控制码控制页边距的功能,或则通过
API函数求得上面的dx,dy得值(因为这个值我是针对我的打印机测出来的,
其他的打印机就不知道了)


 
是不是没法解决,要不我就分分了!
 
问题暂没有解决,但也给分了,不知道能不能提供关于打印方面的资料或网址
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
785
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部