Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Выравнивание текста по ширине как в Worde


Текст выглядит лучше, если он выровнен по двух краям. Для этого пробелы в каждой строке нужно удлинять или укорачивать так, чтобы все строки имели одну длину.

Здесь создана процедура GetLine, которая возвращает одну строку, начиная с заданного символа. Программа находит разницу между шириной текста и реальной длинной строки и при выводе компенсирует эту разницу удлинением пробелов.

Эта программа выводит на экран текст из файла C:\text.txt, выравнивая его по двум краям.


type
  ...
  TLine = record
    s: string;
    wrap: boolean;
    length: integer;
end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

const
  FileName = 'C:\text.txt';

var
  s: string;
  bm: TBitMap;
  LineH: integer;
  MaxTextWidth: integer;

procedure TForm1.FormCreate(Sender: TObject);
var
  F: TFileStream;
  buf: array [0..127] of char;
  l: integer;
begin
  ScrollBar1.Kind := sbVertical;
  bm := TBitMap.Create;
  with bm.Canvas.Font do
  begin
    name := 'Serif';
    Size := 12;
  end;
  LineH := bm.Canvas.TextHeight('123');

  if not FileExists(FileName) then
  begin
    ShowMessage('Can not find file ' + FileName);
    Exit;
  end;
  F := TFileStream.Create(FileName, fmOpenRead);
  repeat
    l := F.read(buf, 128);
    if l = 128 then
      s := s + buf
    else
      s := s + copy(buf, 1, l);
  until
    l < 128;
  F.Destroy;
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  PaintBox1.Left := 0;
  PaintBox1.Top := 0;
  PaintBox1.Height := Form1.ClientHeight;
  PaintBox1.Width := Form1.ClientWidth - ScrollBar1.Width;
  ScrollBar1.Left := PaintBox1.Width;
  ScrollBar1.Top := 0;
  ScrollBar1.Height := PaintBox1.Height;
  bm.Width := PaintBox1.Width;
  bm.Height := PaintBox1.Height;
  ScrollBar1.Max := 1000;
  MaxTextWidth := PaintBox1.Width - 20;
end;

function RealTextWidth(s: string): integer;
var
  i: integer;
begin
  result := bm.Canvas.TextWidth(s);
  for i := 1 to Length(s) do
    if s[i] = #9 then
      inc(result, 40 - bm.Canvas.TextWidth(#9));
end;

function GetLine(index: integer): TLine;
var
  i: integer;
  s1: string;
  first: integer;
begin
  if (s[index] = #13) and (s[index + 1] = #10) then
  begin
    result.s := '';
    result.length := 2;
    result.wrap := true;
    Exit;
  end;
  first := index;
  while (first <= Length(s)) and (s[first] in [#32]) do
    inc(first);
  i := first;
  repeat
    while (i <= Length(s)) and (not (s[i] in [#9, #32])) and (s[i] <> #13) do
      inc(i);
    s1 := copy(s, first, i - index);
    inc(i);
  until
    (i >= Length(s)) or (s[i-1] = #13) or (RealTextWidth(s1) > MaxTextWidth);
  if RealTextWidth(s1) > MaxTextWidth then
  begin
    result.wrap := false;
    if i < Length(s) then
    begin
      dec(i, 2);
      while (i > 0) and (not (s[i] in [#9, #32])) do
        dec(i);
      result.Length := i - index;
      while (i > 0) and (s[i] in [#9, #32]) do
        dec(i);
    end;
    result.s := copy(s, first, i - index + 1);
    if result.s[length(result.s)] = #32 then
      delete(result.s, length(result.s) , 1);
  end
  else
  begin
    result.length := i - index + 1;
    s1 := copy(s, first, i - index + 1);
    if length(s1) > 0 then
    begin
      if s1[Length(s1)] = #9 then
        delete(s1, Length(s1), 1);
      if s1[length(s1) - 1] + s1[length(s1)] = #13#10 then
        delete(s1, length(s1) - 1, 2);
    end;
    result.s := s1;
    result.wrap := true;
  end;
end;


procedure draw;
var
  i, j: integer;
  line: TLine;
  OneWord: string;
  LineN: integer;
  SpaceCount: integer;
  TextLeft: integer;
  shift, allshift: integer;
  d: integer;
  LineCount: integer;
begin
  with bm.Canvas do
  begin
    FillRect(ClipRect);
    i := 1;
    LineCount := 0;
    for j := 1 to Form1.ScrollBar1.Position do
    begin
      line := GetLine(i);
      inc(i, line.length);
      inc(LineCount);
    end;
    LineN := 0;
    repeat
      line := GetLine(i);
      SpaceCount := 0;
      TextLeft := 0;
      for j := 1 to Length(line.s) do
        if line.s[j] = #32 then
          inc(SpaceCount);
      if line.wrap = false then
        allshift := MaxTextWidth - RealTextWidth(line.s)
      else
        allshift := 0;
      if allshift > 40 * SpaceCount then
        allshift := 0;
      shift := 0;
      for j := 1 to Length(line.s) do
      begin
        if (not (line.s[j] in [#9, #32])) and (j < Length(line.s)) then
        begin
          OneWord := OneWord + line.s[j];
        end
        else
        begin
          OneWord := OneWord + line.s[j];
          if OneWord = #9 then
          begin
            inc(TextLeft, 40);
          end
          else
          begin
            if OneWord = #13#10 then
            begin
              inc(LineN);
            end
            else
            begin
              TextOut(10 + TextLeft, LineN * LineH, OneWord);
              if SpaceCount = 0 then
                d := 0
              else
                d := (allshift - shift) div (SpaceCount);
              inc(shift, d);
              inc(TextLeft, TextWidth(OneWord) + d);
              dec(SpaceCount);
            end;
          end;
          OneWord := '';
        end;
      end;
      inc(i, line.length);
      inc(LineN);
    until
      (LineN * LineH > Form1.PaintBox1.Height) or (i >= Length(s));

    repeat
      line := GetLine(i);
      inc(i, line.length);
      inc(LineCount);
    until
      i >= Length(s);

    inc(LineCount, LineN);
    Form1.ScrollBar1.Max := LineCount -
    Form1.PaintBox1.Height div LineH;
  end;
  Form1.PaintBox1.Canvas.Draw(0, 0, bm);
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  draw;
end;

procedure TForm1.ScrollBar1Change(Sender: TObject);
begin
  draw;
end;

Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay