我有下面这样一句话,
“扬州西北绕城高速公路 扬州西互通NK1+100~NK1+578.007 95区路基填筑工程检验认可书、工程报验单及附件”
被打印成:
扬州西北绕城高速公路
扬州西互通NK1+100~NK1+578.007 95区路基填筑
工程检验认可书、工程报验单及附件
很明显第二行的开始几个汉字应该可以打印在第一行上。为此我查看了FastReport和ReportMachine,做了些小修改,希望大家共同研究。
//=============================================================================//
// 修改FastReport 2.52中汉字和英文混合时候断行有错误的问题 //
// Leon,2004-04-18 //
// 位于TfrMemoView.WarpMemo方法中 //
//=============================================================================//
type
TWordBreaks = String;const
gl: set of Char = ['?, '?, '?, '?, '?, '?, '?, '?, '?, '?];
r_sogl: set of Char = ['?, '?];
spaces: set of Char = [' ', '.', ',', '~', '+', '-', '*', '/'];//对BreakWord方法的更改
function BreakWord(s: String): TWordBreaks;
var
i: Integer;
CanBreak: Boolean;
begin
Result := '';
s := AnsiUpperCase(s);
if Length(s) >= 4 then
begin
i := 2;
repeat
CanBreak := False;
if s[i] in gl then
begin
if (s[i + 1] in gl) or (s[i + 2] in gl) then CanBreak := True;
end
else
if (s[i] in r_sogl) and (not(s[i+2] in spaces)) then
begin
CanBreak := True;
end
else
begin
if not (s[i + 1] in gl) and not (s[i + 1] in r_sogl) and
(s[i + 2] in gl) then
CanBreak := True;
end;
// ---> Leon, 2004-08-08
if windows.isDBCSLeadByte(Byte(s[i])) then
CanBreak := True;
// <-- //if CanBreak then
// Result := Result + Chr(i);
//Inc(i); // --> Leon, 2004-08-18
if CanBreak then
If windows.isDBCsLeadByte(Byte(s[i])) then
begin
Result := Result + Chr(i+1);
Inc(i);
end
else
Result := Result + Chr(i);
Inc(i);
// <--
until i > Length(s) - 2;
end;
end;
//----------------------------------------------------------------------------//
// 修改双字节时候的折行问题,LEON,2004-08-18 //
//----------------------------------------------------------------------------////对 TfrMemoView.WrapMemo方法中WrapLine方法的更改: procedure WrapLine(const s: String);
var
i, cur, beg, last, LoopPos, icount: Integer;
WasBreak, CRLF: Boolean;
sSub: String;
begin
CRLF := False;
LoopPos := 0;
for i := 1 to Length(s) do
if s[i] in [#10, #13] then
begin
CRLF := True;
break;
end; //初始化
beg := 1; last := 1; icount := 1; if not CRLF and ((Length(s) <= 1) or (WCanvas.TextWidth(s) <= maxwidth)) then
OutLine(s + #1)
else
begin //-- 要打印的字符串宽度超过Memo的显示宽度 --//
cur := 1;
while cur <= Length(s) do
begin
// (1) 有回车、回车换行,则下移
if s[cur] in [#10, #13] then
begin
OutLine(Copy(s, beg, cur - beg) + #1);
while (cur < Length(s)) and (s[cur] in [#10, #13]) do Inc(cur);
beg := cur; last := beg;
if s[cur] in [#13, #10] then
Exit
else
continue;
end; // (2) 没有空格
if s[cur] <> ' ' then
begin
// --> Leon,2004-04-18,判断是中文时计算宽度要以中文计算
sSub := '';
if windows.isDBCSLeadByte(byte(s[cur])) then
sSub := Copy(s, beg, cur - beg + 2)
else
sSub := Copy(s, beg, cur - beg + 1);
// <--
//if WCanvas.TextWidth(Copy(s, beg, cur - beg + 1)) > maxwidth then
// --> Leon,2004-04-18,修正过的长度校验
if WCanvas.TextWidth(sSub) > maxwidth then
begin
WasBreak := False;
if (Flags and flWordBreak) <> 0 then //断单字
begin
i := cur;
while (i <= Length(s)) and not (s[i] in spaces) do
Inc(i);
b := BreakWord(Copy(s, last + 1, i - last - 1));
if Length(b) > 0 then
begin
i := 1;
cur := last;
while (i <= Length(b)) and
(WCanvas.TextWidth(Copy(s, beg, last - beg + 1 + Ord(b[i])) + '-') <= maxwidth) do
begin
WasBreak := True;
cur := last + Ord(b[i]);
Inc(i);
end;
last := cur;
end;
end
else begin
// --> Leon,2004-04-18,
//当宽度已超过可打印宽度、当前为中文字符时,倒退一个中文字符
if windows.isDBCSLeadByte(Byte(s[cur])) then
begin
WasBreak := True;
last := cur-1;
end;
// <--
if last = beg then last := cur;
end; //如果要断单词
if WasBreak then
//OutLine(Copy(s, beg, last - beg + 1) + '-')
// --> Leon,2004-08-18,增加对双字节的检验
If windows.isDBCSLeadByte(Byte(s[cur])) then
OutLine(Copy(s, beg, last - beg +1))
else
OutLine(Copy(s, beg, last - beg + 1) + '-')
// <--
else if s[last] = ' ' then
OutLine(Copy(s, beg, last - beg))
else
begin
if last = beg then last := cur;
OutLine(Copy(s, beg, last - beg));
Dec(last);
end;
if ((Flags and flWordBreak) <> 0) and not WasBreak and (last = cur - 1) then
begin
if LoopPos = cur then
begin
beg := cur + 1;
cur := Length(s);
break;
end
else
LoopPos := cur;
end;
beg := last + 1; last := beg;
end
// --> Leon,2004-04-08
else begin
//单字节和双字节之间要断开
if not windows.isDBCSLeadByte(byte(s[cur])) then
begin
if (cur-2)>0 then
begin
If windows.isDBCSLeadByte(byte(s[cur-2])) then
begin
WasBreak := True;
last := cur;
end;
end;
end;
end;
// <--
end; // (3) 有空格
if s[cur] in spaces then last := cur;
if s[cur] = ' ' then
begin
if windows.isDBCSLeadByte(byte(s[cur])) then
last := cur + 1
else
last := cur;
end; {$IFNDEF Delphi2}
if windows.isDBCSLeadByte(byte(s[cur])) then //Leon, 2004-08-18
//if ByteType(s, cur) = mbLeadByte then
Inc(cur, 2)
else
{$ENDIF}
Inc(cur);
end; if beg <> cur then
OutLine(Copy(s, beg, cur - beg + 1) + #1);
end;
end;
“扬州西北绕城高速公路 扬州西互通NK1+100~NK1+578.007 95区路基填筑工程检验认可书、工程报验单及附件”
被打印成:
扬州西北绕城高速公路
扬州西互通NK1+100~NK1+578.007 95区路基填筑
工程检验认可书、工程报验单及附件
很明显第二行的开始几个汉字应该可以打印在第一行上。为此我查看了FastReport和ReportMachine,做了些小修改,希望大家共同研究。
//=============================================================================//
// 修改FastReport 2.52中汉字和英文混合时候断行有错误的问题 //
// Leon,2004-04-18 //
// 位于TfrMemoView.WarpMemo方法中 //
//=============================================================================//
type
TWordBreaks = String;const
gl: set of Char = ['?, '?, '?, '?, '?, '?, '?, '?, '?, '?];
r_sogl: set of Char = ['?, '?];
spaces: set of Char = [' ', '.', ',', '~', '+', '-', '*', '/'];//对BreakWord方法的更改
function BreakWord(s: String): TWordBreaks;
var
i: Integer;
CanBreak: Boolean;
begin
Result := '';
s := AnsiUpperCase(s);
if Length(s) >= 4 then
begin
i := 2;
repeat
CanBreak := False;
if s[i] in gl then
begin
if (s[i + 1] in gl) or (s[i + 2] in gl) then CanBreak := True;
end
else
if (s[i] in r_sogl) and (not(s[i+2] in spaces)) then
begin
CanBreak := True;
end
else
begin
if not (s[i + 1] in gl) and not (s[i + 1] in r_sogl) and
(s[i + 2] in gl) then
CanBreak := True;
end;
// ---> Leon, 2004-08-08
if windows.isDBCSLeadByte(Byte(s[i])) then
CanBreak := True;
// <-- //if CanBreak then
// Result := Result + Chr(i);
//Inc(i); // --> Leon, 2004-08-18
if CanBreak then
If windows.isDBCsLeadByte(Byte(s[i])) then
begin
Result := Result + Chr(i+1);
Inc(i);
end
else
Result := Result + Chr(i);
Inc(i);
// <--
until i > Length(s) - 2;
end;
end;
//----------------------------------------------------------------------------//
// 修改双字节时候的折行问题,LEON,2004-08-18 //
//----------------------------------------------------------------------------////对 TfrMemoView.WrapMemo方法中WrapLine方法的更改: procedure WrapLine(const s: String);
var
i, cur, beg, last, LoopPos, icount: Integer;
WasBreak, CRLF: Boolean;
sSub: String;
begin
CRLF := False;
LoopPos := 0;
for i := 1 to Length(s) do
if s[i] in [#10, #13] then
begin
CRLF := True;
break;
end; //初始化
beg := 1; last := 1; icount := 1; if not CRLF and ((Length(s) <= 1) or (WCanvas.TextWidth(s) <= maxwidth)) then
OutLine(s + #1)
else
begin //-- 要打印的字符串宽度超过Memo的显示宽度 --//
cur := 1;
while cur <= Length(s) do
begin
// (1) 有回车、回车换行,则下移
if s[cur] in [#10, #13] then
begin
OutLine(Copy(s, beg, cur - beg) + #1);
while (cur < Length(s)) and (s[cur] in [#10, #13]) do Inc(cur);
beg := cur; last := beg;
if s[cur] in [#13, #10] then
Exit
else
continue;
end; // (2) 没有空格
if s[cur] <> ' ' then
begin
// --> Leon,2004-04-18,判断是中文时计算宽度要以中文计算
sSub := '';
if windows.isDBCSLeadByte(byte(s[cur])) then
sSub := Copy(s, beg, cur - beg + 2)
else
sSub := Copy(s, beg, cur - beg + 1);
// <--
//if WCanvas.TextWidth(Copy(s, beg, cur - beg + 1)) > maxwidth then
// --> Leon,2004-04-18,修正过的长度校验
if WCanvas.TextWidth(sSub) > maxwidth then
begin
WasBreak := False;
if (Flags and flWordBreak) <> 0 then //断单字
begin
i := cur;
while (i <= Length(s)) and not (s[i] in spaces) do
Inc(i);
b := BreakWord(Copy(s, last + 1, i - last - 1));
if Length(b) > 0 then
begin
i := 1;
cur := last;
while (i <= Length(b)) and
(WCanvas.TextWidth(Copy(s, beg, last - beg + 1 + Ord(b[i])) + '-') <= maxwidth) do
begin
WasBreak := True;
cur := last + Ord(b[i]);
Inc(i);
end;
last := cur;
end;
end
else begin
// --> Leon,2004-04-18,
//当宽度已超过可打印宽度、当前为中文字符时,倒退一个中文字符
if windows.isDBCSLeadByte(Byte(s[cur])) then
begin
WasBreak := True;
last := cur-1;
end;
// <--
if last = beg then last := cur;
end; //如果要断单词
if WasBreak then
//OutLine(Copy(s, beg, last - beg + 1) + '-')
// --> Leon,2004-08-18,增加对双字节的检验
If windows.isDBCSLeadByte(Byte(s[cur])) then
OutLine(Copy(s, beg, last - beg +1))
else
OutLine(Copy(s, beg, last - beg + 1) + '-')
// <--
else if s[last] = ' ' then
OutLine(Copy(s, beg, last - beg))
else
begin
if last = beg then last := cur;
OutLine(Copy(s, beg, last - beg));
Dec(last);
end;
if ((Flags and flWordBreak) <> 0) and not WasBreak and (last = cur - 1) then
begin
if LoopPos = cur then
begin
beg := cur + 1;
cur := Length(s);
break;
end
else
LoopPos := cur;
end;
beg := last + 1; last := beg;
end
// --> Leon,2004-04-08
else begin
//单字节和双字节之间要断开
if not windows.isDBCSLeadByte(byte(s[cur])) then
begin
if (cur-2)>0 then
begin
If windows.isDBCSLeadByte(byte(s[cur-2])) then
begin
WasBreak := True;
last := cur;
end;
end;
end;
end;
// <--
end; // (3) 有空格
if s[cur] in spaces then last := cur;
if s[cur] = ' ' then
begin
if windows.isDBCSLeadByte(byte(s[cur])) then
last := cur + 1
else
last := cur;
end; {$IFNDEF Delphi2}
if windows.isDBCSLeadByte(byte(s[cur])) then //Leon, 2004-08-18
//if ByteType(s, cur) = mbLeadByte then
Inc(cur, 2)
else
{$ENDIF}
Inc(cur);
end; if beg <> cur then
OutLine(Copy(s, beg, cur - beg + 1) + #1);
end;
end;
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货