Text formatting with RichEdit [1]

Един от най-добрите начини за динамично форматиране на текст е използването на TRichEdit. Първо искам да ви покажа един интересен метод за началното генериране на RTF-а, който ви осигурява голяма бързина. Идеята е сами да си генерираме RTF документа и след това да го заредим в RichEdit-а. За целта ще си пишем в Rich Text Format, който не е труден за разбиране. Ще се нуждаете от помощта на MSDN (http://msdn.microsoft.com/library/en-us/dnrtfspec/html/rtfspec.asp), за да намирате нужните ви командни думи. Сега ще ви покажа набързо структурата на един RTF документ :

Ето как изглежда целия документ :
{\rtf1\ansi\ansicpg1251\deff0\deflang1026
  {\fonttbl
    {\f0\fswiss\fcharset0 MS Sans Serif;}
    {\f1\fnil\fcharset1251 Arial;}
  }
  {\colortbl
    \red0\green0\blue0;
    \red0\green0\blue255;
  }

  \f0\cf0\fs20
  There is a big shadow over that hill.\par
  It \b might\b0 be d\b\i ue\b0\i0 to the clouds.\par
  \'a4\'eb\u949?\u952?\par
  \highlight1This text's background color is different than\highlight0 this.\par
  {\highlight1This text's background color is different than} this.
}


{ - Започваме с "{". Тeзи скоби се използват за начало и край на файла както и за отделяне на някои елементи

След това е нужно да се въведат някой контролни думи:
\rtf1\ansi\ansicpg1251\deff0\deflang1026 - Значението на всяка от тях можете да проверите в MSDN

{\fonttbl{\f0\fswiss\fcharset0 MS Sans Serif;}{\f1\fnil\fcharset1251 Arial;}} - Таблицата с шрифтовете

{\colortbl\red0\green0\blue0;\red0\green0\blue255;} - Таблицата с цветовете

Следва нашия текст. За инициализация извикваме: първия шрифт от тоблицата, първия цвят от таблицата и нагласяме fontsize на 10 (пише се fontsize * 2)
\f0\cf0\fs20

Сега е време да добавим малко текст
There is a big shadow over that hill.

Форматирането изглежда така. Пред контролна дума се слага "\", а след нея празно място. Ако следва друга контролна дума, празното място се изпуска.
It \b might\b0 be d\b\i ue\b0\i0 to the clouds.

Нов ред се обозначава с (#13 и #10 не се използват)
\par

Други интересни функции:
Извеждане на знаци ASCII код (използват се hex стойности)
\'a4\'eb

!!! За да ползвате Unicode и Highlight е нужно да имате RichEdit v3.0, който е инсталиран по подразби,ане само на Windows 2000/XP. За 9x/ME е нужен ъпдейт richupd.exe (440KB). Този файл трябва да е включен п
ри разпространението на вашата програма.

Извеждане на Unicode знаци
\u949?\u952?

Подчертаване на текст (\highlight + номер на цвят от таблицата)
\highlight1This text's background color is different than\highlight0 this.
или
{\highlight1This text's background color is different than} this.
Отделянето със скоби прекъсва всякакво форматиране!

Все пак разгледайте спецификациите за Rich Text Format в MSDN, за да намерите повече информация за формата.

А сега да започнем с програмирането. За съхранение на нашия RTF мисля да ползваме TStringStream. Ето я нашата процедурка:
procedure ViewRTFText(AText: string);
var
  RTF: TStringStream;
  i: Integer;
  cmd, cyr, num: Boolean;
   ch: Char;
const
   Header =
  '{\rtf1\ansi\ansicpg1251\deff0\deflang1026' +
  '{\fonttbl{\f0\fswiss\fcharset204 %s;}}' +
  '{\colortbl\red%d\green%d\blue%d;' +
    '\red%d\green%d\blue%d;' +
    '\red%d\green%d\blue%d;' +
    '\red%d\green%d\blue%d;}' +
    '\plain\f0\fs%d\cf0\li20';

begin
  RTF := TStringStream.Create('');

   try
    RTF.WriteString(Format(Header, [RichEdit1.Font.Name,
      GetRValue(RichEdit1.Font.Color), GetGValue(RichEdit1.Font.Color), GetBValue(RichEdit1.Font.Color),
      GetRValue(clRed), GetGValue(clRed), GetBValue(clRed),
      GetRValue(clYellow), GetGValue(clYellow), GetBValue(clYellow),
      GetRValue(clWhite), GetGValue(clWhite), GetBValue(clWhite),
      RichEdit1.Font.Size * 2]));

    cyr := false;
    num := false;
    cmd := true;

    for i := 1 to Length(AText) do
    begin
      ch := AText[i];

      //if cyrillic
      if (ch > #191) then
      begin
        if not cyr then
        begin
          cmd := true;
          cyr := true;
          RTF.WriteString('\b\cf1');
        end;
      end
        else begin
          if cyr then
          begin
            cmd := true;
            cyr := false;
            RTF.WriteString('\b0\cf0');
          end;
    end;

    //if number
    if ch in ['0'..'9'] then
    begin
      if not num then
      begin
        cmd := true;
        num := true;
        RTF.WriteString('\ul\highlight2');
      end;
    end
      else begin
        if num then
        begin
          cmd := true;
          num := false;
          RTF.WriteString('\ulnone\highlight3');
        end;
      end;

    //if end of line
    if ch = #13 then
    begin
      cmd := true;
      RTF.WriteString('\par\li50');
    end;

    if (ch <> #13) and (ch <> #10) then
    begin
      if cmd then RTF.WriteString(' ');
      cmd := false;
      if ch < #192 then RTF.WriteString(ch)
        else RTF.WriteString(LowerCase('\''' + IntToHex(Ord(ch), 2)));
    end;
  end;

  RTF.WriteString('}');
  RTF.Seek(0, soFromBeginning);
  RichEdit1.Lines.BeginUpdate;
  RichEdit1.Lines.LoadFromStream(RTF);
  RichEdit1.Lines.EndUpdate;
  finally
    RTF.Free;
  end;

  RichEdit1.SelStart := 0;
  RichEdit1.SelLength := 0;
end;

Тя визуализира подаден й string като извършва следните промени. Ако срещне:
- кирилица - удебелява шрифта и сменя цвета му на червен
- числа - задава курсивен шрифт и сменя цвета на жълт

Ето моя пробен текст :
ViewRTFText('Hello there! Как спа днес.'#13#10 +
'През 2002 year we won the World Cup'#13#10 +
'Bye');


В следващата част ще обясня как най-добре можете да променяте форматирането на текста, докато потребителя работи с вашата програма.

Ако имате някакви коментари или въпроси, ми изпратете един мейл.

Copyright © 2002 Wise Guy
wise_guybg@yahoo.com
Last revised: 06.06.2002