Mini-curso - Criando componentes

Veja neste artigo de Adriano Santos, a Parte I do mini-curso sobre criação de componentes.

Bem amigos, há muito tempo que venho querendo ministrar um curso para ensinar a desenvolver componentes em Delphi. É uma forma de aprender mais e passar o conhecimento que obtive com meus colegas do fórum e com alguns livros que li. Então mãos à obra, pois temos muito trabalho a fazer.

Conhecendo a estrutura

No início o desenvolvimento de componentes, confesso, é um pouco confuso, mas logo você irá se apaixonar por seus próprios componentes, prometo.

A primeira coisa que se deve ter em mente é que componentes são desenvolvidos sem auxílio pleno no que diz respeito a visual, ou seja, é basicamente a digitação de classes, procedures e functions. Por isso é necessário se ter uma boa noção de como criar procedimentos, funções, classes e etc.

Você deve estar se perguntando: Na Internet existem milhares de componentes gratuitos e até com código fonte aberto, porque desenvolvê-los? Para responder esta questão faço uso de duas palavras que resumem tudo: controle e personalização. Nem sempre encontramos componentes que se encaixem com nossa realidade, daí surge a necessidade de criá-los.

Para este nosso primeiro artigo, vamos criar um componente bem interessante e útil. O TexTabToEnter. O componente fará o trabalho de trocar o tab pelo enter em toda a aplicação. Calma, calma. A ideia inicial é que possamos ver o básico da criação de um componente, pois o TexTabToEnter existe aos montes na grande teia, vamos apenas treinar.

Nota: Usarei o prefixo “ex” para todos os componentes que criaremos em nossos exemplos.

Por onde começar?

O início de um projeto de componente é bem mais simples do que muitos imaginam.

Abra o Delphi e logo em seguida feche o projeto default que se abre usando a opção Close All no menu File. Depois disso basta acionar a opção New Component presente no meu Component. Uma caixa de diálogo aparecerá (veja Figura 1) e nela vamos preencher alguns parâmetros.

Figura 1. Diálogo de criação do componente

Nesta caixa de diálogo definimos informações referentes ao nosso novo componente conforme explicação:

Após a configuração dessas informações basta clicar em Ok para que o Delphi crie pra nós o escopo inicial de nosso componente e olhando com atenção para nossa nova Unit vemos que existem algumas seções que não encontramos em nossos programas (veja a Listagem 1).

unit exTabToEnter; interface; uses SysUtils, Classes; type TexTabToEnter = class(TComponent); private {Private Declarations} protected {Protected Declarations} public {Public Declarations} published {Published Declarations} end; procedure Register; implementation procedure Register; begin RegisterComponents('ClubeDelphi', [TabToEnter]); end; end.
Listagem 1. Unit do nosso componente ainda sem nenhuma implementação

Implementando funcionalidades

Para este primeiro projetos, vamos fazer algo bem simples.

Nosso componente será responsável por fazer com que o Enter funcione como TAB em nossos sistemas.

A mágica consiste em “desviar” o evento onMessage do objeto TApplication para uma função Execute do componente que por sua vez fará a “troca” de Tab para Enter.

Nota: Na verdade não faremos a troca, afinal de contas o tab continuará tendo sua funcionalidade.

Vamos precisar de apenas uma propriedade: Ativo do tipo Boolean. Esta propriedade quando ativa será checada pela procedure Execute realizando a tarefa desejada. Para criar uma propriedade basta usar a palavra reservada property na seção Published. Esta seção é responsável por publicar nossas propriedades no Object Inspector, ou seja, será visível para o desenvolvedor em tempo de projeto. (veja a Listagem 2).

unit exTabToEnter; interface; uses Windows, Messages, SysUtils, Classes; type TabToEnter = class(TComponent); private {Private Declarations} FAtivo : Boolean; protected {Protected Declarations} public {Public Declarations} published {Published Declarations} property Ativo: Boolean read FAtivo write FAtivo; end; procedure Register; implementation procedure Register; begin RegisterComponents('ClubeDelphi', [TabToEnter]); end; end.
Listagem 2. Declaração da propriedade Ativo

Como podemos notar, fizemos a declaração da propriedade em Published e a criação de uma variável (FAtivo) em private. O efe “F” na frente da variável é uma convenção e significa Field.

Nota: Quando criamos a propriedade informamos a ela que a leitura (read) e sua escrita (write) será feita através do campo FAtivo.

Para finalizar nosso componente precisamos implementar os métodos: Constructor (construtor), Destructor (destrutor) e Execute (executar, este método fará a principal tarefa do componente).

Para isso faça as declarações dos métodos como na Listagem 3 e logo em seguida pressione Ctrl + Shift + C, isso fará com que o Delphi crie automaticamente o corpo dos métodos.

Para este artigo não há necessidade de fazer mudanças ou inserção de algorítimos em nosso construtor e destrutor. Já no método Execute você terá que programar a tarefa que este componente terá que realizar. A listagem completa está presente em Listagem 3.

unit exTabToEnter; interface; uses Windows, Messages, SysUtils, Classes; type TabToEnter = class(TComponent); private {Private Declarations} FAtivo : Boolean; protected {Protected Declarations} public {Public Declarations} constructor Create(AOWner: TComponent); override; destructor Destroy;override; procedure Execute(var Msg: TMsg; var Handled: Boolean); published {Published Declarations} property Ativo : Boolean read FAtivo write FAtivo; end; procedure Register; implementation procedure Register; begin RegisterComponents('ClubeDelphi', [TabToEnter]); end; procedure TexTabToEnter.Destroy; begin inherited; end; procedure TexTabToEnter.Constructor(AOWner: TComponent); begin inherited; end; procedure TexTabToEnter.Execute; begin if (FAtivo) or not (csDesigning in ComponentState) then begin if not ((Screen.ActiveControl is TCustomMemo) or (Screen.ActiveControl is TCustomGrid) or (Screen.ActiveControl is TButton) or (Screen.ActiveControl is TBitBtn) or (Screen.ActiveForm.ClassName = 'TMessageForm')) then if (Msg.message = WM_KEYDOWN) then Case Msg.wParam of VK_RETURN,VK_DOWN: Screen.ActiveForm.Perform(WM_NextDlgCtl, 0, 0); VK_UP: Screen.ActiveForm.Perform(WM_NextDlgCtl,1,0); end; end else Application.OnMessage := nil; end; end.
Listagem 3. Listagem completa do componente
Nota: No trecho de código “not (csDesigning in ComponentState)” verificamos se o componente está sendo usando em tempo de design, ou seja, ainda na IDE do Delphi e então passamos o valor nil para ele. Do contrário os diálogos do Delphi iriam adquirir a funcionalidade do componente, trocando o Tab pelo Enter.

Declaração

Como dito anteriormente, existem quatro seções na unit do componente, diferente do que estamos acostumados a ver no dia-a-dia. São elas: private, public, protected e published.

As propriedades podem ser declaradas em qualquer seção, porém apenas na seção published é que estarão visíveis no Object Inspector. Cada propriedade necessita de uma função ou campo para leitura e escrita. Os campos são na verdade variáveis precedidas do prefixo "F", uma convenção da Borland que significa Field (campo) e não podem ser declaradas na seção published. Também é comum criarmos funções e procedimentos para a leitura e escrita da propriedade quando necessário. O mais comum é que todas as variáveis sejam declaradas na seção private, pois apenas o componente terá acesso a elas.

Caso a propriedade necessite de um tratamento especial então criamos uma função para leitura e um procedimento para escrita, veremos mais a seguir um exemplo prático.

Declaração na prática

Faremos a criação de um componente capaz de capturar os erros em nossos aplicativos e o mostraremos de uma mensagem mais amigável para o usuário final. Para isso criaremos as seguintes propriedades apresentadas na Tabela 1.

Propriedade Tipo Finalidade
Ativo Boolean Ativa e Desativa o componente
Mensagem String Mensagem ao usuário
Dialogo TTipoDialogo Tipo de mensagem que será exibida

Tabela 1. Propriedades do novo componente.

Prática

Abra o Delphi e crie a unit do novo componente. Daremos o nome de TexCapturaErro e o criaremos paleta ClubeDelphi. Declare as propriedades como na Listagem 4.

unit exCapturaErro; interface uses SysUtils, Classes, Dialogs, Forms; type TTipoDialogo = (tdAviso, tdErro, tdInformacao); type TexCapturaErro = class(TComponent) private { Private Declarations } FAtivo : Boolean; FMensagem : string; FTipoDialogo : TTpoDialogo; proctected { Protected Declarations } constructor Create(AOWner: TComponent);override; public { Public Declarations } published { Published Declarations } property Ativo : Boolean read FAtivo write FAtivo; property Mensagem : String read FMensagem write FMensagem; property TipoDialogo : TTipoDialogo read GetDialogo write SetDialogo; end; procedure Register; implementation procedure Register; begin RegisterComponents('ClubeDelphi', [TexCapturaErro]); end; procedure Create(AOWner: TComponent); begin inherited; Application.OnException := Execute; end; end.
Listagem 4. Declaração de variáveis e propriedades

Algumas explicações

Logo abaixo do uses de nosso componente criamos um novo tipo, o TTipoDialogo. Isso é que o chamamos de variáveis tipadas. Nosso usuário poderá escolher se o componente irá mostrar uma mensagem de Aviso, Erro ou apenas uma Informação.

Para o uso disso, basta declarar uma variável/campo do mesmo tipo declarado acima. E também declarar nossa property do mesmo tipo usando para leitura e escrita a variável declarada.

Após declaradas as propriedades, basta pressionar Ctrl + Shift + C para que o Delphi crie automaticamente o escopo das funções/procedimentos necessários.

Repare que criamos um construtor para o novo componente, nos próximos artigos veremos mais detalhadamente como funcionam. O código para a leitura e escrita da propriedade TipoDialogo é bem simples. (veja Listagem 5.)

... funtion TexCapturaerro.GetTipoDialogo: FTipoDialogo; begin Result := FTipoDialogo; end; procedure TexCapturaerro.SetTipoDialogo(Value: FTipoDialogo); begin FTipoDialogo := Value; end; ... end.
Listagem 5. Leitura e Escrita da propriedade TipoDialogo

Função Execute

Agora precisamos desenvolver o algoritmo que capturará mostrar a mensagem ao usuário. Declare a função Execute como na Listagem 6 e seu algoritmo como na Listagem 7.

... public { Public Declarations } procedure Execute(Sender: Tobject; E: Exception); published ...
Listagem 6. Leitura e Escrita da propriedade TipoDialogo
... procedure TexCapturaerro.Execute(Sender: Tobject; E: Exception); var Dialogo : TMsgDlgType; begin if FAtivo then begin case FTipoDialogo of tdAviso : mtWarning; tdErro : mtError; tdInformacao : mtInformation; end; Beep; MessageDlg(FMensagem + #13#13#13 + E.Message, Dialogo, [mbOk], 0); end else Application.ShowException(E); end; ...
Listagem 7. Leitura e Escrita da propriedade TipoDialogo

Ótimo, agora basta instalar o componente e testar.

Conclusões

Neste artigo entendemos melhor como funciona a declaração de variáveis incluído variáveis tipadas.

Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados