quarta-feira, 21 de janeiro de 2009

Destacando palavras no RichEdit

Bom galera, de volta das férias, de volta aos posts. Já de início, uma coisa que a algum tempo vinha despertando minha curiosidade, e hoje, vendo um post de usuário no fórum do Imasters, resolvi colocar a cabeça pra pensar. Imagine, um formulário no Delphi onde você vai digitando normalmente seu texto, e dentro dele, algumas palavras vão ganhando destaque, cores diferentes, ficam em negrito. Da mesma forma como acontece no Word, ao digitar "microsoft" ele corrige e troca para "Microsoft", ou, porque não fazer com que fique imediatamente em negrito também, assim "Microsoft".

De início, crie um novo projeto Windows Forms (Win32) no Delphi, em seguida, adicione os seguintes componentes: Edit (Edit1), ColorBox (ColorBox1) da paleta additional,um Button (Button1) e um RichEdit (RichEdit1) da paleta Win32.

Agora, no código, no corpo da unit, crie um novo tipo (nova declaração de tipo), adicionando as seguintes linhas logo após a linha "type":

TRPalavras = Record
DS_PALAVRA: String;
VR_COR : TColor;
ESTILO : TFontStyles;
end;

TAPalavras = array of TRPalavras;

Agora, declare uma variável do tipo private, da seguinte forma:

APalavras : array of TRPalavras;

Esta varável irá descender do tipo TRPalavras criado anteriormente.

Acessando agora o evento OnClick do botão, adicione o código a seguir, o qual será responsável por armazenar no array quais as palavras e respectivas cores que devem ser destacadas no texto a ser digitado no componente RichEdit.

{ Adicionando as palavras a lista }
SetLength( APalavras, Length( APalavras )+1 );
APalavras[ High( APalavras ) ].DS_PALAVRA := Edit1.Text;
APalavras[ High( APalavras ) ].VR_COR := ColorBox1.Selected;
APalavras[ High( APalavras ) ].ESTILO := [fsBold];

Por final, adicione também ao evento OnKeyUp do RichEdit o código a seguir, código este que irá identificar o início e fim de uma palavra que está sendo digitada, fazendo sua comparação com as palavras armazenadas. Caso a palavra digitada coincida com uma das armazenadas, um comando for será disparado fazendo com que todas as letras sejam destacadas em negrito e de acordo com a cor selecionada com componente ColorBox.

procedure TForm1.RichEdit1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
const
LetrasValidas = ['a'..'z', 'A'..'Z', '0'..'9', '<', '>', '!', '='];

var
iPosIni: Integer;
iPosFim: Integer;
iSelStart: Integer;
iSelLength: Integer;
iLoopFor: Integer;
sText: String;
begin

LockWindowUpdate(RichEdit1.Handle);

{ guardaremos a posição inicial }
iSelStart := RichEdit1.SelStart;
iSelLength := RichEdit1.SelLength;

sText := RichEdit1.Text;

{ Acharemos o inicio da palavra }
iPosIni := iSelStart;
if sText[ iPosIni ] in LetrasValidas then
begin
for iLoopFor := iSelStart-1 downto 0 do
begin
if sText[ iLoopFor ] in LetrasValidas then
iPosIni := iLoopFor
else
Break;
end;
end;

{ Acharemos o final da palavra }
iPosFim := iSelStart;
for iLoopFor := iSelStart+1 to Length( RichEdit1.Text ) do
begin
if RichEdit1.Text[ iLoopFor ] in LetrasValidas then
iPosFim := iLoopFor
else
Break;
end;

{ Selecionaremos a palavra }
RichEdit1.SelStart := iPosIni-1;
RichEdit1.SelLength := (iPosFim)-RichEdit1.SelStart;

{ setaremos a cor original e estilo original }
RichEdit1.SelAttributes.Color := clBlack;
RichEdit1.SelAttributes.Style := [];

{ Atribuiremos a nova cor e estilo caso encontre a palavra }
for iLoopFor := 0 to High( APalavras ) do
begin
if UpperCase(APalavras[ iLoopFor ].DS_PALAVRA) = UpperCase(RichEdit1.SelText) then
begin
RichEdit1.SelAttributes.Color := APalavras[ iLoopFor ].VR_COR;
RichEdit1.SelAttributes.Style := APalavras[ iLoopFor ].ESTILO;
Break;
end;
end;

{ Posicionaremos o cursor na posição original }
RichEdit1.SelStart := iSelStart;
RichEdit1.SelLength := iSelLength;

LockWindowUpdate(0);

end;

Com o sistema em funcionamento, ao adicionarmos a palavra "microsoft", e digitarmos um texto no componente RichEdit da tela, ao digitarmos alguma das palavras adicionadas, a mesma será descada, conforme mostra a imagem.

Assim, faça a implementação em seus sistemas, boa leitura e até a próxima.
Obs.: Deixe um comentário com seu nome / e-mail para receber os fontes.

9 comentários:

Soidho disse...

Muito bom este artigo, está de parabens!

Gostaria de saber tambem, como eu faço para fazer uma lista e palavras já definidas e o programa compara a palavra com o texto e destaca? Seria mais ou menos como se fosse o Delphi. Quando eu digito begin ele fica negrito. Como eu faria tentei aqui e não consegui. Obrigado!

Maikel Scheid disse...

Olá Bruno

Bom, há diversar formas de você fazer isto, uma até poderia ser digitar as palavras no Edit e para cada uma delas você clica em adicionar, onde todas ficarão guardadas em memória no array.

Outra forma, se pretende usar uma lista fixa de palavras poderia ser colocar o seguinte trecho no evento OnShow do forma, e repetir o trecho para cada palavra a ser destacada:
SetLength( APalavras, Length( APalavras )+1 );
APalavras[ High( APalavras ) ].DS_PALAVRA := 'Begin';
APalavras[ High( APalavras ) ].VR_COR := clRed;
APalavras[ High( APalavras ) ].ESTILO := [fsBold];

SetLength( APalavras, Length( APalavras )+1 );
APalavras[ High( APalavras ) ].DS_PALAVRA := 'End';
APalavras[ High( APalavras ) ].VR_COR := clRed;
APalavras[ High( APalavras ) ].ESTILO := [fsBold];

Uma terceira forma poderia ser carregar as informações de um ClientDataSet vindo do banco de dados, ou até poderia ler um TXT, onde faria um loop e adicionaria as palavras enquanto houvessem, assim:
ClientDataSet1.First;
while not ClientDataSet1.Eof do
begin
SetLength( APalavras, Length( APalavras )+1 );
APalavras[ High( APalavras ) ].DS_PALAVRA := ClientDataSet1.FildByName('CAMPO').AsString;
APalavras[ High( APalavras ) ].VR_COR := clRed;
APalavras[ High( APalavras ) ].ESTILO := [fsBold];
ClientDataSet1.Next;
End;

E assim, poderiamos ainda criar outras situações de preenchimento da lista.

Att

Maikel

Harley Coimbra dos Santos disse...

Ola..

Muito Bom Artigo Maikel.

Primeiramente gostaria de receber os fontes binabreu@hotmail.com.

E gostaria de criar um rotina que destaca-se a palavra quando eu inicia-se e termina-se ela com #.
Ex: #Exemplo# essa palavra Exemplo ficasse em negrito tem como ?

critik disse...

Muito bom mesmo mais tenhu uma duvida cruel estou desenvolvendo um progrma um mini editor so que eu queria qui ele tabem fizasse isso sem precisar digitar tipo pra ele tbm execuar isso quando copiar e colar ja tetei e não consigo .

Desde ja agradeço
João

Analista Programador disse...

Muito bom...
Funcionou perfeitamente para o que eu queria, só tem um porem que ainda vou tentar resolver, somente a primeira linha recebe as cores e estilo, a outras não se alguem souber...me enviem a solução por email, janderalberice@hotmail.com. No mais otimo codigo.

DREIGON FENRIZ disse...

OLA,SERA QUE PODERIA ME ENVIAR O CODIGO FONTE,DESDE JA AGRADEÇO

Ir.Adriano disse...

Me socorram, tá acusando o erro na minha uses, tá dizendo F2063, está marcando na minha unit

Ir.Adriano disse...

Program agendacompleta;

Uses
Vcs.Forms,
U_agenda in 'agendacompleta' {Form1};
{$R*.res}

Begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
End.

{Tá acusando erro no código, sou I iciante em Delphi}

Alessandro Esteves disse...

Olá! E para eu imprimir esse texto (que terá algumas palavras em negrito)? Estou fazendo teste e não consegui imprimir ele mantendo esse negrito. Estou usando o Fortes Report CE e o campo RLRichText.