Text formatting with RichEdit [2]

Информацията тук е изцяло взаимствана от статията "Faster rich edit syntax highlighting" на Robert Dunn

Да започваме направо. За да форматираме текста максимално бързо, трябва да изключим всякакви ненужни обработки на събития, които забавят работата ни. Това става като изпратим едно EM_SETEVENTMASK на нашия RichEdit. То се използва за задаване кои съобщения да изпраща RichEdit-а към програмата. Значи казваме на RichEdit-а да не се занимава изобщо с изпращане на MouseMove, MouseClick и т.н. докато работим. Освен това ще кажем на RichEdit-а и да не се прерисува (WM_SETREDRAW) през това време. Ето как изглежда инициализиращия код:

procedure Format(AHandle: THandle);
var
  eventMask: Integer;
begin
  eventMask := SendMessage(AHandle, EM_SETEVENTMASK, 0, 0); //запазваме предишната event mask
  SendMessage(AHandle, WM_SETREDRAW, 0, 0); //изключваме redraw
  ParseAllText(AHandle); //форматиране
  SendMessage(AHandle, WM_SETREDRAW, 1, 0); //включваме redraw
  InvalidateRect(AHandle, nil, true); //прересувай RichEdit-а
  SendMessage(AHandle, EM_SETEVENTMASK, 0, eventMask);//възстановяваме предишната event mask
end;

Когато форматираме текста е най-добре да забравим свойствата на TRichEdit компонента (пр. SelAttributes) и да ползваме съобщения. Така постигаме още по-голямо бързодействие. Ще ви покажа малко примерен код. За съжаление не можах да измисля точно какво да прави и няма някаква реална цел. Поне ще видите как се ползват съобщенията и общата идея на този метод за форматиране на текст.

Процедурата ParseAllText проверява дали селектирания текст е "then" и ако е сменя цвета му на син. Тази процедура е доста безмислена, но ви демонстрира работата с SetTokenColor, която можете да ползвате направо във вашата програма. SetTokenColor прави същинското форматиране. Тя получава Handle към RichEdit-а, участъка от текст и цвета, който трябва да се зададе. Тя наглася нова селекция (текста за форматиране), променя форматирането й и връща началната селекция.

procedure ParseAllText(AHandle: THandle);
var
  chrgSave, chrgSet: TCharRange;
  str: string;
begin
  SendMessage(AHandle, EM_EXGETSEL, 0, LongInt(@chrgSave)); // взимаме размера на селекцията
  SetLength(str, chrgSave.cpMax - chrgSave.cpMin); // инициализираме str
  SendMessage(AHandle, EM_GETSELTEXT, 0, LongInt(PChar(str))); // слагаме селекцията в str
  if str = 'then' then
  begin
    chrgSet.cpMin := chrgSave.cpMin; // инициализираме chrgSet
    chrgSet.cpMax := chrgSave.cpMax;
    SetTokenColor(AHandle, chrgSet, clBlue); // задаваме смяна на цвета
  end;
end;

procedure SetTokenColor(AHandle: THandle; ACharRange: TCharRange; AColor: TColor);
var
  chrgSave: TCharRange;
  cf: TCharFormat;
begin
  SendMessage(AHandle, EM_EXGETSEL, 0, LongInt(@chrgSave)); // запазваме текущата селекция
  SendMessage(AHandle, EM_EXSETSEL, 0, LongInt(@ACharRange)); // нагласяме участъка за промяна
  cf.dwMask := CFM_COLOR; // инициализираме cf
  cf.crTextColor := AColor;
  cf.dwEffects := CFM_BOLD;
  cf.cbSize := SizeOf(cf);
  SendMessage(AHandle, EM_SETCHARFORMAT, SCF_SELECTION, LongInt(@cf)); // задаваме новия формат
  SendMessage(AHandle, EM_EXSETSEL, 0, LongInt(@chrgSave)); // връщаме селекцията
end;

Е надявам се разбрахте как оптимално можете да форматирате текст в RichEdit. Вече можете да се пробвате да направите собствен parser :-)

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

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