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.
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.
Nesta caixa de diálogo definimos informações referentes ao nosso novo componente conforme explicação:
- Ancestor type: Classe "pai" do nosso componente, ou seja, de qual classe nosso componente será "parente". No caso TComponent.
- Class Name: Nome da nova classe que estamos criando. Vamos usar em nossos exemplos o prefixo "ex" de exemplo para todas as classes.
- Pallete Page: Em qual paleta do Delphi nosso componente será instalado.
- Unit file name: Informe ao Delphi em qual diretório será salvo nosso componente.
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.
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.
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.
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.
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.
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.
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.
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
...
...
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;
...
Ó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.
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo