Delphi@Brasil Magazine - Janeiro 98


Tópico do mês : Continuação da criação de um componente do tipo painel de status.

- Mês passado terminamos nossa matéria no ponto em que estavamos tornando propriedades pertencentes à TCustomPanel published, tornando assim as propriedades visíveis ao Object Inspector. Porém se quisermos que nosso objeto tenha uma característica diferente das padões quando da sua criação(notar que a criação de um componente visual se dá tanto em tempo de execução quanto em tempo de projeto), precisamos sobreescrever um método que dentro da OOP é chamado normalmente de método construtor, e no Delphi têm como rótulo método Create.

- O método Create nos fornece meios de inicializar nosso objeto, e para isso nos precisamos apenas solicitar ao Delphi que ao criar o componente execute o nosso método Create sobrescrito(ou Override na linguagem Delphi), ao invés de seu Create padrão. Abaixo nos podemos ver na figura I, como fica a declaração de nosso método Create, notar que o Create sempre têm que ser declarado como Public, pois de outra maneira não poderíamos sequer criar o componente em tempo de execução.

Figura I.

- Verificar a palavra chave Override, após a declaração do Constructor Create. O Override nada mais faz do que indicar ao Delphi que a inicialização do componente agora será feita por nós, e não pelo método que foi herdado de seu ancestral TCustomPanel. Porém a simples declaração do constructor não faz nada se não escrevermos o código relativo a este que pode ser visualizado na figura II (notar que é apenas o código marcado).

Figura II

- Verifique que na nossa inicialização fazemos uso de um comando chamada Inherited, que nos auxilia a chamar um método de qualquer componente ancestral do nosso, bastando para isso após a declaração do Inherited passarmos o método que queremos executar e como parâmetro do método o objeto ancestral que é recebido pelo parâmetro AOwner. Agora perceba a ligação entre como é declarado o método Create(AOwner : TCompont) e a declaração inicial do nosso tipo de objeto(vide a edição Dezembro/98), TStatusPanel = Class(TCustomPanel), ou seja o nosso Create têm como parâmetro o ancestral do tipo TCustomPanel, assim como todos os componentes da VCL precisam ter um ancestral para poderem existir. O motivo principal de chamarmos a inicialização de TCustomPanel é eliminarmos a redundancia de código já que nosso TCustomPanel inicializa diversas propriedades que batem com as propriedades que desejamos que nosso objeto possua, simplemente após inicializarmos como um TCustomPanel, mudamos a propriedade BevelOuter := bvLowered. Quem quiser saber mais sobre a inicialização de TCustomPanel pode dar uma olhada na figura III que está o código do Create de TCustomPanel.

Figura III

- Notar que o próprio TCustomPanel chama o Create do seu ancestral(que no caso é TCustomControl, o qual por sua vez têm como ancestral TWinControl, e deste também herda seu Create), agora imagine a quantidade de código precisariamos escrever se não fossémos pelo caminho de chamar o Create de nosso ancestral.

- Agora iremos dar uma funcionalidade real ao nosso componente. Inicialmente vamos declarar um tipo set(conjunto), que em breve notaremos que será os elementos de um ComboBox visualizado no Object Inspector. Declare nosso Set logo abaixo da palavra chave Type e antes da declaração de TStatusPanel, da seguinte forma :

TOpcoesApto = ( apVendido, apDesocupado, apAtraso);

- Notar que seguimos a notação do Delphi que ao criarmos conjunto de propriedades, sempre iniciarmos com letras minúsculas, descrevendo de que tipo de conjunto o elemento veio. Feito isto declaramos duas propriedades Privates (só têm visibilidade dentro da própria Unit, ou seja, um usuário de nosso componente não pode setar nem ler essas propriedades), da forma que está escrito abaixo logo após a palavra chave Private :

FOpcoesApto : TOpcoesApto;

FTamanhoBorda : Integer;

- Mais uma vez seguimos a notação do Delphi ao colocar o "F" como prefixo de nossas variáveis, o F vêm de Field ou Campo em inglês, para indicar que é um campo para trabalho de variáveis internas e intrinsécas ao componente, e não para uso de usuários de nosso componente. O primeiro campo servirá para o controle de que opção está setado o componten como por exemplo se o valor de FOpcoesApto for igual a apVendido significa que o nosso componente vai mostra o status de um apartamento vendido. A segunda propriedade servirá para controlarmos a largura da borda de nosso painel como veremos adiante.

- Agora vamos declarar alguns métodos internos do nosso componente, por este motivo eles serãodeclarados logo abaixo dos campos acima comentados, na parte private de nossa unit, e terão esta forma :

Procedure SetDisplayOptions( Value : TOpcoesApto);

Procedure SetTamanhoBorda(Value : Integer);

- Estes métodos serão os responsáveis por setar as propriedades do status do painel(SetDisplayOptions) e o tamanho da borda de nosso painel(SetTamanhoBorda), perceba bem como os argumentos que são passados por eles são dos mesmos tipos de nossos campos, declarados anteriormente. Agora vamos ver na figura IV o código relativo aos dois métodos :

Figura IV

- Os métodos são relativamente simples apenas verifica se a nova opção escolhida que é passada como parâmetro é diferente da atual, se verdade então iguala a propriedade à opção passada e executa um Refresh(que será declarado adiante). O truque de verificar de se a propriedade é diferente e só assim mudar é para evitar por exemplo que em componentes visuais aja um flique do componente, mesmo que a propriedade tenha sido escolhido no Object Inspector mas não alterada.

- Vemos agora dar uma olhada no nosso método Refresh na figura V.

Figura V.

- O método Refresh deve ser declarado dentro das propriedades Protected. O código de Refresh é muito simples, apenas seta de forma correta as novas propriedades de nosso componente.

- Agora para terminar nosso componente basta publicar propriedades que nos permitam a partir do Object Inspector visualizar nossas propriedades, e como vimos na edição passada para isto basta publicarmos nossas propriedades como Published. Abaixo vemos a declaração :

property OpcoesApto : TOpcoesApto read FOpcoesApto write SetDisplayOptions default apDesocupado;

property TamanhoBorda : Integer read FTamanhoBorda write SetTamanhoBorda default 10;

- Verificamos agora uma nova maneira de declara um propriedade já que entraram as palavras chavs read, set e default. Como o próprio nome diz o responsável pela leitura da propriedade para mostrar no Object Inspector é o método ou propriedade logo após a declaração do mesmo, no caso da propriedade OpcoesApto o responsável pela leitura da propriedade é o próprio campo FOpcoesApto, já na escrita da propriedade o responsável é o método declarado anteriormente SetDisplayOptions. Já a palavra chave Default nos indica o valor padrão de nosso componente quando da sua criação.

- Para podermos instalar nosso componente só falta inlcuirmos mais duas linhas no método create de nosso componente como as linhas abaixo :

Cursor := crHelp;

Refresh;

- Isso nos indica que o cursor ao passar por nosso componente terá a forma de uma interrogação, e que ao ser criado devemos dar um Refresh para que o mesmo seja inicializado corretamente.

- Agora podemos finalmente instalar no novo componente a partir da opção Install Component do menu Component, na caixa de diálogo que nós é exibida (figura VI) escolhemos a unit do nosso componente e clicamos em Ok, a nossa VCL será recompilada e o nosso componente finalmente instalado

Figura VI

- Após intalarmos o nosso componente podemos vê-lo em ação como na figura VII. e VIII.

Object Inspector de nosso Painel

Figura VII

Nosso Componente em ação

Figura VIII

- Se preferirem podem pegar o fonte deste componente direto nesta página, bastando para isso clicar aqui.

- Esperamos que as informações aqui contidas tenha lhe sido de grande utilidade. Venho reforçar o pedido para que se desejarem entrem em contato conosco por meio de [email protected] , e também espero no próximo mês já encontrá-los no nosso domínio próprio.

 

Fúlvio C. Albuquerque

Editor Responsável

 

Hosted by www.Geocities.ws

1