![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Раскраска 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);
А тут ошибка. Удаляется символ атрибута, на его место перемещается следующий за ним, и этот следующий символ не проверяется.