Você está na página 1de 15

editor de texto Página 1 de 15

Construção do Editor de Textos

Vamos dar os primeiros passos na construção de um Editor de Textos.


Clique em File e depois em New Application.
Pegue um componente RichEdit na palleta Win32 (ou Win95) e a coloque no Form.
Altere a propriedade BorderStyle do Form para bsNone (para tirar a barra de títulos e suas propriedades).
Altere a propriedade Align do RichEdit para alCliente (Assim o RichEdit ocupará toda a área cliente do Form).
Na palleta Standart pegue um componente PopudMenu (para criarmos alguns menus pop-up), e coloque no Form.
Dê um clique com o botão direito do mouse sobre o componente PopupMenu e escolha a opção Menu Designer ...
Abrir-se-á o Menu Designer (Editor de Menus). Na propriedade Caption (no Object Inspector) do Editor digite:Arquivo

Dê um clique na parte selecionada do Menu Designer. Aparecerá a palavra Arquivo selecionada no menu flutuante, e abrir-
se-á, logo abaixo, um novo campo para menu.
Dê um clique nesse novo campo (que ficará selecionado) e, na propriedade Caption, digite:
Editar
Muito bem, já sabemos criar o Menu Popup.
Agora, no Menu Designer, onde tem a palavra Arquivo dê um clique para selecionar o menu correspondente. Depois, com o
botão direito do mouse, dê um clique sobre o menu Arquivo já selecionado. Aparecerá um menu Pop-up. Escolha a opção
Create Submenu.
Na propriedade Caption digite:&Abrir

O Símbolo & cria um atalho (tecla de atalho + a letra sublinhada) para o menu. Abaixo do menu Abrir, Crie o menu
Locali&zar; abaixo do menu Localizar crie o menu &Salvar; abaixo do menu Salvar crie o traço separador de menus
digitando apenas um traço: - ;abaixo do traço, crie o menu Sai&r.

Nota: quando criamos atalho, tomemos cuidado para não usar as mesmas teclas de atalho para funções diferentes.

Construção do Editor de Textos


Segunda parte
Agora dê um duplo clique no menu Sair. Abrir-se-á o Editor Properties que é o Editor de Códigos do programa. Digite:
Close();
O Código deve ficar assim:

void __fastcall TForm1::Sair1Click(TObject *Sender)


{
Close();
}

Para ativar o PopupMenu, no evento OnCreate do Form1 digite:


PopupMenu1->AutoPopup = true;
RichEdit1->PopupMenu = PopupMenu1;
O Código deve ficar assim:

void __fastcall TForm1::FormCreate(TObject *Sender)


{
PopupMenu1 -> AutoPopup = true;
RichEdit1 -> PopupMenu = PopupMenu1;
}

Rode o Programa (Tecla F9). Você perceberá que criou um Editor de Textos bem estranho. Digite ou delete letras e
palavras.

Para fechar o programa, dê um clique com o botão direito do mouse sobre o Editor e escolha a opção Sair no menu Arquivo.

Se você seguiu os passos corretamente, e o programa fechou sem problemas, na propriedade WindowState do Form1
escolha a opção: wsMaximized, e rode novamente o programa. Ele ocupará toda a tela do Windows. Siga o mesmo
procedimento para encerrar o programa. Uma outra forma de encerrar o aplicativo é pressionando simultaneamente as teclas
alt + F4.

Dê um duplo clique na propriedade Lines de RichEdit1. No editor que se abrir, delete a palavra RichEdit1 e dê um OK, o
que fará que essa string não apareça mais na execução do programa.
Na palette Dialogs, pegue um componente OpenDialog e coloque no projeto. Na propriedade InitialDir de OpenDialog

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 2 de 15

podemos digitar o caminho do diretório onde queremos que a Caixa de Diálogo Abrir inicialize (por exemplo: C:\Meus
documentos) e, feito isso, podemos completar o caminho e escolher um arquivo inicial na propriedade FileName (por
exemplo: C:\Meus documentos\Tutorial.txt). Na propriedade Filter, nós podemos escolher os arquivos que o Editor pode
abrir, por meio do Filter Editor.
No Filter Editor digite:

Filter Name Filter


arquivos richtext *.rtf *.rtf
arquivos de texto *.txt *.txt
todos os arquivo *.* *.*

e dê um OK.
Abra o MenuDesigner e dê um duplo clique no submenu Abrir para abrir o Editor Properties.
Entre as chaves { e } digite:

if (OpenDialog1 -> Execute())


RichEdit1 -> Lines -> LoadFromFile(OpenDialog1 -> FileName);
else
MessageBeep(0);
O código deverá ficar assim:

void __fastcall TForm1::Abrir1Click(TObject *Sender)


{
if (OpenDialog1 -> Execute())
RichEdit1 -> Lines -> LoadFromFile(OpenDialog1 -> FileName);
else
MessageBeep(0);
}

Nosso Editor já está em condições de abrir documentos. Rode o programa e abra alguns documentos de texto (*.txt) ou
richtext (*.rtf).

Passemos ao submenu Localizar.


Coloque um componente FindDialog no projeto. Em seguida abra o Menu Designer e dê um duplo clique em Localizar. No
Editor Properties, entre as chaves { e } que se abrirem, digite:

FindDialog1->Execute();
int FoundAt, StartPos, ToEnd; // declara três variáveis int

////////////////////////////////////////////////////////////////////////
// INICIA A BUSCA A PARTIR DA SELEÇÃO ATUAL
// OU DE OUTRA FORMA
// INICIA A PARTIR DO INÍCIO DO TEXTO

/*SelLength devolve o número de caracteres selecionados*/


if (RichEdit1->SelLength) /* se há caracteres selecionados em RichEdit1*/
/*SelStart devolve a posição do primeiro caracter selecionado no texto*/
/*o código abaixo devolve a posição do último caracter selecionado*/
StartPos = RichEdit1->SelStart + RichEdit1->SelLength;
else
StartPos = 0;
///////////////////////////////////////////////////////////////////////////

/*Length() retorna o número de caracteres de AnsiString*/


/*Ou ToEnd será igual a Text.Lengt() ou igual ao número dos
caracteres a serem contados após o último caracter selecionado*/
ToEnd = RichEdit1->Text.Length() - StartPos;
/*FindText busca o texto num controle rich edit para a string
especificada no parametro SearchStr (no exemplo: FindDialog1->FindText)*/
FoundAt = RichEdit1->FindText(FindDialog1->FindText,

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 3 de 15

StartPos, ToEnd, TSearchTypes());


if (FoundAt != -1) // se a variável for difetente de -1
RichEdit1->SetFocus(); // coloca o foco em RichEdit1
// coloca o cursor na primeira ocorrência
RichEdit1->SelStart = FoundAt;
// seleciona a string procurada no texto do RichEdit1
RichEdit1->SelLength = FindDialog1->FindText.Length();

No Object Inspector, no evento (Events) OnFind de FindDialog1 escolha a opção Localizar1Click. Em Properties, dê um
duplo clique em Options. Altere de false para true as seguintes opções:

frHideMatchCase true
frHideWholeWord true
frHideUpDown true

Agora seu editor já se encontra apto para efetuar algumas buscas de textos ou caracteres.

Coloque um componente SaveDialog no projeto, abra o Menu Designer e dê um duplo clique em Salvar. No Editor
Properties, entre as chaves { e } que se abrirem, digite:

if (SaveDialog1 -> Execute())


RichEdit1 -> Lines -> SaveToFile(SaveDialog1 -> FileName);
else
MessageBeep(0);

Em SaveDialog, temos funcionando de forma semelhante ao funcionamento em OpenDialog, as propriedades InitialDir,


FileName e Filter, com a diferença de que, no presente caso, estamos cuidando de salvar arquivos, e não abri-los.

Como experiência, no Filter Editor digite:

Filter Name Filter


arquivos richtext *.rtf *.rtf
arquivos de texto *.txt *.txt
todos os arquivo *.* *.*

e escolha um diretório inicial para salvar os arquivos.

Pois bem, todos os submenus do menu Arquivo já estão funcionando. Agora vamos criar mais alguns menus e submenus.
Selecione o menu Editar no Menu Designer e crie os seguintes submenus: Cortar, Copiar, Colar, Deletar e Selecionar Tudo.
Vamos aos códigos:

submenu Cortar:

void __fastcall TForm1::Cortar1Click(TObject *Sender)


{
TComponent *pComponent = PopupMenu1->PopupComponent;
if (pComponent)
{
if (pComponent->ClassNameIs("TRichEdit"))
((TRichEdit *)pComponent)->CutToClipboard();
else

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 4 de 15

MessageBeep(0);
}
}

submenu Copiar

void __fastcall TForm1::Copiar1Click(TObject *Sender)


{
TComponent *pComponent = PopupMenu1->PopupComponent;
if (pComponent)
{
if (pComponent->ClassNameIs("TRichEdit"))
((TRichEdit *)pComponent)->CopyToClipboard();
else
MessageBeep(0);
}
}

submenu Colar

void __fastcall TForm1::Colar1Click(TObject *Sender)


{
TComponent *pComponent = PopupMenu1->PopupComponent;
if (pComponent)
{
if (pComponent->ClassNameIs("TRichEdit"))
((TRichEdit *)pComponent)->PasteFromClipboard();
else
MessageBeep(0);
}
}

Agora vamos trabalhar com um código mais simples nas funções Deletar e Selecionar Tudo.

submenu Deletar

void __fastcall TForm1::Deletar1Click(TObject *Sender)


{
RichEdit1 -> ClearSelection();
}

submenu Selecionar Tudo

void __fastcall TForm1::SelecionarTudo1Click(TObject *Sender)


{
RichEdit1 -> SelectAll();
}

Exercício: Pesquise TComponent no Help do C++Builder e procure entender seu papel nas funções que usaram-no. Depois
insira comentários documentando detalhadamente os códigos acima.

Abaixo do menu Editar, crie o menu Formatar com dois submenus: Fontes e Cores.
submenu Fontes

Coloque um componente FontDialog no projeto.

Eis o código:

void __fastcall TForm1::Fontes1Click(TObject *Sender)


{ /*coloca os atributos do texto selecionado no RichEdit1
em FontDialog1*/
FontDialog1->Font->Assign(RichEdit1->SelAttributes);
/*Sendo chamada a caixa de diálogo de fontes*/

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 5 de 15

if(FontDialog1->Execute())
/*as fontes selecionadas de RichEdit1 receberão os atributos
da caixa de diálogos de fontes*/
RichEdit1->SelAttributes->Assign(FontDialog1->Font);
}
Nota: TtextAttributes::Assign

Coloca as propriedades de um objeto TTextAttributes em conformidade com as propriedades especificadas em outro objeto
TTextAttributes ou num objeto TFont.

Use Assign para mudar todos os atributos de texto simultaneamente. Assign pode colocar as características das fonts
selecionadas num texto em conformidade com as características default da font ou vice-versa. Quando o início é um objeto
TTextAttributes, Assign adapta somente Color, Name, Style, e propriedades Pitch. Quando o início é um objeto TFont,
Assign também adapta o Size.

Nota: Assign somente substitui em tempo de execução quando ´início é um objeto TTextAttributes, um objeto TFont, ou
um objeto que tenha implementado um método AssignTo que trate o objeto TTextAttributes. Outras origens produzem
exceções de erro.

Coloque um componente ColorDialog no projeto.

Eis o código:

void __fastcall TForm1::Cores1Click(TObject *Sender)


{
if (ColorDialog1 -> Execute())
/*a cor de RichEdit1 será a cor escolhida em ColorDialog1*/
RichEdit1 -> Color = ColorDialog1 -> Color;
}

O código de Cores1Click não é subsistente. Ou seja, se você alterar a cor do editor de textos e fechar o aplicativo, na
próxima vez que abrir o editor de textos, ele abrirá na cor padrão, estabelecida inicialmente no Object Inspector.
Futuramente nós veremos um modo de conservar a cor atrávés de arquivos .INI.

Vamos alterar algumas propriedades:


Para colocar uma barra de rolagem vertical, altere a propriedade ScrollBarss de RichEdit1 para ssVertical.
Normalmente os componentes Memo e RichEdit têm uma limitação na quantidade de dados que podem receber, que é uma
quantia padrão. Podemos aumentá-la ou diminui-la bastante. Na verdade, tudo depende da quantidade de dados que
trabalharemos. Para alterar essa quantia de dados devemos mudar a propriedade MaxLength (no Object Inspector ou em
tempo de execução). Por exemplo, se colocarmos a propriedade MaxLength para 2147483645 (que é um tamanho
praticamente incomensurável) tais componentes poderão receber dois bilhões, cento e quarenta e sete milhões, quatrocentos
e oitenta e três mil, seiscentos e quarenta e cinco caracteres.
No momento, nosso projeto deve estar com esta aparência:

Exercícios:

1) O submenu Localizar deve ser retirado do menu Arquivo e colocado no menu Editar;

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 6 de 15

2) Falta uma função que ative a impressora para imprimir textos. Providencie a colocação do componente e do código
correspondente.

3) Coloque atalhos nos menus. Use as propriedades ShortCut correspondentes.

Feito isso, continuemos. Vamos dar ao nosso Editor a possibilidade de alterar seu tamanho.
Abra o MenuDesigner e, abaixo do menu Formatar, crie o menu Janela que deverá conter os seguintes submenus:
Maximizar, Normal, Minimizar.
Vamos aos códigos:

void __fastcall TForm1::Maximizar1Click(TObject *Sender)


{
BorderStyle = bsNone;
WindowState = wsMaximized;
}

//------------------------------------------------------
void __fastcall TForm1::Normal1Click(TObject *Sender)
{
BorderStyle = bsNone;
WindowState = wsNormal;
}

//------------------------------------------------------
void __fastcall TForm1::Minimizar1Click(TObject *Sender)
{
BorderStyle = bsSizeable;
WindowState = wsMinimized;
}

Execute o programa e experimente todos os menus. Observe se todos os comandos estão obedecendo perfeitamente. Caso
haja algum problema, dê uma olhada se não digitou algum código errado.

Agora vamos deixá-lo mais parecido com aqueles editores que estamos acostumados a trabalhar. Em primeiro lugar, altere o
nome do submenu Salvar para Salvar Como. Feito isso, dê um clique com o botão direito do mouse sobre o submenu Salvar
Como e, em seguida, um clique em insert. Abrir-se-á um espaço para um novo submenu. Dê-lhe o nome de Salvar e, como
exercício, digite para ele o código que o usuário salva o texto automaticamente sem chamar a caixa de diálogo Salvar Como
(caso o arquivo já esteja gravado em disco). Caso você não consiga, não se preocupe. Em lições futuras estudaremos esse
evento.

Abra novamente o Menu Designer e crie o menu Visualizar, com os seguintes submenus: Barra de títulos, Barra de
Ferramentas e Régua. Vamos ao primeiro código:

void __fastcall TForm1::BarradeTtulos1Click(TObject *Sender)


{
if(BorderStyle == bsSizeable)
BorderStyle = bsNone;
else
BorderStyle = bsSizeable;
}

Vamos colocar uma Barra de Ferramentas e uma Régua em nosso Editor. Primeiramente coloque um componente TPanel
(Panel), da página Standard no Form. Desse componente, no Object Inspector, delete qualquer caracter da propriedade
Caption, altere a propriedade Align para alTop e a Propriedade Visible para false. Feito isso, eis o código do menu
correspondente:

void __fastcall TForm1::BarradeFerramentas1Click(TObject *Sender)


{
if(Panel1->Visible == true)
Panel1->Visible = false;
else
Panel1->Visible = true;
}

Após terminar de digitar o código, coloque um segundo TPanel no Form. As Propriedades são rigorosamente as mesmas:
Caption = “”; Align = alTop e Visible = false. Você perceberá que esse segundo Panel se instalará abaixo do primeiro (de
Panel1). Eis o código:

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 7 de 15

void __fastcall TForm1::Rgua1Click(TObject *Sender)


{
if(Panel2->Visible == true)
Panel2->Visible = false;
else
Panel2->Visible = true;
}

O primeiro Panel será usado para construírmos a Barra de Ferramentas e o segundo, a régua.
Rode a aplicação e experimente o resultado parcial.

O C++Builder possui componentes Buttons que podem carregar imagens. Trata-se dos SpeedButtons e BitBtns. Para colocar
imagens nesses botões, basta editar sua propriedade Glyph no Object Inspector. As imagens a seguir, tiradas dos próprios
exemplos do C++Builder, sendo que algumas delas podem ser editadas para ser carregadas no botão adequado do nosso
editor de textos.

Caso você ainda não tenha providenciado, vamos agora estudar como podemos colocar um botão (ou menu) Salvar em
nosso Editor. Antes, porém, certifique-se de ter providenciado a alteração solicitada no final da seção: Construção do Editor
de Textos - Nona parte.

Dificuldade: Quando o botão for pressionado (ou o menu respectivo receber o evento correspondente), o programa deverá
fazer uma verificação para saber se o arquivo já se encontra gravado em disco; em caso afirmativo, deverá conhecer o
caminho completo para salvar o arquivo; em caso negativo, deverá chamar a caixa de diálogos Salvar Como. Comecemos
trabalhando com os menus. Vá para o Editor de Códigos e lhe dê um clique com o botão direito do mouse. No menu pop-up
que se abrir, escolha a opção: Open Source/Header File, ou simplesmente pressione as teclas Ctrl + F6 simultaneamente.
Abrir-se-á o arquivo de cabeçalho Unit1.h. Na parte de baixo do arquivo, Depois da linha que inicia as declarações privadas
da classe, declare duas AnsiString que servirão para guardar os caminhos dos arquivos que forem abertos ou salvos,
respectivamente. Eis as declarações.

private: // User declarations


AnsiString Caminho_Abrir;
AnsiString Caminho_Salvar;
public: // User declarations
Nota: Futuramente entenderemos melhor a finalidade deste arquivo.

Agora vamos implementar algumas modificações nos códigos dos eventos Abrir e Salvar Como do nosso Editor de Textos:

void __fastcall TForm1::Abrir1Click(TObject *Sender)


{
if (OpenDialog1 -> Execute())
{
RichEdit1 -> Lines -> LoadFromFile(OpenDialog1 -> FileName);

//Caminho_Abrir atribuída com caminho do último arquivo aberto


Caminho_Abrir = OpenDialog1->FileName;
//atribui Caminho_Abrir para Caminho_Salvar (para ficarem iguais)
Caminho_Salvar = Caminho_Abrir;
}
else
MessageBeep(0);
}
//---------------------------------------------------------------------------

void __fastcall Tform1::Salvar1Click/*atual Salvar Como*/(TObject *Sender)


{
if (SaveDialog1 -> Execute())
{
RichEdit1 -> Lines -> SaveToFile(SaveDialog1 -> FileName);

// Caminho_Salvar atribuída com caminho do último arquivo salvo


Caminho_Salvar = SaveDialog1->FileName;
// atribui Caminho_Salvar para Caminho_Abrir (para ficarem iguais)
Caminho_Abrir = Caminho_Salvar;
}
else
MessageBeep(0);
}

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 8 de 15

//---------------------------------------------------------------------------
Agora basta digitarmos o código para o menu salvar:
void __fastcall TForm1::Salvar2Click/*Salvar*/(TObject *Sender)
{
// se o arquivo aberto já foi salvo ...
if((Caminho_Abrir == Caminho_Salvar) && (Caminho_Salvar != ""))
// o arquivo será salvo sem chamar a caixa Salvar Como
RichEdit1->Lines->SaveToFile(Caminho_Abrir);
else // senão
// a caixa de diálogos Salvar Como será Chamada
Salvar1Click(Sender);
}
Vamos agora suspender, por algum tempo, a construção do Editor de Textos, a fim de abordarmos alguns pontos muito
importantes. Brevemente retornaremos às lições.

Dando continuidade à construção de nosso Editor de Textos, vamos providenciar alguns botões (SpeedButtons) que
realizarão as mesmas tarefas realizadas pelos menus correspondentes. Esses botões devem ser agrupados. Por exemplo, um
primeiro grupo de botões realizará as mesmas tarefas executadas pelos principais menus normalmente inseridos no menu
Arquivo (Novo, Abrir, Salvar e Salvar Como). Depois disso, deixamos um pequeno espaço entre os botões para iniciar o
segundo grupo (correspondente ao menu Editar) e assim sucessivamente você colocará aquelas tarefas que você entende
como principais e, portanto, obrigatoriamente disponíveis em menus e em botões. Veja abaixo uma ilustração de como
poderiam se dar tais agrupamentos:

A partir daqui (referente à barra de ferramentas), deixaremos você um pouco mais à vontade com relação ao layout do
Editor. Ou seja, Você decidirá quais botões serão criados (tarefas desejadas). Mesmo porque estaremos trabalhando de uma
forma um tanto repetitiva. Forneceremos código para tarefas que você ainda não conhece, bem como do botão Abrir. Os
demais, seguirão o mesmo caminho, baseando-se nos códigos prontos dos menus equivalentes. As imagens para os botões
você poderá escolher livremente, tomando o cuidado de escolher aquelas que se encaixam no perfil da tarefa a ser executada
e no tamanho do botão.

Se você quiser dar uma aparência tridimensional nos botões (SpeedButtons) altere a propriedade Flat para True.

Nota: Toolbars oferecem um modo fácil de organizar e administrar controles visuais. Podemos criar uma barra de botões
com um componente panel e alguns speed buttons, ou simplesmente usar o componente ToolBar. Para maiores
esclarecimentos, clique aqui

Eis o código para a opção Novo (no caso um menu) que pode ser colocado no grupo Arquivo:

void __fastcall TForm1::Novo1Click(TObject *Sender)


{
ShellExecute(0, "open", Application->ExeName.c_str(), 0, 0, SW_SHOW);
}

Vamos colocar o código do botão Abrir, o qual alteramos a propriedade Name para SpButtonAbrir:

void __fastcall TForm1::SpButtonAbrirClick(TObject *Sender)


{
Abrir1Click(Sender);
}

Exercício: Baseando-se no código acima, coloque o código dos outros botões.

Também podemos colocar um comando (menu e/ou botão) que desfaz a última ação do usuário (o famoso Ctrl + z). Eis o
código:

void __fastcall TForm1::Desfazer1Click(TObject *Sender)


{
SendMessage(RichEdit1->Handle, WM_UNDO, 0, 0);
}

Caso você não tenha conseguido inserir um código para imprimir, veja um exemplo:

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 9 de 15

/*Envia o Text do RichEdit para a impressora imprimeir*/


if ( PrintDialog1->Execute() ) RichEdit1->Print(RichEdit1->Text);

Assumimos que você já se encontra apto a completar o códigos da maioria dos botões da Barra de Ferramentas (os
estudados nos menus).

Nenhum Editor seria completo sem as opções de alinhamento de texto. Vamos possibilitar, ao nosso Editor, o alinhamento à
esquerda, ao centro e à direita. Para tanto, devemos colocar três SpeedButton na Barra de Ferramentas. Esses botões devem
trabalhar em conjunto, pois quando o evento de um estiver produzindo efeitos, os dos outros dois deverão permanecer
inativados. Assinale a Propriedade GroupIndex de todos eles para 1. Isso fará que eles pertençam ao mesmo grupo. Assinale,
também, a propriedade Down do Botão Responsável pelo alinhamento à esquerda para True. Dessa forma, esse alinhamento
à esquerda será padrão para o Editor.

Eis os códigos para os SpeedButton já com os novos nomes (Name):

void __fastcall TForm1::SpdBtAlinhEsqClick(TObject *Sender)


{
RichEdit1->Paragraph->Alignment = taLeftJustify;
}

//------------------------------------------------------
void __fastcall TForm1::SpdBtAlinhCentClick(TObject *Sender)
{
RichEdit1->Paragraph->Alignment = taCenter;
}

//------------------------------------------------------
void __fastcall TForm1::SpdBtAlinhDirClick(TObject *Sender)
{
RichEdit1->Paragraph->Alignment = taRightJustify;
}

Agora precisamos forçar a mudança espontânea do estado (Down) dos botões. O código abaixo verifica a necessidade de
alterar o estado dos botões através do evento OnKeyUp.

void __fastcall TForm1::RichEdit1KeyUp(TObject *Sender, WORD &Key,


TShiftState Shift)
{
if(RichEdit1->Paragraph->Alignment == taLeftJustify)
SpdBtAlinhEsq->Down = true;
else if(RichEdit1->Paragraph->Alignment == taCenter)
SpdBtAlinhCent->Down = true;
else if(RichEdit1->Paragraph->Alignment == taRightJustify)
SpdBtAlinhDir->Down = true;
}

Que tal acrescentarmos alguns botões para alterar atributos de texto (negrito, itálico e sublinhado).

Nota: SelAttributes descreve as características de um texto selecionado num controle RichEdit


Use SelAttributes para revelar ou adaptar as características de font do texto selecionado. SelAttributes é um objeto
TTextAttributes, que especifica características como font face, color, size, style, e pitch (número de caracteres). Para mudar
um único atributo de um texto selecionado, interprete SelAttributes, e adapte uma de suas propriedades. Para mudar todos os
atributos de um texto selecionado, coloque SelAttributes para um objeto TTextAttributes que represente a configuração
desejada dos atributos. Se não há texto selecionado, SelAttributes representa a posição do cursor.
Quando inserimos um novo texto, as características da font são compatíveis com SelAttributes.
SelAttributes está disponível apenas em tempo de execução.

Introduziremos juntos o código responsável pelo sublinhamento do texto. Os códigos necessários ao negrito e itálico ficarão
por sua conta.
Não é novidade para você SpeedButtons trabalhando em grupo (GroupIndex). Já imaginou um grupo de apenas um botão?
Pois bem, é o que faremos agora. Cada um dos botões deverá ter um número único na propriedade GroupIndex, ou seja,
apenas um botão com tal número.
Coloque três SpeedButtons no Form. Do botão responsável pelo sublinhamento do texto, altere a propriedade Name para
SpdBtUnderline. Altere a propriedade AllowAllUp desse botão para true; e altere o número do GroupIndex do mesmo para
2 (lembre-se de que nenhum outro botão poderá ter esse mesmo número para essa propriedade). Com esses dois simples
procedimentos nós damos um primeiro passo para forçar o botão a trabalhar down ou up corretamente. Vejamos o código
responsável pelas ações de sublinhamento:

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 10 de 15

void __fastcall TForm1::SpdBtUnderlineClick(TObject *Sender)


{
// Se o texto selecionado em RichEdit1 não está sublinhado
if(RichEdit1->SelAttributes->Style == RichEdit1->SelAttributes->Style >> fsUnderline)
// ele será sublinhado
RichEdit1->SelAttributes->Style = RichEdit1->SelAttributes->Style << fsUnderline;
else if // ou então
// se o texto estiver sublinhado
(RichEdit1->SelAttributes->Style == RichEdit1->SelAttributes->Style << fsUnderline)
// ele será desmarcado
RichEdit1->SelAttributes->Style = RichEdit1->SelAttributes->Style >> fsUnderline;
}

Agora nós vamos acrescentar uma linha de código no evento OnKeyUp de RichEdit1:

void __fastcall TForm1::RichEdit1KeyUp(TObject *Sender, WORD &Key,


TShiftState Shift)
{
//atualiza o estado (Down) do botão de sublinhado
SpdBtUnderline->Down = RichEdit1->SelAttributes->Style.Contains(fsUnderline);

//atualiza o estado (Down) dos botões - alinhamento de texto


if(RichEdit1->Paragraph->Alignment == taLeftJustify)
SpdBtAlinhEsq->Down = true;
else if(RichEdit1->Paragraph->Alignment == taCenter)
SpdBtAlinhCent->Down = true;
else if(RichEdit1->Paragraph->Alignment == taRightJustify)
SpdBtAlinhDir->Down = true;
}

Com isso encerramos esta seção do Editor, cabendo lembrar que para negrito usamos fsBold, enquanto para itálico usamos
fsItalic.

Vamos agora colocar comando para alterar o tipo (Name) e o tamanho (Size) das fontes de nosso Editor. Para manejar o
tipo, usaremos um ComboBox e, para o tamanho, um Edit conjugado com um UpDown. Desta feita, como exercício,
forneceremos apenas os códigos necessários ao funcionamento destas ações, com um comentário básico. Caberá a você
quebrar um pouquinho a cabeça para entendê-los. Se você vem acompanhando este curso desde o seu início, a compreensão
será moleza!
Notas: 1º. Observe que alguns códigos são novos; outros, não (visto que já estavam no Editor); 2º Impeça que o usuário
digite no ComboBox e altere o seu texto inicial, de acordo com a fonte padrão em seu sitema.

UpDown: Associate = Edit1; Max = 72; Min = 1.

//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)


{
// ComboBox com os nomes das fontes instaladas no sistema
ComboBox1->Items->Assign(Screen->Fonts);

PopupMenu1 -> AutoPopup = true;


RichEdit1 -> PopupMenu = PopupMenu1;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::RichEdit1KeyUp(TObject *Sender, WORD &Key,


TShiftState Shift)
{
//atualiza o tipo (Name) de font no ComboBox
ComboBox1->Text = RichEdit1->SelAttributes->Name;

//Atualiza o tamanho (Size) da font em Edit1


Edit1->Text = RichEdit1->SelAttributes->Size;

//atualiza o estado (Down) do botão de sublinhado


SpeedButton10->Down = RichEdit1->SelAttributes->Style.Contains(fsUnderline);

//atualiza o estado (Down) dos botões - alinhamento de texto


if(RichEdit1->Paragraph->Alignment == taLeftJustify)

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 11 de 15

SpdBtAlinhEsq->Down = true;
else if(RichEdit1->Paragraph->Alignment == taCenter)
SpdBtAlinhCent->Down = true;
else if(RichEdit1->Paragraph->Alignment == taRightJustify)
SpdBtAlinhDir->Down = true;

}
//---------------------------------------------------------------------------

void __fastcall TForm1::ComboBox1Change(TObject *Sender)


{
// O tipo de font de RichEdit1 será igual os especificado em ComboBox1
RichEdit1->SelAttributes->Name = ComboBox1->Items->Strings[ComboBox1->ItemIndex];
// Coloca o foco em RichEdit1
RichEdit1->SetFocus();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Edit1Change(TObject *Sender)


{
// O size da font de RichEdit1 será
// igual ao especificado em Edit1
RichEdit1->SelAttributes->Size = atoi(Edit1->Text.c_str());
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Edit1MouseDown(TObject *Sender,


TMouseButton Button, TShiftState Shift, int X, int Y)
{
// impede que o usuário digite no Edit
RichEdit1->SetFocus();
}
//---------------------------------------------------------------------------

A seguir, entraremos na parte final da construção do nosso editor, aprendendo a construir uma régua através da qual
poderemos estabelecer limites para os textos com os quais estivermos trabalhando.

Passemos agora à construção da régua naquele segundo componente Panel já colocado no Editor. Visualize previamente a
disposição dos componentes da régua:

Eis as propriedades de Panel2:

Propriedades Align = alTop


Alignment = taLeftJustify
Bevellnner = bvLowered
BevelWidth = 1 //profundidade da borda
BorderWidth = 1 //largura da borda

Coloque um Bevel (paleta Additional) dentro do Panel e procure deixá-lo parecido com uma linha que divida o
comprimento do Panel em duas partes iguais (conforme ilustração). Eis as propriedades:

Propriedades de Bevel1 Align = alNone


Height = 2
Left = 4

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 12 de 15

Shape = bsTopLine
Stile = bsLowered

Coloque um Label (Label1) acima do Bevel e outro abaixo (Label2)

Propriedades de Label1
AutoSize = true
Caption = ê
DragCursor = crArrow
Font = Charset = DEFAULT_CHARSET
Color = clRed
Height = -11
Name = Wingdings
Pitch = fpDefault
Size = 8
Stile = []
Height = 11
Left = 2

No Label2 as propriedades são as mesmas, exceto Caption = é

Coloque outro Label no Panel. O Label3 deverá ser colocado próximo à extremidade direita inferior do componente Panel1,
com as mesmas propriedades supramencionadas para Label1 e Label2, excetuando sua propriedades Caption que será = ñ,
Font Color = clBlue e Left = 770. Uma vez adotadas essas providências, a régua de nosso projeto já deverá estar parecida
com a ilustração acima.

Vá para o Editor de Códigos e, na paleta onde está escrito o nome do arquivo (se não foi alterado quando salvo, deve
chamar-se: Unit1.cpp) dê um clique com o botão direito do mouse e escolha: Open Sourse/Hearder File ou simplesmente
aperte as teclas Ctrl + F6. Será aberto outro arquivo, o Unit1.h.
Em class TForm1 : public TForm, __published: declare o protótipo da função MudarParag() e, na parte privada da Classe,
declare os dados membros: int Arrastar e bool Arrastando e a função void __fastcall Regua(void). A parte privada fica entre
a declaração private e a declaração public. Observe abaixo como deverá ficar o código:

(...)
class TForm1 : public TForm
{
__published:
(...)
void __fastcall MudarParag(TObject *Sender);

private: // User declarations


(...)
int Arrastar;
bool Arrastando;
void __fastcall Regua(void);

public: // User declarations

__fastcall TForm1(TComponent* Owner);


};
(...)

Nota: os trechos (...) não constituem parte integrante do código, mas indicam que trechos do mesmo foram suprimidos
porque, no momento, não nos interessa vê-los.
Não se esqueça de introduzir comentários indicando tratar-se de linhas de código para régua!
Volte para o arquivo Unit1.cpp e faça o seguinte:
Declare e inicialize duas constantes globais:

//-------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

//distância que o cursor fica da seta conforme a movimentamos


const float Reg = 4.0 / 3.0;

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 13 de 15

//Distância dos dois Labels da margem esquerda


const int Semp = 6;
//-------------------------------------------------------------------
#pragma package(smart_init)

Passemos à definição da função void __fastcall TForm1::MudarParag(TObject * Sender):

/************digite todo o código abaixo, inclusive o cabeçalho da


função, pois essa função não foi criada automaticamente
pelo compilador, mas por nós.
observe que os comandos if() estabelecem posições
limítrofres para os componentes Label***************/
void __fastcall TForm1::MudarParag(TObject * Sender)
{
Label1->Left = int(RichEdit1->Paragraph->FirstIndent*Reg)-4+Semp;
if (Label1->Left >= 772)
Label1->Left = 770;

Label2->Left = int((RichEdit1->Paragraph->LeftIndent+
RichEdit1->Paragraph->FirstIndent)*Reg)-4+Semp;
if (Label2->Left >= 770)
Label2->Left = 748;

Label3->Left = Panel1->ClientWidth-6-int(
(RichEdit1->Paragraph->RightIndent+Semp)*Reg);
if (Label3->Left >= 772)
Label3->Left = 770;
if (Label3->Left <= 12)
Label3->Left = 13;
}
TparaAttributes::FirstIndent - FirstIndent especifica a distância, em pixels, da primeira linha de um parágrafo relativa à
margem esquerda.
TparaAttributes::LeftIndent - LeftIndent especifica a distância, em pixels, do parágrafo relativa à margem esquerda.
TparaAttributes::RightIndent - RightIndent especifica a distância, em pixels, do parágrafo relativa à margem direita.
TcustomRichEdit.Paragraph - Paragraph especifica a informação de formatação do atual parágrafo. Interprete Paragraph
para colocar objeto TParaAttributes usado por controle rich edit para especificar a informação da formatação do parágrafo.
Use o objeto TParaAttributes para ler ou escrever a informação da formatação do parágrafo para o atual parágrafo. Estas
informações incluem alignment, indentation, numbering e tabs. Paragraph é uma propriedade read-only, porque um objeto
TCustomRichEdit possui somente um objeto TParaAttributes, que não pode ser mudado. Os atributos do corrente
parágrafo, entretanto, pode ser mudado pela colocação marcação da propriedade do objeto TParaAttributes. Estes pode ser
setados um por um, ou todos podem ser setados para um valor de um objeto TParaAttributes existente pelo uso
Paragraph->Assign.
O parágrafo atual são os parágrafos que contém o texto selecionado. Se não há texto selecionado, o atual parágrafo é aquele
que contém o cursor.
Nota: Paragraph está disponível somente em tempo de execução.

Na paleta Events de RichEdit1, em OnSelectionChange selecione a função MudarParag, o que fará que as setas Lable(s)
sejam atualizadas conforme o movimento do cursor no texto.
Nota: para efetuar a associação acima, dê um clique no lado direito do evento mencionado no Object Inspector. Dê um
clique na seta que aparecerá e escolha a função mencionada no combobox que se abrirá.
Passaremos agora à definição da função void __fastcall TForm1::Regua(void). Não se esqueça de que esta função não foi
criada automaticamente pelo C++Builder:

void __fastcall TForm1::Regua(void)


{
int Distanc = 0; // variável para o contador
while (Distanc < 15) // números da régua
{
Distanc++; //incremento
// imprime os números de 1 a 15 na régua
Panel1->Caption = Panel1->Caption + '\t' + Distanc;
}
}

Nota: Seria interessante colocar, manualmente, aquelas linhas de comentários usadas pelo compilador C++Builder (//---------
-) para separar essas instruções.
Precisamos fazer o compilador chamar a função acima na criação do formulário (evento OnCreate do Form):

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 14 de 15

void __fastcall TForm1::FormCreate(TObject *Sender)


{
// chama a função régua na criação do formulário
Regua();
(...)
}

Ajuste a propriedade Height de Bevel1 para 1.


A régua ainda não está funcional, mas já pode ser visualizada em tempo de execução.

Inicialmente vamos nos lembrar das funcionalidades básicas dos eventos OnMouseDown, OnMouseMove e OnMouseUP:

Tcontrol::OnMouseDown - OnMouseDown ocorre quando, estando o ponteiro do mouse sobre um controle, o usuário
pressiona um botão do mouse. O evento OnMouseDown pode responder ao pressionamento sobre os botões esquerdo,
direito e central do mouse, bem como sobre combinações entre botões do mouse com as teclas Shift, Ctrl, e Alt. X e Y são
as coordenadas (pixel) do ponteiro do mouse na client area do Sender.
Tcontrol::OnMouseMove - OnMouseMove ocorre quando o usuário move o ponteiros do mouse, enquanto o ponteiro do
mouso está sobre algum controle. Podemos usar o parâmetro Shift do evento OnMouseDown para determinar o estado das
teclas (ou combinações) mencionadas no tópico anterior ( OnMouseDown ). X e Y são as coordenadas (pixel) da nova
localização do ponteiro do mouse client area do Sender .
Tcontrol::OnMouseUp – OnMouseUp ocorre no momento em que o usuário está liberando o botão do mouse que estava
pressionando um componente com o ponteiro do mouse. O evento OnMouseUp pode responder a ações sobre os botões
esquerdo, direito e central do mouse, bem como sobre combinações entre botões do mouse com as teclas Shift, Ctrl, e Alt.
X e Y são as coordenadas (pixel) do ponteiro do mouse na client area do Sender.

Passemos ao tratamento desses eventos nos componentes envolvidos nas ações respectivas. Inicialmente vamos escrever
uma função responsável pelo evento OnMouseDown, associando-a aos componentes respectivos. Em Unit1.h, na parte
__published, declare o protótipo da função AreguaMouseDown():

void __fastcall AReguaMouseDown(TObject *Sender, TMouseButton Button,


TShiftState Shift, int X, int Y);

Agora, em Unit1.cpp:

void __fastcall TForm1::AReguaMouseDown(TObject *Sender,


TMouseButton Button, TShiftState Shift, int X, int Y)
{
TLabel * oTmpLabel = (TLabel *)Sender;
Arrastar = oTmpLabel->Width / 2;
oTmpLabel->Left = oTmpLabel->Left+X-Arrastar;
Arrastando = True;
}

Vá ao Object Inspector e, na guia Events, associe os eventos OnMouseDown de Label1, Label2 e Label3 à função
AreguaMouseDown (do mesmo modo que procedemos para associar RichEdit1 a OnSelectionChange).

Agora vamos tratar o evento OnMouseMove. O procedimento é bem parecido com o anterior. Em __published de Unit1.h:

void __fastcall AReguaMouseMove(TObject *Sender, TShiftState Shift,


int X, int Y);

Em Unit1.cpp:

void __fastcall TForm1::AReguaMouseMove(TObject *Sender, TShiftState Shift,


int X, int Y)
{
if (Arrastando) {
TLabel * oTmpLabel = (TLabel *)Sender;
oTmpLabel->Left = oTmpLabel->Left+X-Arrastar;
}
}

Vá ao Object Inspector e, na guia Events, associe os eventos OnMouseMove de Label1, Label2 e Label3 à função
AReguaMouseMove.

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013
editor de texto Página 15 de 15

No que se refere a OnMouseUP, Label1, Label2 e Label3 não compartilham o mesmo evento. Devemos, então, proceder ao
tratamento individual para cada componente. Iniciemos por Label1. Na guia Events, dê um clique em OnMouseUp, para
chamar o método correspondente. Eis o código:

void __fastcall TForm1::Label1MouseUp(TObject *Sender, TMouseButton Button,


TShiftState Shift, int X, int Y)
{
Arrastando = False;
RichEdit1 -> Paragraph -> FirstIndent =
int((Label1->Left+Arrastar-Semp) / Reg);
Label2MouseUp(Sender, Button, Shift, X, Y);
}

Eis o código para o evento OnMouseUp de Label2:

void __fastcall TForm1::Label2MouseUp(TObject *Sender, TMouseButton Button,


TShiftState Shift, int X, int Y)
{
Arrastando = False;
RichEdit1->Paragraph->LeftIndent =
int((Label2->Left+Arrastar-Semp) / Reg)-RichEdit1 ->Paragraph ->FirstIndent;
MudarParag(Sender);
}

Aqui está o código para o mesmo evento de Label3:

void __fastcall TForm1::Label3MouseUp(TObject *Sender, TMouseButton Button,


TShiftState Shift, int X, int Y)
{
Arrastando = False;
RichEdit1->Paragraph->RightIndent =
int((Panel2->ClientWidth-Label3->Left+Arrastar-2) /
Reg)-2*Semp;
MudarParag(Sender);
}

Ajuste a Propriedade TabStop dos controles RichEdi1, ComboBox1 e Edit1 para false (para impedir que o foco saia de
RichEdit1 quando for pressionada a tecla de tabulação); Ajuste a Propriedade WantTabs de RichEdit1 para true (ativará a
marcação de textos com tabulações nesse componente).

Assim, conforme prometido no início deste curso, completamos o nosso Editor de Textos. Na verdade, fomos além daquilo
que propusemos, uma vez que esse editor não está limitado a edição de textos não formatados como o Bloco de Notas do
Windows. Para criar um Editor como o NotePad, use um componente Memo no lugar do RichEdit, mas com consciência de
que as formatações possibilitadas por este Editor estarão ausentes naquele!

Por fim, informamos que o nosso Editor pode ser melhorado. Agora cabe a você procurar as falhas e corrigi-las, uma vez
que o tratamento de erros ou melhora na lógica dos comandos é uma obrigação fundamental de todos os programadores.

A seguir, dando continuidade no curso, estaremos trabalhando na finalização do projeto Paint, visto que já possuímos
praticamente todos os conceitos necessários à sua conclusão.

VMS Desenvolvimentos
Diversas Dicas, Apostilas, Arquivos Fontes, Tutoriais, Vídeo Aula, Download de Arquivos Relacionado a Programação em C++ Builder.
Voltar ao Site

http://vmsdesenvolvimentos.50webs.com/tutoriais/editor_texto/index.html 12/11/2013

Você também pode gostar