procedure Bresenham_Line(Image:TImage;x0,y0,x1,y1:Integer); var i,p,dx,dy,s0,s1,x,y:Integer; isChanged:Boolean; begin dx:=Abs(x1-x0); dy:=Abs(y1-y0); s0:=Sign(x1-x0); s1:=Sign(y1-y0); x:=x0; y:=y0; if dy>dx then begin i:=dy; dy:=dx; dx:=i; isChanged:=true; end else isChanged:=false;
p:=2*dy-dx; for i:=1 to dx do begin Image.Canvas.Pixels[x,y]:=clRed; if P>=0 then begin if isChanged then x:=x+s0 else y:=y+s1; p:=p-2*dx; end; if isChanged then y:=y+s1 else x:=x+s0; p:=p+2*dy; end; end;
TQShape控件,使用该控件可以画出列与列之间的竖线,但如果用户不能正确地调整TQShape实例的高度,输出报表中的竖线不是不
连续就是超长,另外如果我们调整了某个Band的高度,我们将不得不调整该Band下的所有TQShape实例的高度;至于斜线,
QuickReport报表组件根本就没有提供这一功能。
解决思路
以TQShape为父类,建立新的控件,新控件可以画竖线、斜线和反斜线。
重载TQShape 类的Paint方法,这样在设计阶段可以非常直观地画坚线、斜线和反斜线。用户可以在设计阶段选择线的类型,
如果选择直线,控件自动将其高度调整为所属Band的高度,用户可以调整其横向位置但不能调整其高度;如果选择斜线,用户可以
根据需要调整斜线的长度和倾角。
重载TQShape 类的Print方法,这样可以在运行阶段输出直线和斜线。
说明:该控件只能画直线和斜线,如果读者需要画矩形和圆,可以使用TQShape控件来实现。
控件设计步骤
步骤1.使用Delphi提供的控件向导,选择TQShape为父类,建立新类TMyQRShape,并选择适当的包(Package),最后生成单元文件。
步骤2.在生成的单元文件中,增加枚举类型。
TLines = ( None,TopBottom,BottomTop ) ;None、TopBottom、BottomTop三种取值,分别代表直线、斜线 \ 和反斜线 /。
步骤3.在新类TMyQRShape 中增加private 成员 FLineType:TLines ,增加published属性 LineType:TLines Read
FLineType Write SetFLineType。
步骤4.建立过程SetFLineType。
procedure
TMyQRShape.SetFLineType(Value:TLines);
begin
if Value<>FLineType then
begin
FLineType:=Value ;
Invalidate ;
end ;
end ;
步骤5.重载Paint方法。
procedure TMyQRShape.Paint ;
begin
case LineType of
BottomTop:
begin
Canvas.MoveTo(0,Height) ;
Canvas.LineTo(width,0 ) ;
end ;
TopBottom:
begin
Canvas.MoveTo(0,0) ;
Canvas.LineTo(width,Height ) ;
end ;
None:
begin
Height := Parent.Height ;
Top:=0 ;
Width:=4 ;
Shape:=qrsVertLine ;
Inherited Paint ;
end ;
end ;
end ;
步骤6.重载Print方法。
procedure TMyQRShape.Print(OfsX,OfsY : Integer);
begin
with QRPrinter do
begin
case LineType of
BottomTop:
begin
Canvas.MoveTo(XPos(OfsX + Size.Left), YPos(OfsY + Size.Top)+Height) ;
Canvas.LineTo(XPos(OfsX + Size.Left)+width,YPos(OfsY + Size.Top) ) ;
end ;
TopBottom:
begin
Canvas.MoveTo(XPos(OfsX + Size.Left), YPos(OfsY + Size.Top)) ;
Canvas.LineTo(XPos(OfsX + Size.Left)+Width,YPos(OfsY + Size.Top)+Height ) ;
end ;
None:
Inherited Print(OfsX,OfsY ) ;
end ;
end ;
end;
步骤7.保存并安装TMyQRShape控件。
该控件的完整代码如下:
源程序:
unit MyQRShape;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics,
Controls, Forms, Dialogs,
QuickRpt, Qrctrls;
type
TLines = ( None,TopBottom,BottomTop ) ;
TMyQRShape = class(TQRShape)
private
FLineType:TLines ;
procedure SetFLineType(Value:TLines) ;
protected
procedure Print(OfsX, OfsY : integer); override;
procedure Paint ;Override ;
public
published
property LineType:TLines Read FLineType Write SetFLineType ;
end;
procedure Register;
implementation
procedure
TMyQRShape.SetFLineType(Value:TLines);
begin
if Value<>FLineType then
begin
FLineType:=Value ;
Invalidate ;
end ;
end ;
procedure TMyQRShape.Paint ;
begin
case LineType of
BottomTop:
begin
Canvas.MoveTo(0,Height) ;
Canvas.LineTo(width,0 ) ;
end ;
TopBottom:
begin
Canvas.MoveTo(0,0) ;
Canvas.LineTo(width,Height ) ;
end ;
None:
begin
Height := Parent.Height ;
Top:=0 ;
Width:=4 ;
Shape:=qrsVertLine ;
Inherited Paint ;
end ;
end ;
end ;
procedure TMyQRShape.Print(OfsX,OfsY : Integer);
begin
with QRPrinter do
begin
case LineType of
BottomTop:
begin
Canvas.MoveTo(XPos(OfsX + Size.Left), YPos(OfsY + Size.Top)+Height) ;
Canvas.LineTo(XPos(OfsX + Size.Left)+width,YPos(OfsY + Size.Top) ) ;
end ;
TopBottom:
begin
Canvas.MoveTo(XPos(OfsX + Size.Left), YPos(OfsY + Size.Top)) ;
Canvas.LineTo(XPos(OfsX + Size.Left)+Width,YPos(OfsY + Size.Top)+Height ) ;
end ;
None:
Inherited Print(OfsX,OfsY ) ;
end ;
end ;
end;
procedure Register;
begin
RegisterComponents(‘QReport', [TMyQRShape]);
end;
end.
to:wave_calmly(静波)
你推荐的这方法有否试验成功过?可行吗?我想试,你不告诉也行。
我没有试过
very 好用
qrimage1.Canvas.MoveTo(0,0);
qrimage1.Canvas.LineTo(qrimage1.Width,qrimage1.Height);或者Bresenham直线画法:从(x0,y0)到(x1,y1)
procedure Bresenham_Line(Image:TImage;x0,y0,x1,y1:Integer);
var
i,p,dx,dy,s0,s1,x,y:Integer;
isChanged:Boolean;
begin
dx:=Abs(x1-x0);
dy:=Abs(y1-y0);
s0:=Sign(x1-x0);
s1:=Sign(y1-y0);
x:=x0;
y:=y0;
if dy>dx then
begin
i:=dy;
dy:=dx;
dx:=i;
isChanged:=true;
end
else
isChanged:=false;
p:=2*dy-dx;
for i:=1 to dx do
begin
Image.Canvas.Pixels[x,y]:=clRed;
if P>=0 then
begin
if isChanged then
x:=x+s0
else
y:=y+s1;
p:=p-2*dx;
end;
if isChanged then
y:=y+s1
else
x:=x+s0;
p:=p+2*dy;
end;
end;