Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Раскраска TRichEdit'a [D7, WinXP]


ircnoob ©   (2006-03-04 12:20:00) 

В общем, пишу свой жутко простенький IRC-чат. Решил разобраться со стилями шрифта / цветом в главном окне вывода информации на базе TRichEdit'a.

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

У кого есть немного времени и желание помочь мне разобраться в проблеме? )

type
 TIRCTextAttribCode = (taColor, taBold, taUnderline);

 TStyleQuote = record
  StartPos: Integer;
  EndPos: Integer;
  Color: TColor;
 end;

 TSQArray = array of TStyleQuote;

const
 AttribCodes: array [TIRCTextAttribCode] of Char =
  (
    #3, // Color
    #2, // Bold
    #31 // Underline
  );

procedure TVisualChannel.AddIRCLine(const AText: String);
var
PB: Integer;
ALine: String;
i: Integer;
//--
SQArrayC: TSQArray; SQArrayCC: Integer; IsOpenedC: Boolean;
SQArrayB: TSQArray; SQArrayBC: Integer; IsOpenedB: Boolean;
SQArrayU: TSQArray; SQArrayUC: Integer; IsOpenedU: Boolean;
SColor: String;
begin
// добавляем время в формате '[hh:mm:ss] '+AText
ALine:=AddTimeStamp(AText);
PB:=0;
for i:=0 to FFrame.edIRCChat.Lines.Count-1 do
 PB:=PB+Length(FFrame.edIRCChat.Lines[i]);

i:=1;
IsOpenedC:=False; SQArrayCC:=0;
IsOpenedB:=False; SQArrayBC:=0;
IsOpenedU:=False; SQArrayUC:=0;
while i<>Length(ALine) do
begin
 if ALine[i]=AttribCodes[taBold] then
 begin
  if IsOpenedB then
  begin
   IsOpenedB:=False;
   Delete(ALine,i,1);
   SQArrayB[High(SQArrayB)].EndPos:=i+PB-1;
  end else
  begin
   IsOpenedB:=True;
   Inc(SQArrayBC);
   SetLength(SQArrayB,SQArrayBC);
   Delete(ALine,i,1);
   SQArrayB[High(SQArrayB)].StartPos:=i+PB;
  end;
 end;
 if ALine[i]=AttribCodes[taUnderline] then
 begin
  if IsOpenedU then
  begin
   IsOpenedU:=False;
   Delete(ALine,i,1);
   SQArrayU[High(SQArrayU)].EndPos:=i+PB-1;
  end else
  begin
   IsOpenedU:=True;
   Inc(SQArrayUC);
   SetLength(SQArrayU,SQArrayUC);
   Delete(ALine,i,1);
   SQArrayU[High(SQArrayU)].StartPos:=i+PB;
  end;
 end;
 if ALine[i]=AttribCodes[taColor] then
 begin
  if IsOpenedC then
  begin
   IsOpenedC:=False;
   Delete(ALine,i,3);
   SQArrayC[High(SQArrayC)].EndPos:=i+PB-1;
  end else
  begin
   IsOpenedC:=True;
   Inc(SQArrayCC);
   SetLength(SQArrayC,SQArrayCC);
   SColor:=Copy(ALine,i+1,2);
   if SColor='00' then SQArrayC[High(SQArrayC)].Color:=clWhite;
   if SColor='01' then SQArrayC[High(SQArrayC)].Color:=clBlack;
   if SColor='02' then SQArrayC[High(SQArrayC)].Color:=clNavy;
   if SColor='03' then SQArrayC[High(SQArrayC)].Color:=clRed;
   if SColor='04' then SQArrayC[High(SQArrayC)].Color:=clMaroon;  // brown
   if SColor='05' then SQArrayC[High(SQArrayC)].Color:=clPurple;
   if SColor='06' then SQArrayC[High(SQArrayC)].Color:=clYellow;  // orange
   if SColor='07' then SQArrayC[High(SQArrayC)].Color:=clYellow;
   if SColor='08' then SQArrayC[High(SQArrayC)].Color:=clLime;
   if SColor='10' then SQArrayC[High(SQArrayC)].Color:=clTeal;
   if SColor='11' then SQArrayC[High(SQArrayC)].Color:=clAqua;
   if SColor='12' then SQArrayC[High(SQArrayC)].Color:=clBlue;
   if SColor='13' then SQArrayC[High(SQArrayC)].Color:=clFuchsia;
   if SColor='14' then SQArrayC[High(SQArrayC)].Color:=clGray;
   if SColor='15' then SQArrayC[High(SQArrayC)].Color:=clSilver;
   Delete(ALine,i,3);
   SQArrayC[High(SQArrayC)].StartPos:=i+PB;
  end;
 end;
 Inc(i);
end;

edIRCChat.Lines.Add(ALine);

for i:=Low(SQArrayC) to High(SQArrayC) do
begin
 edIRCChat.SelStart:=SQArrayC[i].StartPos;
 edIRCChat.SelLength:=SQArrayC[i].EndPos-SQArrayC[i].StartPos;
 edIRCChat.SelAttributes.Color:=SQArrayC[i].Color;
end;
for i:=Low(SQArrayB) to High(SQArrayB) do
begin
 edIRCChat.SelStart:=SQArrayB[i].StartPos;
 edIRCChat.SelLength:=SQArrayB[i].EndPos-SQArrayB[i].StartPos;
 edIRCChat.SelAttributes.Style:=edIRCChat.SelAttributes.Style+[fsBold];
end;
for i:=Low(SQArrayU) to High(SQArrayU) do
begin
 edIRCChat.SelStart:=SQArrayU[i].StartPos;
 edIRCChat.SelLength:=SQArrayU[i].EndPos-SQArrayU[i].StartPos;
 edIRCChat.SelAttributes.Style:=edIRCChat.SelAttributes.Style+[fsUnderline];
end;

SetLength(SQArrayC,0);
SetLength(SQArrayB,0);
SetLength(SQArrayU,0);

edIRCChat.SelStart:=Length(edIRCChat.Lines.Text);
edIRCChat.SelLength:=0;
end;


Заранее спасибо, если кто найдется желающий помочь )


ircnoob   (2006-03-05 10:24:00) [1]

слушайте, я запутался ( посоветуйте что-нить толковое, а?...


ircnoob   (2006-03-04 19:09:00) [2]

PB := edIRCChat.GetTextLen

всегда возвращает 0, в отличии от моего предыдущего варианта. вот в чем трабла -) но вопрос остается открытым. если это можно назвать вопросом )


ircnoob   (2006-03-04 18:49:00) [3]

забыл по глупости выделить измененные моменты. простите:

procedure TVisualChannel.AddIRCLine(const AText: String);
var
PB: Integer;
ALine: String;
i: Integer;
//--
SQArrayC: TSQArray; SQArrayCC: Integer; IsOpenedC: Boolean;
SQArrayB: TSQArray; SQArrayBC: Integer; IsOpenedB: Boolean;
SQArrayU: TSQArray; SQArrayUC: Integer; IsOpenedU: Boolean;
SColor: String;
begin
ALine:=AddTimeStamp(AText);
PB:= FFrame.edIRCEdit.GetTextLen;

i:=1;
IsOpenedC:=False; SQArrayCC:=0;
IsOpenedB:=False; SQArrayBC:=0;
IsOpenedU:=False; SQArrayUC:=0;
while i<>Length(ALine) do
begin
 if ALine[i]=AttribCodes[taBold] then
 begin
  if IsOpenedB then
  begin
   IsOpenedB:=False;
   Delete(ALine,i,1);
   SQArrayB[High(SQArrayB)].EndPos:=i+PB;
  end else
  begin
   IsOpenedB:=True;
   Inc(SQArrayBC);
   SetLength(SQArrayB,SQArrayBC);
   Delete(ALine,i,1);
   SQArrayB[High(SQArrayB)].StartPos:=i+PB;
  end;
 end else
 if ALine[i]=AttribCodes[taUnderline] then
 begin
  if IsOpenedU then
  begin
   IsOpenedU:=False;
   Delete(ALine,i,1);
   SQArrayU[High(SQArrayU)].EndPos:=i+PB;
  end else
  begin
   IsOpenedU:=True;
   Inc(SQArrayUC);
   SetLength(SQArrayU,SQArrayUC);
   Delete(ALine,i,1);
   SQArrayU[High(SQArrayU)].StartPos:=i+PB;
  end;
 end else
 if ALine[i]=AttribCodes[taColor] then
 begin
  if IsOpenedC then
  begin
   IsOpenedC:=False;
   Delete(ALine,i,3);
   SQArrayC[High(SQArrayC)].EndPos:=i+PB;
  end else
  begin
   IsOpenedC:=True;
   Inc(SQArrayCC);
   SetLength(SQArrayC,SQArrayCC);
   SColor:=Copy(ALine,i+1,2);
   if SColor='00' then SQArrayC[High(SQArrayC)].Color:=clWhite;
   if SColor='01' then SQArrayC[High(SQArrayC)].Color:=clBlack;
   if SColor='02' then SQArrayC[High(SQArrayC)].Color:=clNavy;
   if SColor='03' then SQArrayC[High(SQArrayC)].Color:=clRed;
   if SColor='04' then SQArrayC[High(SQArrayC)].Color:=clMaroon;  // brown
   if SColor='05' then SQArrayC[High(SQArrayC)].Color:=clPurple;
   if SColor='06' then SQArrayC[High(SQArrayC)].Color:=clYellow;  // orange
   if SColor='07' then SQArrayC[High(SQArrayC)].Color:=clYellow;
   if SColor='08' then SQArrayC[High(SQArrayC)].Color:=clLime;
   if SColor='10' then SQArrayC[High(SQArrayC)].Color:=clTeal;
   if SColor='11' then SQArrayC[High(SQArrayC)].Color:=clAqua;
   if SColor='12' then SQArrayC[High(SQArrayC)].Color:=clBlue;
   if SColor='13' then SQArrayC[High(SQArrayC)].Color:=clFuchsia;
   if SColor='14' then SQArrayC[High(SQArrayC)].Color:=clGray;
   if SColor='15' then SQArrayC[High(SQArrayC)].Color:=clSilver;
   Delete(ALine,i,3);
   SQArrayC[High(SQArrayC)].StartPos:=i+PB;
  end;
 end else
  Inc(i);
end;

FFrame.edIRCChat.Lines.Add(ALine);

{ Highlight Tab }
if not FTabItem.Checked then Highlight:=True;

for i:=Low(SQArrayC) to High(SQArrayC) do
begin
 FFrame.edIRCChat.SelStart:=SQArrayC[i].StartPos;
 FFrame.edIRCChat.SelLength:=SQArrayC[i].EndPos-SQArrayC[i].StartPos;
 FFrame.edIRCChat.SelAttributes.Color:=SQArrayC[i].Color;
end;
for i:=Low(SQArrayB) to High(SQArrayB) do
begin
 FFrame.edIRCChat.SelStart:=SQArrayB[i].StartPos;
 FFrame.edIRCChat.SelLength:=SQArrayB[i].EndPos-SQArrayB[i].StartPos;
 FFrame.edIRCChat.SelAttributes.Style:=FFrame.edIRCChat.SelAttributes.Style+[fsBold];
end;
for i:=Low(SQArrayU) to High(SQArrayU) do
begin
 FFrame.edIRCChat.SelStart:=SQArrayU[i].StartPos;
 FFrame.edIRCChat.SelLength:=SQArrayU[i].EndPos-SQArrayU[i].StartPos;
 FFrame.edIRCChat.SelAttributes.Style:=FFrame.edIRCChat.SelAttributes.Style+[fsUnderline];
end;
SetLength(SQArrayC,0);
SetLength(SQArrayB,0);
SetLength(SQArrayU,0);

FFrame.edIRCChat.SelStart:=FFrame.edIRCChat.GetTextLen;
FFrame.edIRCChat.SelLength:=0;
end;


ircnoob   (2006-03-04 18:46:00) [4]

большое спасибо. я тысячу раз проше прощение, что возможно пользуюсь ситуацией, но мну клинит ( я запутался. понял свою ошибку, связанную с непроверкой текущего символа в случае удаления, исправился, но ситуация выглядит просто ужасно +(

procedure TVisualChannel.AddIRCLine(const AText: String);
var
PB: Integer;
ALine: String;
i: Integer;
//--
SQArrayC: TSQArray; SQArrayCC: Integer; IsOpenedC: Boolean;
SQArrayB: TSQArray; SQArrayBC: Integer; IsOpenedB: Boolean;
SQArrayU: TSQArray; SQArrayUC: Integer; IsOpenedU: Boolean;
SColor: String;
begin
ALine:=AddTimeStamp(AText);
PB:=FFrame.edIRCEdit.GetTextLen;

i:=1;
IsOpenedC:=False; SQArrayCC:=0;
IsOpenedB:=False; SQArrayBC:=0;
IsOpenedU:=False; SQArrayUC:=0;
while i<>Length(ALine) do
begin
 if ALine[i]=AttribCodes[taBold] then
 begin
  if IsOpenedB then
  begin
   IsOpenedB:=False;
   Delete(ALine,i,1);
   SQArrayB[High(SQArrayB)].EndPos:=i+PB-1;
  end else
  begin
   IsOpenedB:=True;
   Inc(SQArrayBC);
   SetLength(SQArrayB,SQArrayBC);
   Delete(ALine,i,1);
   SQArrayB[High(SQArrayB)].StartPos:=i+PB;
  end;
 end else
 if ALine[i]=AttribCodes[taUnderline] then
 begin
  if IsOpenedU then
  begin
   IsOpenedU:=False;
   Delete(ALine,i,1);
   SQArrayU[High(SQArrayU)].EndPos:=i+PB-1;
  end else
  begin
   IsOpenedU:=True;
   Inc(SQArrayUC);
   SetLength(SQArrayU,SQArrayUC);
   Delete(ALine,i,1);
   SQArrayU[High(SQArrayU)].StartPos:=i+PB;
  end;
 end else
 if ALine[i]=AttribCodes[taColor] then
 begin
  if IsOpenedC then
  begin
   IsOpenedC:=False;
   Delete(ALine,i,3);
   SQArrayC[High(SQArrayC)].EndPos:=i+PB-1;
  end else
  begin
   IsOpenedC:=True;
   Inc(SQArrayCC);
   SetLength(SQArrayC,SQArrayCC);
   SColor:=Copy(ALine,i+1,2);
   if SColor='00' then SQArrayC[High(SQArrayC)].Color:=clWhite;
   if SColor='01' then SQArrayC[High(SQArrayC)].Color:=clBlack;
   if SColor='02' then SQArrayC[High(SQArrayC)].Color:=clNavy;
   if SColor='03' then SQArrayC[High(SQArrayC)].Color:=clRed;
   if SColor='04' then SQArrayC[High(SQArrayC)].Color:=clMaroon;  // brown
   if SColor='05' then SQArrayC[High(SQArrayC)].Color:=clPurple;
   if SColor='06' then SQArrayC[High(SQArrayC)].Color:=clYellow;  // orange
   if SColor='07' then SQArrayC[High(SQArrayC)].Color:=clYellow;
   if SColor='08' then SQArrayC[High(SQArrayC)].Color:=clLime;
   if SColor='10' then SQArrayC[High(SQArrayC)].Color:=clTeal;
   if SColor='11' then SQArrayC[High(SQArrayC)].Color:=clAqua;
   if SColor='12' then SQArrayC[High(SQArrayC)].Color:=clBlue;
   if SColor='13' then SQArrayC[High(SQArrayC)].Color:=clFuchsia;
   if SColor='14' then SQArrayC[High(SQArrayC)].Color:=clGray;
   if SColor='15' then SQArrayC[High(SQArrayC)].Color:=clSilver;
   Delete(ALine,i,3);
   SQArrayC[High(SQArrayC)].StartPos:=i+PB;
  end;
 end else
  Inc(i);
end;

FFrame.edIRCChat.Lines.Add(ALine);

{ Highlight Tab }
if not FTabItem.Checked then Highlight:=True;

for i:=Low(SQArrayC) to High(SQArrayC) do
begin
 FFrame.edIRCChat.SelStart:=SQArrayC[i].StartPos;
 FFrame.edIRCChat.SelLength:=SQArrayC[i].EndPos-SQArrayC[i].StartPos;
 FFrame.edIRCChat.SelAttributes.Color:=SQArrayC[i].Color;
end;
for i:=Low(SQArrayB) to High(SQArrayB) do
begin
 FFrame.edIRCChat.SelStart:=SQArrayB[i].StartPos;
 FFrame.edIRCChat.SelLength:=SQArrayB[i].EndPos-SQArrayB[i].StartPos;
 FFrame.edIRCChat.SelAttributes.Style:=FFrame.edIRCChat.SelAttributes.Style+[fsBold];
end;
for i:=Low(SQArrayU) to High(SQArrayU) do
begin
 FFrame.edIRCChat.SelStart:=SQArrayU[i].StartPos;
 FFrame.edIRCChat.SelLength:=SQArrayU[i].EndPos-SQArrayU[i].StartPos;
 FFrame.edIRCChat.SelAttributes.Style:=FFrame.edIRCChat.SelAttributes.Style+[fsUnderline];
end;
SetLength(SQArrayC,0);
SetLength(SQArrayB,0);
SetLength(SQArrayU,0);

FFrame.edIRCChat.SelStart:=FFrame.edIRCChat.GetTextLen;
FFrame.edIRCChat.SelLength:=0;
end;


з.ы. вроде все должно быть пучком (


begin...end   (2006-03-04 12:52:00) [5]

> ircnoob   (04.03.06 12:20)

> PB:=0;
> for i:=0 to FFrame.edIRCChat.Lines.Count-1 do
>  PB:=PB+Length(FFrame.edIRCChat.Lines[i]);

PB := edIRCChat.GetTextLen

> Delete(ALine,i,1);
> ...
> Inc(i);

А тут ошибка. Удаляется символ атрибута, на его место перемещается следующий за ним, и этот следующий символ не проверяется.


Наверх

Титульная страница Поиск, карта сайта Написать письмо