您的位置:首页 > 其它

FastReport 4.7 的两个BUG及修复方法

2009-06-03 22:31 381 查看
现在做的一个项目,需要涉及到打印,所以选择了FASTREPORT。网上下的FOR DELPHI2009是有源代码的,用起来还是不错,我前面的BLOG中已经写了几个封装的功能,用了下还是比较爽的。

但是发现几个问题。

项目需要打印一个很大篇幅的文章,文章内容放在一个数据库的TEXT字段中,内容大小又不一样,大的可能需要用好几十页纸才能打完,小的可能只有几个字,并且每行打印的时候都要求要下划先,如果一行文字中间折行的,整行需要加下划线。

效果如下:





用FASTREPORT设计还是比较简单的,直接把这个字段拖进来就好了,然后设置这个MemoView的StretchMode为smActualHeight,这样就可以打印多行了,然后设置UnderLines为True就可以打印的时候有下划线了。然后设置一下字体和LineSpacing就可以了。

但是运行后发现两个问题:

1.设置UnderLines属性后,最后一行的下划线有时候会打印出来,有时候又不打印。

2.文章内容,如果超过一页,文章的最后一行也是有时候会打出来,有时候又打不出来。

网上下了几个版本,都存在这个问题,并且官方网站也没有提起,没办法,只能自己去研究FASTREPORT的代码了。

最开始认为这两个问题是同一个问题,经过分析发现是不同的两个BUG。

先研究下划线问题。

这个问题比较简单,先找到frxClass单元中的TfrxCustomMemoView的Draw方法,专门有一个函数DrawUnderlines;是用于划下划线的,中间有一段循环:

    dy := FY + h + (GapY - LineSpacing + 1) * ScaleY;
    while dy < FY1 do
    begin
      Canvas.MoveTo(FX, Round(dy));
      Canvas.LineTo(FX1, Round(dy));

。。。。

这个代码中循环的判断while dy < FY1 do是有问题的。他并没有考虑最后一行的情况,修改如下:

    h := FDrawText.LineHeight * ScaleY;
    dy := FY + h + (GapY - LineSpacing + 1) * ScaleY;
    //hl changed  20090602
    while dy < (FY1 + Trunc(LineSpacing/2) ) do
//    while dy < FY1 do
    begin
      Canvas.MoveTo(FX, Round(dy));
      Canvas.LineTo(FX1, Round(dy));

 

OK,问题解决。

最后一行有可能不打印的问题就麻烦了。要去研究整个FASTREPORT的运行机制。折腾到凌晨一点多,基本有点眉目了。

原因在于计算行高的时候,没考虑到最后一行是不需要计算LineSpacing的情况。

错误代码如下:

function TfrxDrawText.GetOutBoundsText(var ParaBreak: Boolean): WideString;
var
  PrnSz: Integer;
  n, vl, Ln: Integer;
  ratio: Extended;
  Tag: TfrxHTMLTags;
  cl: LongInt;
begin
  ParaBreak := False;
  Result := '';
  n := FText.Count;
  if n = 0 then Exit;

  FCanvas.Lock;
  try
    PrnSz := -FCanvas.Font.Height;
    ratio := FDefPPI / FScrPPI;

  // number of lines that will fit in the bounds
    vl := Trunc((FOriginalRect.Bottom - FOriginalRect.Top + 1) / (PrnSz / ratio + FLineSpacing));--这里是有问题的

修改为:

function TfrxDrawText.GetOutBoundsText(var ParaBreak: Boolean): WideString;
var
  PrnSz: Integer;
  n, vl, Ln: Integer;
  ratio: Extended;
  Tag: TfrxHTMLTags;
  cl: LongInt;
begin
  ParaBreak := False;
  Result := '';
  n := FText.Count;
  if n = 0 then Exit;

  FCanvas.Lock;
  try
    PrnSz := -FCanvas.Font.Height;
    ratio := FDefPPI / FScrPPI;

  // number of lines that will fit in the bounds
    vl := Trunc((FOriginalRect.Bottom - FOriginalRect.Top + 1) / (PrnSz / ratio + FLineSpacing));
    //hl changed 20090603
    if ((FOriginalRect.Bottom - FOriginalRect.Top + 1) - vl * (PrnSz / ratio + FLineSpacing)) >= (PrnSz / ratio) then
      Inc(vl);

 

然后再修改计算剩余高度的代码。修改方法同上。

OK,问题解决。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: