segunda-feira, 29 de outubro de 2007

Linguagem de Programação C++

Oi, hoje vamos falar sobre C++, uma linguagem de programação pouco falada aqui no blog.


Introdução

A linguagem C++ foi desenvolvida inicialmente por Bjarne Stroustrup na AT&T, de 1979 a 1983, à partir da linguagem C, tendo como idéia principal a de agregar o conceito de classes, de orientação à objetos, àquela linguagem. Razão porque inicialmente chamva-se de “C com classes”. Bjarne procurou tanto quanto possível manter retrocompatibilidade com C, de modo que programas em C pudessem ser compilados por um compilador C++ com um mínimo de alterações. Entretanto, encarar C++ como um superconjunto de C é um erro, e C++ deve ser vista como uma “outra linguagem”, por diversas razões. Em primeiro lugar, nem todo o programa escrito em C é compilado em C++ sem erros, e pode nem mesmo gerar o mesmo resultado, já que a sintaxe e a semântica de algumas construções diferem. Ao ligar-se partes de um programa em C++ com partes em C, estas devem ser bem especificadas, pois as convenções de funcionamento do código compilado também diferem. Além disso, C++ oferece um conjunto de mecanismos básicos que não estavam presentes em C, e estes devem ser usados para produzir software mais modular e confiável explorando-se as verificações disponíveis no compilador. Finalmente, os mecanismos de C++ devem inspirar a programação segundo o paradigma de orientação a objetos e, portanto, não se deve programar em C++ como se faz em C.

A partir da primeira versão de 1983, a linguagem foi sendo revisada e evoluindo, tornou-se disponível fora da AT&T em 1985, e após um longo processo foi padronizada pela ISO no final de 1997, pelo padrão ISO/IEC 14882. Você pode obter mais informações sobre o desenvolvimento da linguagem na página do próprio autor em [STR 2004].

STL é uma parte do padrão C++, e consiste em uma biblioteca de funções e estruturas de dados que todo compilador C++ deve oferecer, provê as implementações mais comuns em um programa, e pode-se utilizá-la com diferentes tipos de dados. Um bom ponto de partida para leitura específica sobre STL é na página da Silicon Graphics, Inc. em [STL 2004].

De forma geral, é possível obter muito material de referência da linguagem através de páginas na Internet. Tente por exemplo pesquisar com a expressão “C++ reference” no Google. Também é muito produtivo criar o hábito de pesquisar por problemas bem específicos. Tente, por exemplo, pesquisar “iostream.h iostream difference”, ou “STL hash_map code example”. Pode-se obter cursos [BRA 1998], livros e exemplos de código [ECK 2000]

Os compiladores do projeto GNU também podem ser obtidos livremente através da Internet. O ambiente BloodShed Dev-C++ roda sobre Windows e utiliza os compiladores gcc e g++. É possível baixá-lo de: http://www.bloodshed.net/devcpp.html. Há também inúmeros fóruns e listas de discussão sobre aspectos técnicos da linguagem.



Artigo completo (View Full Post)

terça-feira, 9 de outubro de 2007

Turbinando o Firefox

Se vocês usam firefox, tem um macete que vai fazer ele abrir mais rápido.

1-Abra o firefox e digite na barra de endereços: "about:config" (sem aspas)

Desça a página e procure pelas seguintes entradas(está em ordem alfabética, acho que ninguém aqui vai ter dificuldade pra achar):

Código:
network.http.pipelining
network.http.proxy.pipelining
network.http.pipelining.maxrequests

Normalmente o browser só pede pela página uma vez, mas habilitando o pipelining, ele vai fazer isso varias vezes, fazendo com que a página carregue mais rapidamente.

2-Troque os seguintes valores:

Código:
"network.http.pipelining" d "false" pra "true"

"network.http.proxy.pipelining" d "false" pra "true"

"network.http.pipelining.maxrequests" d "0" pra "8"

3- Por último clique com o botão direito do mouse em qualquer lugar da página e escolha: nova>inteira

Coloque o nome de "nglayout.initialpaint.delay"(sem as aspas) e coloque seu valor como "0"(esse valor é o número de vezes que o seu browser vai esperar ate agir nas informações que recebe).

Agora feche o firefox, abra de novo e ai esta: Demais!!

Funciona mesmo , eu testei e aprovei.



Artigo completo (View Full Post)

segunda-feira, 17 de setembro de 2007

Construção de Componentes IV

Na seqüência de artigos sobre criação de componentes você pode observar que podemos criar um componente funcional, pronto para ser instalado na paleta de Componente. Vimos que é possível testar o novo componente, tanto em tempo de design, quanto em runtime Vimos também que, mesmo depois de instalado, você pode acrescentar novas funcionalidades, e características, recompilar e re-instalar o componente e continuar a testa-lo.

Em seguida listaremos alguns passos básicos que você deve executar sempre que for criar um componente novo:

1 Criar uma unidade (unit) para o componente novo:
No menu File ► New ►Unit

2 Derivar seu componente de um tipo de componente pré-existente, descendente direta ou indiretamente da VCL.

3 Adicionar novas properties (propriedades), methods (métodos), e events (eventos).

4 registrar seu componente na IDE.

5 Criam um bitmap para o componente. De maneira que na palheta de componentes da IDE ele seja exibido com uma imagem exclusiva, podendo assim ser identificado facilmente.

6 Criam um pacote (uma biblioteca de dinâmico-ligação especial – Uma Package) de forma que possa organizar logicamente seus componentes ao registrá-los e instala-los na IDE.

7 Criam um arquivo de Ajuda para seu componente, explicando e suas propriedades, métodos, e eventos, facilitando para outros desenvolvedores a consumo do seu componente.


Criando um bitmap para o componente criado.

Conforme mencionado acima, vamos criar uma imagem, bitmap para representar um componente qualquer criado, na palheta de componentes, aonde foi instalado. Na própria IDE do Delphi existe uma ferramenta para editar imagens. Essa ferramenta, é usada para criarmos os bitmaps, os quais podemos associa-los aos componentes que construímos.

Passo 1: No menu Tools ► Image Editor, você executa o editor de imagem ao qual me refiro.




Passo 2: No menu, do “Image Editor” (do Delphi), File ►New ► Component Resource File (.dcr)

Passo 3: Na janela de diálogo, cujo o título é “untitled1.dcr”, na palavra “Contents” clike com o botão direito do mouse, escolha “New | Bitmap”.



Passo 4: No próximo diálo, será solicitado as dimensões do bitmap. Altere o valor para 24 pixels tanto, para altura (Height), quanto para largura (Width). Em colors, selecione VGA (16 colors).



Passo 5: Em resposta, na tela é criado sub-itens abaixo de “Contents”: Bitmap, abaixo dele, Bitmap1. Com o botão direito do mouse sobre “Bitmap1”, selecione “Rename” para nomearmos nosso arquivo.



Nomeie o bitmap1 com o mesmo nome da classe que define o componente criado por você, totalmente em caixa alta. Por exemplo, usaremos o nosso “TZNDisplayTimerUltimate”. Portanto, re-nomeie o bitmap1 com o nome dessa classe, em caixa alta, veja a seguir: “TZNDISPLAYTIMERULTIMATE”.



Passo 6: Com um duplo click sobre “TZNDISPLAYTIMERULTIMATE” você poderá iniciar a edição do bitmap. Desenhe seu bitmap na tela conforme imagem abaixo.



Passo 7: Para salvar, feche a imagem (menu file | Close), em seguida salve no mesmo diretório onde se encontra a sua package.



Passo 8: Agora, basta codificar a diretiva de compilação que inclui o arquivo bitmap que criamos na package que contém o componente para o qual a imagem foi criada. No exemplo em questão, estamos trabalhando com a mesma package dos artigos anteriores: “ZnConstruindoComponenetes”. Portanto, no Delphi, abra a package e na unit ““ZnConstruindoComponenete.dpk” e codifique conforme o trecho abaixo:



{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$IMPLICITBUILD OFF}

requires
rtl,
vcl,
designide;

contains
ZnCombo in 'ZnCombo.pas',
ZNDisplayTimerUltimate in 'ZNDisplayTimerUltimate.pas',
ZNDisplayTimerProgress in 'ZNDisplayTimerProgress.pas',
ZnGraphicSeta in 'ZnGraphicSeta.pas',
ZNNode in 'ZNNode.pas',
ZnAresta in 'ZnAresta.pas';

end.



Compile e SALVE a package, conforme demonstrado em artigos anteriores.



Artigo completo (View Full Post)

Novos Tempos - Mart'nália

O coração de quem é Zn bate em dois por quatro. Onde o Surdo e o Tan-tan fazem mais sentido, ecoam deep in my heart.

Gostei bastante desse último trabalho da Mart'nália ...

"NOVOS TEMPOS" uma composição do violonista|Guitarrista, Cláudio Jorge, composta numa viagem em turnê com Martinho da Vila. Segundo reza a lenda, assim que ouviu, Mart'nália, reservou pra ela, exigindo exclusividade: "_ Essa é minha, não dá pra ninguém que um dia eu gravo". Pois é, aconteceu ... Obrigado Claudio Jorge, obrigado Mart'nália. Então por isso mesmo ... lá vai ...

“Se você gosta de samba, encosta e vê se dá ...”




NOVOS TEMPOS
A chuva chega e ela vem lavar
Vem me livrar do mal
É água fresca para aliviar
Meu coração que secou
De tanto pranto derramado
Pela mágoa
Que se instalou no meu peito
De um jeito tão perverso
Hoje se desfaz nesses versos
Um arco-íris se formou no céu
É um sinal
Que a paz está de volta na minha alma
Sinto calma
São novos tempos enfim graças à chuva
Que levou o rancor
Me permitindo viver
Outro grande amor
Graças à chuva
Que levou o rancor
Me permitindo viver
Outro grande amor

Artigo completo (View Full Post)

domingo, 16 de setembro de 2007

Delphi - Alternativas Free

A maioria dos artigos que temos publicado é sobre Delphi, muitas pessoas não tem acesso a essa ferramenta por causa da necessidade de licença. Portanto, listamos alguns links com alternativas free, para você conhecer.

A Borland disponibiliza uma versão free do Delphi. Ela é antiga, não atende a todas as necessidades de um projeto de software atual. Contudo, ainda é muito eficaz, podendo ser usada em alguns projetos onde exista restrição de custos. Ou um projeto que prescinda de alta tecnologia.

Delphi 3 douwnload

Alternativas free ao Delphi:

Free Pascal

http://pt.wikipedia.org/wiki/Free_Pascal

Lazarus:

é um ambiente de desenvolvimento integrado (IDE) para o compilador Free Pascal. O software objetiva ser compatível com o Delphi e, ao mesmo tempo, suportar diversas arquiteturas e sistemas operacionais. O que em muitos aspectos representa uma grande vantagem dessa ferramenta como diferencia de mercado.

Ainda hoje, apesar de toda a popularidade do Delphi, muitos projetos, durante o processo de codificação e implementação, são feitos desprezando as principais características de ponta da ferramenta. Essas características, justamente, justificam a compra da sua licença e diferencia o Delphi diante das demais ferramentas presentes no mercado. Portanto, considerando isso, tanto faz se o projeto está usando a versão atual, uma mais antiga, ou até mesmo um genérico, free, como o Free Pascal ou Lazarus. Se o projeto não faz uso dos componentes Dataware (Conscientes de dados), ou da tecnologia MIDAS/Data Snap (essa por sua vez, na minha opnião é o que justifica o custo de uma licença enterprise).




Artigo completo (View Full Post)

sábado, 1 de setembro de 2007

Construção de Componentes III

Dando continuidade ao assunto, neste artigo pretendo exemplificar o conceito de herança em OO. Neste momento, faremos uma abordagem simples onde nos ateremos somente ao trivial de como fazer isso em Delphi. A minha idéia é tentar chagar ao mais próximo de uma situação real. Acho que dessa forma posso tornar mais acessível o conteúdo desse artigo.
Vou extender a classe que criamos no artigo Construção de Componentes II, para uma que saiba trabalhar também com uma barra de progressão. Para que seja opcional ao programador optar por usar a barra ou não, implementaremos a associação dela com o TZNDisplayTimerUltimate externamente. Na literatura sobre criação de componentes em Delphi você vai encontrar esses termos, componentes compostos internos e externos:

Componentes Internos: Criados e Gerenciados pelo componente pricipal. Esta opção deixa
o componente encapsulado, obtendo a vantagem de se poder decidir o
que vamos publicar ou esconder do componente. Assim como fizemos na
relação do ZnDisplayTimer com o campo FTimer. A desvantagem é o
acoplamento extremo entre os dois componentes. Em determinadas situações
isso pode ser indesejável.

Componentes Externos: São associados através de uma propriedade do componente principal. Temos
um acoplamento bem mais fraco, isso pode ser bastante vantajoso.


Associações

Craig Larman, em Applying UML and Patterns (Traduzido como: Utilizando UML e Padrões), descreve associações entre classes como um relacionamento entre tipos (ou, mais especificamente, instâncias desses tipos). Não esquecendo que devemos entender “tipos” como classes, e que estes relacionamentos indicam uma conexão com significado e interesse. Na UML, as associações são descritas como: “Um relacionamento semântico entre dois ou mais classificadores envolvendo conexão entre suas instâncias


Por que um ProgressBar?

Minha escolha foi justamente por conta da principal funcionalidade do componente que criamos. De forma visual, transmitir ao usuário, uma idéia de quanto tempo falta até que seja disparado um evento. E este evento pode ser usado para se codificar qualquer coisa: A execução de uma consulta, a exibição de um filme, a transmissão de um e-mail, etc...
Toda vez que em seu programa, alguma módulo executar uma ação que demande tempo, você pode usar uma barra de progressão (TProgressBar, da palheta Win32, o TGauge, palheta Samples. Existem ainda vários outros, mais incrementados, como os da JVCL - Jedi) que mostrará quanto da ação ainda resta para ela ser completada. A propriedade “Prosition” do TProgressBar indica o quanto da barra já foi preenchida. As propriedades “Max” e “Mim”, marcam o valor relativo de início e final do preenchimento da barra. Para efetuar o preenchimento gradual da barra faça chamada ao método “StepBy” ou “StepIt”. A Propriedade “Step” determina o valor de incremento que será usado por “StepIt”. Veja um micro-exemplo:

procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
ProgressBar1.Max := 100000000;
ProgressBar1.Min := 0;

for i := 0 to 100000000 do
begin
ProgressBar1.StepBy(i);
end;

end;

Criando o Componente

No Delphi, No menu File ► Open Project ... , abra a unit “ZnConstruindoComponenetes” da package que criamos e temos trabalhado nela nos artigos anteriores sobre componentes. Em seguida, no menu Component ►New Component, vamos criar mais um componente que herdará do temporizador que construímos anteriormente.



Salve a unit ZNDisplayTimerProgress.pas, pois ela já está adicionada a package.



Antes de qualquer coisa adicione na seção uses da interface a unit “ZNDisplayTimerUltimate”. Onde está definido a classe ancestral.


interface

uses
SysUtils, Classes, ZNDisplayTimerUltimate;


Vamos criar a associação entre a classe TZNDisplayTimerProgress e a classe TProgressBar, a qual implementaremos em forma de uma propriedade. Visto que, nosso objetivo é criarmos um componente composto por um componente externo.


type
TZNDisplayTimerProgress = class(TZNDisplayTimerUltimate)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
property ProgressBar: TProgressBar;
end;

Ctrl + Shift + C” para implementarmos o método SetProgressBar. Antes de digitar o código abaixo apague o que você ancontar lá.


{ TZNDisplayTimerProgress }

procedure TZNDisplayTimerProgress.SetProgressBar(
const Value: TProgressBar);
begin
if FProgressBar <> Value then
begin
FProgressBar := Value;
if FProgressBar <> nil then
FProgressBar.FreeNotification(Self);
end;
end;

Pretendo associar um componente ProgressBar ao temporizador, adicionando um, a propriedade que acabamos de codificar. Ora adicionaremos, ora, se necessário, removeremos. um TComponente pode notificar que um outro componente está sendo inserido ou está sendo removido de alguma associação. Por exemplo, se um componente possuir campos ou propriedades cujos tipos sejam referências a outros componentes (outras classes, como no nosso caso), ele pode verificar através das notificações uma remoção de componente, por exemplo, permitindo assim invalidar essas referências evitando “access violate”.
O método FreeNotification, insere um componente, através do parâmetro “AComponent”, numa lista que registra os componentes cujo algumas operações sobre eles deverão ser notificadas ao Owner (componente proprietário). Em outras palavras, isso permite que um componente Owner A, seja notificado que um outro B, numa de suas associações, será destruído. Permitindo que seja implementado tratamento para essa situação. Veja um screenshot da definição deste método na classe TComponent.



Agora vamos sobrescrever o método “Notification” na nossa classe.

procedure Notification(AComponent: TComponent; Operation: TOperation);


Observe na imagem a cima o funcionamento do método “Notification”. O tipo de operação é testado. Caso remoção, indicando que um componente foi removido da lista de componentes associados (FComponents), chama “RemoveFreeNotification”, que remove o componente passado pelo parâmetro (“AComponent”) da lista de componentes notificáveis (FFreeNotifies.Remove(AComponent);)


type TOperation = (opInsert, opRemove);

O parâmetro “Operation”, cujo o tipo é TOpration representa os tipos de operações sobre os componentes registrados na lista de notificações (FFreeNotifies) cujo a ocorrência é propagada pelo método Notification. Os valores definidos por esse tipo são:

opInsert: Indica que um objeto (indicado pelo parânetro AComponent) recentemente foi criado.
opRemove: Indica que um objeto foi destruído.


type
TZNDisplayTimerProgress = class(TZNDisplayTimerUltimate)
private
FProgressBar: TProgressBar;
procedure SetProgressBar(const Value: TProgressBar);
{ Private declarations }
Protected

(*Estamos fazendo herança do método “Notification” e sobrescrevendo ele. *)
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
public
{ Public declarations }
published
property ProgressBar: TProgressBar read FProgressBar write SetProgressBar;
end;



Testamos através do parâmetro “AComponent” se a notificação ocorrida se refere ao campos FProgressBar, testamos também a operação, caso seja de remoção do componente, limpamos a referência (ao endereço de memória) do componente atribuindo “nill”.

procedure TZNDisplayTimerProgress.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited;
//Remove a referência quando o componente externo é destuido
if (AComponent = FProgressBar) and (Operation = opRemove) then
FProgressBar := nil;
end;


Agora vou ter que fazer uma pequena alteração na superclasse (TZNDisplayTimerUltimate), o método privado “SetResetTimeValue (const Value: Integer);” deve ficar na seção “protected”e ser marcado como “virtual”. Dei um mole nesse ponto, mais nada que não possa ser reajustado sem grandes traumas Logo, voltando a unit “TZNDisplayTimerUltimate”, faça a alteração conforme exemplo abaixo:


protected
FTimer: TTimer;

function GetEnabledTimer: Boolean; virtual;
function GetInterval: Integer; virtual;
procedure SetEnabledTimer(const Value: Boolean); virtual;
procedure SetInterval(const Value: Integer); virtual;

procedure UpdateClock(Sender: TObject); virtual;
procedure UpdateCurrentTime(const Multiplicador: Integer); virtual;
(* Este método estava na private, nesnte momento o movi para
a seção "privaate"*).
procedure SetResetTimeValue(const Value: Integer); virtual;
public
constructor Create(AOwner: TComponent); override;


Recompile a package, e salve. Voltemos a unit do “ZNDisplayTimerProgress” para digitarmos a assinatura.


ype
TZNDisplayTimerProgress = class(TZNDisplayTimerUltimate)
private
FProgressBar: TProgressBar;
procedure SetProgressBar(const Value: TProgressBar);
{ Private declarations }
protected
(* Este método estava na private, nesnte momento o movi para
a seção "privaate"*)
procedure SetResetTimeValue(const Value: Integer); override;
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
public
{ Public declarations }
published
property ProgressBar: TProgressBar read FProgressBar write SetProgressBar;
end;


Agora fazendo o polimorfismo, implementaremos o corpo do método ...


procedure TZNDisplayTimerProgress.SetResetTimeValue(const Value: Integer);
begin
inherited SetResetTimeValue(Value);

if not Assigned(FProgressBar) then Exit;
FProgressBar.Min := 1;
FProgressBar.Max := Value;
end;


Mais um polimorfismo: “UpdateCurrentTime”, neste método vamos incrementar a ProgressBar juntamente com o Label.




type
TZNDisplayTimerProgress = class(TZNDisplayTimerUltimate)
private
FProgressBar: TProgressBar;
procedure SetProgressBar(const Value: TProgressBar);
{ Private declarations }
protected
(* Este método estava na private, nesnte momento o movi para
a seção "privaate"*)
procedure SetResetTimeValue(const Value: Integer); override;
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;

procedure UpdateCurrentTime(const Multiplicador: Integer); override;
public
{ Public declarations }
published
property ProgressBar: TProgressBar read FProgressBar write SetProgressBar;
end;


Codificando o corpo do método ....


procedure TZNDisplayTimerProgress.UpdateCurrentTime(
const Multiplicador: Integer);
begin
inherited UpdateCurrentTime(Multiplicador);

if not Assigned(FProgressBar) then Exit;
FProgressBar.Position := CurrentTimeValue;
end;


Agora re-compile apackage “ZnConstruindoComponenetes” .....



Re-instale, clickando em Instal ...



Para testar o que acabamos de construir, feche o projeto da package, no menu File ►Close All. Em seguida inicie uma nova aplicação no menu File ► New ►Application.


Adicione os seguintes componentes no Form1:

1- Um ProgressBar (Palheta Win32)



Configure as seguintes propriedades:
Left = 8
Top = 80
Width = 350
Font.Color = clNavy
Font.Height = 24
Font.Name = 'MS Sans Serif'
Font.Style = [fsBold]

2- Um componente ZNDisplayTimerProgress (Palheta EstacaoZn).





Configure as seguintes propriedades:
Left = 232
Top = 24
Width = 3
Height = 13
ResetTimeValue = 5
Interval = 1000
ProgressBar = ProgressBar1

As propriedades dos componentes são configuradas no Object Inspector.



3- Um BitBtn (palheta additional).







Configure as seguintes propriedades:
Name = btnAtivar
Left = 16
Top = 16
Width = 75
Height = 25
Caption = '&Ativar'


4- Um SpinEdit (Palheta Samples)



Configure as seguintes propriedades:
Left = 112
Top = 16
Width = 77
Height = 22


5 – Um ListBox (Palheta Standard):

Configure as seguintes propriedades:
Left = 8
Top = 108
Width = 353
Height = 229



Codificando o programa

Primeiro o evento OnCreate do Form1

procedure TForm1.FormCreate(Sender: TObject);
begin
SpinEdit1.Value := 10;
end;


Segundo o evento OnChange do SpinEdit1

procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
ZNDisplayTimerProgress1.ResetTimeValue := SpinEdit1.Value;
end;


Terceiro o evento OnClick do btnAtivar

procedure TForm1.btnAtivarClick(Sender: TObject);
begin
ZNDisplayTimerProgress1.EnabledTimer := not ZNDisplayTimerProgress1.EnabledTimer;
end;



Quarto o evento OnExecute do ZNDisplayTimerProgress1

procedure TForm1.ZNDisplayTimerProgress1Execute(Sender: TObject);
begin
ListBox1.Items.Add('Disparada Ação ' + TimeToStr(Now));
end;






Segue todo o código da Unit referente ao programa teste:



unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Spin, Buttons, ComCtrls, ZNDisplayTimerUltimate,
ZNDisplayTimerProgress;

type
TForm1 = class(TForm)
ZNDisplayTimerProgress1: TZNDisplayTimerProgress;
ProgressBar1: TProgressBar;
btnAtivar: TBitBtn;
SpinEdit1: TSpinEdit;
ListBox1: TListBox;
procedure btnAtivarClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure SpinEdit1Change(Sender: TObject);
procedure ZNDisplayTimerProgress1Execute(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btnAtivarClick(Sender: TObject);
begin
ZNDisplayTimerProgress1.EnabledTimer := not ZNDisplayTimerProgress1.EnabledTimer;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
SpinEdit1.Value := 10;
end;

procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
ZNDisplayTimerProgress1.ResetTimeValue := SpinEdit1.Value;
end;

procedure TForm1.ZNDisplayTimerProgress1Execute(Sender: TObject);
begin
ListBox1.Items.Add('Disparada Ação '+ TimeToStr(Now));
end;

end.


Para conferir também, segue a unit onde criamos o componente deste artigo:


unit ZNDisplayTimerProgress;

interface

uses
SysUtils, Classes, ZNDisplayTimerUltimate, ComCtrls;

type
TZNDisplayTimerProgress = class(TZNDisplayTimerUltimate)
private
FProgressBar: TProgressBar;
procedure SetProgressBar(const Value: TProgressBar);
{ Private declarations }
protected
(* Este método estava na private, nesnte momento o movi para
a seção "privaate"*)
procedure SetResetTimeValue(const Value: Integer); override;
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;

procedure UpdateCurrentTime(const Multiplicador: Integer); override;
public
{ Public declarations }
published
property ProgressBar: TProgressBar read FProgressBar write SetProgressBar;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('EstacaoZn', [TZNDisplayTimerProgress]);
end;

{ TZNDisplayTimerProgress }

procedure TZNDisplayTimerProgress.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited;
//Remove a referência quando o componente externo é destuido
if (AComponent = FProgressBar) and (Operation = opRemove) then
FProgressBar := nil;
end;

procedure TZNDisplayTimerProgress.SetProgressBar(
const Value: TProgressBar);
begin
if FProgressBar <> Value then
begin
FProgressBar := Value;
if FProgressBar <> nil then
FProgressBar.FreeNotification(Self);
end;
end;

procedure TZNDisplayTimerProgress.SetResetTimeValue(const Value: Integer);
begin
inherited SetResetTimeValue(Value);

if not Assigned(FProgressBar) then Exit;
FProgressBar.Min := 1;
FProgressBar.Max := Value;
end;

procedure TZNDisplayTimerProgress.UpdateCurrentTime(
const Multiplicador: Integer);
begin
inherited UpdateCurrentTime(Multiplicador);

if not Assigned(FProgressBar) then Exit;

FProgressBar.Position := CurrentTimeValue;
end;

end.

Artigo completo (View Full Post)

sábado, 25 de agosto de 2007

Construção de Componentes II


Certa ocasião, o cliente solicitou que numa tela de consulta, fosse construído um temporizador. O objetivo era que, segundo um valor pré-configurado pelo usuário, o sistema, regularmente, desse um refresh na consulta. Essa funcionalidade deveria, através de algum componente visual, exibir o tempo restante até que disparasse a próxima atualização. Para isso, poderíamos usar uma barra de progressão ou simplesmente um Label.
Neste artigo vamos trabalhar num componente que possa atender esse tipo de requisito.


Dicas

Observar os conceitos discutidos no artigo sobre escopo de visibilidade. Isso é extremamente importante neste momento.
Dominar o conceito de polimorfismo do paradigma OO, também discutido em artigos anteriores (meus e do Felipe).
Relembrando, o que colocamos no artigo Construção de Componentes I, devemos construir um componente sempre a partir de um outro pré-existente, seja ele extendido direto da VCL ou extendido de outro construído por você (recursivamente). Uma consideração é extremamente importante: Qual a classe hierarquicamente mais alta (mais abstrata), possuidora das características essenciais do objeto que pretendo construir? Essa será a classe base, da qual herdará o seu componente. Quando você souber responder essa pergunta com precisão, estará um passo na frente para ser um bom construtor de componentes. Um pré-requisito fundamental para isso, é conhecer bem a VCL e ter sempre por perto uma boa referência para consultar. O Help do Delphi não pode faltar neste contexto (O Diagrama da VCL também é bem legal).
O que posso adiantar que invariavelmente, num universo de coisas mais simples, corriqueiras, o feijão com arroz do dia-a-dia, o componente que você pretende construir estará dentro de três grupos bases de classes:
  1- TWinControl:
Classe base para todo componente baseado em janela. Ou seja, a idéia de janelas que o
SO Windows transmite. As características mais marcantes dessa classe são:
1.1 Pode receber foco.
1.2 Obter mensagens do Windows.
1.3 Pode trabalhar com Handles de janelas. Em suma, você pode ficar moito próximo as
APIS do Windows. Finalizando, para trabalhar com essa categoria de classes você
deverá herdar seu componente de TCustomControl.

2- TGraphicControl:
Classe base para os componentes visuais que não possuem handle do Windows. Característica que
pode ser bastante preferível quando você deseja economizar recursos do SO. Em contraste com a
classe TWinControl , TGraphicControl não recebe foco, tão pouco pode trabalhar com mensagens do
Windows. Para você criar um componente gráfico desta categoria de classes deverá extender seu
componente de TCustomControl.

3 – TComponent:
Esta é a superclasse de todos os componentes. Inclusive os “controles” (“TGenecosControls”, digamos) .
Entretanto, quando o componente que você desejar criar não possuir características visuais essa classe
poderá ser ideal para atender sua necessidade. TComponent é a classe mais alta da VCL a possuir propriedades
(Properties). Nela surge a propriedade “Name”, por exemplo. Outro ponto importante é que nela surge o conceito
de Owner, cujo a importância falaremos um pouco adiante. A classe TComponent extende de TPersistent e apresentam
importantes características:
3.1 Integração com IDE:
A habilidade para serem adicionados em uma paleta de componentes da IDE.
Capaz de serem manipulados em tempo de projeto (design time).

3.2 Proprietariedade (Ownership):
A habilidade para administrar outros componentes. Se um componente A possui
o componente B, então A é responsável por destruir B, quando A é destruído.
Isso é muito importe e nos remete ao que foi discutido no artigo sobre o uso
do método “Free” ou “Destroy”. Lembre-se que quando estamos trabalhando com
uma variável cujo tipo é uma classe, obrigatoriamente estaremos alocando memória
dinamicamente. Portanto, somos responsáveis por gerenciar a liberação da mesma.

3.3 Streaming e Filing:
características de persistência herdadas de TPersistent.

3.4 Suporte a COM:
Podem ser convertidos em controles de ActiveX, objetos COM do Windows.
Os TComponents podem ser encapsulados por objetos COM.




Um Diagrama rezumido da VCL




Como no mundo real, os componentes existentes, em muitos casos, são objetos compostos por um conjunto de outros objetos. Da mesma forma, posso aproveitar essa idéia para montar o meu temporizador com display. O qual chamarei de ZNDisplayTimer. Sendo fiel a minha linha de raciocínio, vou compor o ZNDisplayTimer por dois componentes, inicialmente: Um Timer (TTimer), e um Label (TLabel).

Vou aproveitar este artigo para experimentarmos esse efeito na prática, o nosso componente será capaz de, em tempo de projeto exibir o tempo restante para ele executar uma ação.


Vamos ao que interessa .... Codificando

Inicie a construção do nosso novo componente, no menu do Delphi: Component ►New Component (Ou alternada mente digite “Alt ► C ► N”).





Vou preferir herdar o componente de TCustomLabel, porque a partir dessa classe eu posso decidir o que eu vou esconder (encapsular), e o que eu vou permitir acesso na que pretendo criar, a qual chamarei de TZNDisplayTimerUltimate. Neste caso específico, pretendo esconder a propriedade “Caption”. Minha finalidade com isso é não permitir que o programador que vier fazer uso deste componente não se confunda e atribua valor para essa propriedade. O que tornaria o comportamento do ZNDisplayTimer deficiente.



type
TZNDisplayTimerUltimate = class(TCustomLabel)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
property Align;
property Alignment;
property Color;
property Font;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Transparent;
property Visible;
end;

Das propriedades originais, as que pretendo expor são as digitadas no trecho de código acima: Align, Alignment, Color, Font, ParentColor, ParentFont, ParentShowHint, PopupMenu, ShowHint, Transparent, Visible. Digite conforme o exemplo acima, em seguida salve sua unit. Tudo que é declarado na seção “published” ficará listado no Object Inspector.

Além dessas propriedades, preciso de uma que armazene o valor que definirá o período entre a execução da ação desejada (essa ação inicialmente desejamos atualizar uma consulta). Denominarei essa propriedade de “ResetTimeValue”. Outra somente de leitura que indicará o valor corrente do tempo, cujo o nome será: “CurrentTimeValue”. Veja a seguir:


type
TZNDisplayTimerUltimate = class(TCustomLabel)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
property Align;
property Alignment;
property Color;
property Font;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Transparent;
property Visible;
(* Acrescente as linhas abaixo e pressione “Ctrl + Shift + C *)
property ResetTimeValue: Integer;
property CurrentTimeValue: Integer FCurrentTimeValue default 0;
end


O Delphi vai auto-completar a codificação das propriedades novas.

.
.
.
property ShowHint;
property Transparent;
property Visible;
property ResetTimeValue: Integer read FResetTimeValue write SetResetTimeValue;
property CurrentTimeValue: Integer read FCurrentTimeValue default 0;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('EstacaoZn', [TZNDisplayTimerUltimate]);
end;

{ TZNDisplayTimerUltimate }
procedure TZNDisplayTimerUltimate.SetResetTimeValue(const Value: Integer);
begin
FResetTimeValue := Value;
end;

Agora vou definir o componente interno possuidor da capacidade de ser um temporizador, um TTimer. Vou cuidar para que ele fique encapsulado porque, partindo do mesmo princípio que usei para esconder o caption do Label, não quero que meu componente Dilpay seja usado equivocadamente. Portanto, a fim de esconder, principalmente, o evento OnTimer (O qual terá um papel fundamental para o comportamento do ZNDisplayTimer), bem como as demais propriedades da classe TTimer, vou defini-lo na seção “protected”. Entretanto, isso demandará a codificação de uma interface para comunicação com as propriedades do Timer.
Esse encapsulamento é muito importante, pois somente mediante a manipulação do componente da forma que planejei, conseguirei garantir, em qualquer circunstancia, não importando o programador, o comportamento adequado para o nosso componente. Entenda que embora este componente tenha características de um temporizador, ou melhor, conforme especifiquei no inicio do artigo, seja de fato um, não quero deixar sombra de dúvida que ele não é, em essência, igual ao TTimer da VCL. Ele especializa um TTimer, e possui uma finalidade específica, bem diferente do seu progenitor. Veja o trecho abaixo:


type
TZNDisplayTimerUltimate = class(TCustomLabel)
private
{ Private declarations }
FResetTimeValue: Integer;
FCurrentTimeValue: Integer;
procedure SetResetTimeValue(const Value: Integer);
protected
FTimer: TTimer;
public
{ Public declarations }
published
property Align;
property Alignment;
property Color;
property Font;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Transparent;
property Visible;
property ResetTimeValue: Integer read FResetTimeValue write SetResetTimeValue;
property CurrentTimeValue: Integer read FCurrentTimeValue default 0;
(*As linhas abaixo implementam a interface com o componente FTimer. Após digitar pressione “Ctrl + Shift + C” *)
property EnabledTimer: Boolean read GetEnabledTimer write SetEnabledTimer default False;
property Interval: Integer read GetInterval write SetInterval;
end;


Neste momento, quero chamar a atenção para o fato de que, quem está construindo um componente deve arquitetar sua construção considerando a possibilidade desse componente ser extendido mais tarde. Ou seja, imaginar que seu componente poderá ser superclasse para um outro que o especializará. Não julgo que este exemplo, especificamente, constitua o cenário mais adequado para situação que descrevi. Todavia, mais uma vez sobre a premissa de uma ênfase didática, vou aproveitar e exemplificar aqui, como preparar sua classe para que ela seja herdada. Por isso, defini o campo FTimer, na “protected” e não na “private”. Visto que, isso o tornaria inacessível para o caso de um extensor. Logo, seguindo esta mesma linha de raciocínio, os métodos, “GetEnabledTimer” e “SetEnabledTimer” que fazem a interface para a propriedade “EnabledTimer”. Bem como, “GetInterval” e “SetInterval”, que fazem o mesmo para a propriedade “Interval”, serão definidos na seção “protected” e serão marcados como “virtual”, viabilizando assim a possibilidade de polimorfismo, no herdeiro. Se você pressionou “Ctrl + Shift + C” como recomendado acima, verá que o Delphi auto-completou a codificação do corpo dos métodos que citei na “implemantation”, sendo que suas assinaturas foram parar na “private”. Retire a assinatura dos métodos que citei (GetEnabledTimer e SetEnabledTimer, GetInterval e SetInterval) da seção “private” e transporte para a seção “propected” imediatamente abaixo da definição o campo “FTimer”. Em seguida marque-os com a diretiva “virtual”, conforme o trecho abaixo:




type
TZNDisplayTimerUltimate = class(TCustomLabel)
private FResetTimeValue: Integer;
FCurrentTimeValue: Integer;
procedure SetResetTimeValue(const Value: Integer);
{ Private declarations }
protected
FTimer: TTimer;
function GetEnabledTimer: Boolean; virtual;
function GetInterval: Integer; virtual;
procedure SetEnabledTimer(const Value: Boolean); virtual;
procedure SetInterval(const Value: Integer); virtual;
public
{ Public declarations }
published
property Align;
property Alignment;
property Color;
property Font;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Transparent;
property Visible;
property ResetTimeValue: Integer read FResetTimeValue write SetResetTimeValue;
property CurrentTimeValue: Integer read FCurrentTimeValue default 0;
property EnabledTimer: Boolean read GetEnabledTimer write SetEnabledTimer default False;
property Interval: Integer read GetInterval write SetInterval;
end;


Em seguida vamos codificar os corpo dos métodos que acabamos de criar.
1 - GetEnabledTimer

function TZNDisplayTimerUltimate.GetEnabledTimer: Boolean;
begin
Result := FTimer.Enabled;
end;


2 - GetInterval

function TZNDisplayTimerUltimate.GetInterval: Integer;
begin
Result := FTimer.Interval;
end;


3 - SetEnabledTimer

procedure TZNDisplayTimerUltimate.SetEnabledTimer(const Value: Boolean);
begin
FTimer.Enabled := Value;
end;


4 - SetInterval

procedure TZNDisplayTimerUltimate.SetInterval(const Value: Integer);
begin
FTimer.Interval := Value;
end;


Sobrescrevendo um Método – Override:
Por falar em polimorfismo, agora vamos especializar o método “constructor” da classe TCustomLabel, a fim de configuramos de maneira adequada a “TZNDisplayTimerUltimate”. Na seção “public” digite conforme ilustrado no trecho abaixo:

protected
procedure UpdateClock(Sender: TObject);
procedure UpdateCurrentTime(const Multiplicador: Integer);
public
(* Digite o construtor e pressione “Ctrl + Shift + C” *)
constructor Create(AOwner: TComponent); override;


Sobrescrevendo o construtor da classe ..... Após marcar o método “Create”, construtor, com a palavra chave “override”, vou codificar para instanciar o componente interno (temporizador) e setar os valores default.


constructor TZNDisplayTimerUltimate.Create(AOwner: TComponent);
begin
(* evocando o método do ancestral *)
inherited Create(AOwner);

(* Instanciando o componente interno*)
FTimer := TTimer.Create(Self);

(* Configurando a Classe com valores default *)
FTimer.Name := 'ZnDisplayTimer';
FTimer.Enabled := False;
FCurrentTimeValue := 0;
FResetTimeValue := 5;
end;


Codificando a funcionalidade do TZNDisplayTimerUltimate

O componente deverá possuir duas funcionalidades. Elas deverão ser sincronizadas e dependentes:
1° Ação- De tempos em tempos disparar uma ação, sendo que, o intervalo entre as ações deve ser constante podendo ser, dinamicamente, definido pelo usuário do sistema. Implementaremos ela em forma de evento e a propriedade que definirá esse intervalo é a “ResetTimeValue”.
2° Ação – Exibir o tempo restante para a próxima ação disparada. A propriedade “Caption” que vamos absorver da classe TCustomLabel.

Na seção “Type” vamos definir o evento que implementará a primeira ação do nosso componente.
Vejamos o código abaixo:


type
(* Primeiro codifique o evento *)
TExecuteEvent = procedure(Sender: TObject) of object;
TZNDisplayTimerUltimate = class(TCustomLabel)
private
FTimer: TTimer;
FResetTimeValue: Integer;
FCurrentTimeValue: Integer;
FResetMod: TResetMod;
.
.
.
constructor Create(AOwner: TComponent); override;
published
.
.
.
property Align;
property Alignment;
(*Em seguida, digite a propriedade aqui, assim ela seja listada no
Object Inspector *)
property OnExecute: TExecuteEvent read FOnExecute write FOnExecute;


Ao pressionar “Ctrl + Shift + C” será criado o campo privado “FOnExecute”, veja abaixo:


type
TExecuteEvent = procedure(Sender: TObject) of object;
TZNDisplayTimerUltimate = class(TCustomLabel)
private
FResetTimeValue: Integer;
FCurrentTimeValue: Integer;
FOnExecute: TExecuteEvent;
procedure SetResetTimeValue(const Value: Integer);

{ Private declarations }
protected
FTimer: TTimer;
.
.

O Evento “OnExecute” esta pronto, a primeira funcionalidade está implementada. Agora, vamos tratar da exibição e do sincronismo ente a contagem do tempo e a execução do evento.

type
TExecuteEvent = procedure(Sender: TObject) of object;
TZNDisplayTimerUltimate = class(TCustomLabel)
private
FResetTimeValue: Integer;
FCurrentTimeValue: Integer;
FOnExecute: TExecuteEvent;
procedure SetResetTimeValue(const Value: Integer);

protected
FTimer: TTimer;

function GetEnabledTimer: Boolean; virtual;
function GetInterval: Integer; virtual;
procedure SetEnabledTimer(const Value: Boolean); virtual;
procedure SetInterval(const Value: Integer); virtual;

procedure UpdateClock(Sender: TObject); virtual;
procedure UpdateCurrentTime(const Multiplicador: Integer); virtual;
public
constructor Create(AOwner: TComponent); override;
published
.
.
.


Na seção “protected” declarei dois procedimentos e os marquei com a diretiva virtual, preparando a classe para ser extendida. Mais uma vez o bom e velho “Ctrl + Shift + C” e vamos codificar cada um deles. Adicione na seção “uses” da “implementation” a unit “DateUtils”.

implementation

uses
DateUtils;

Por falar em uses, veja como deve estar a seção “uses” da “interface” .


interface

uses
SysUtils, Classes, Controls, StdCtrls, ExtCtrls;
.
.
.

Codificando o método UpdateCurrentTime.


procedure TZNDisplayTimerUltimate.UpdateCurrentTime(
const Multiplicador: Integer);
var
AuxSecond: Integer;
begin
AuxSecond := SecondOf(Time);
if ((AuxSecond * Multiplicador) mod FResetTimeValue = 0) then
FCurrentTimeValue := 1
else
FCurrentTimeValue := FCurrentTimeValue + 1;
end;

FCurrentTimeValue indica o valor do tempo corrente. O método acima incrementa o campo ou reseta seu valor caso ele atinja o limite determinado para isso. Ou seja, a cada intervalo determinado no campo FResetTimeValue o campo FCurrentTimeValue é resetado, recebendo valor 1. Enquanto isso não acontece ele é incrementado. O Parâmetro “Multiplicador” serve para flexibilizar nosso componente, de maneira que ele seja capaz de trabalhar com a ordem de grandeza segundo, minuto, ou hora. Basta para isso variar o valor do multiplicador entre: 1 para segundo, 60 para minuto, 360 para hora.
No método seguinte faremos a chamada ao “UpdateCurrentTime”, atualizaremos o “Caption” para assim exibir o valor de “FCurrentTimeValue” em seguida. A cada vez que ele for resetado dispararemos o evento “OnExecute”.

procedure TZNDisplayTimerUltimate.UpdateClock(Sender: TObject);
begin
(*Atualizando o tempo corrente*)
UpdateCurrentTime(1);
(*Atribuindo o valor atualizado na propriedade de output do componente*)
Self.Caption := IntToStr(FCurrentTimeValue);

(*Caso o campo tenha seido resetado dispara o evento OnExecute*)
if (FCurrentTimeValue = 1) then
if Assigned(FOnExecute) then FOnExecute(Self);
end;



Agora voltaremos ao construtor para a última configuração.


constructor TZNDisplayTimerUltimate.Create(AOwner: TComponent);
begin
(* evocando o método do ancestral *)
inherited Create(AOwner);

(* Instanciando o componente interno*)
FTimer := TTimer.Create(Self);

(* Configurando a Classe com valores default *)
FTimer.Name := 'ZnDisplayTimer';
FTimer.Enabled := False;
FCurrentTimeValue := 0;
FResetTimeValue := 5;
(*Ao evento onTimer atribuimos o método que possui
a principal funcionalidade do nosso componente*)
FTimer.OnTimer := UpdateClock;

end;


Agora que nosso componente está pronto o adicione a package que criamos no artigo anterior sobre construção de componentes. Compile a package e re-instale.



Clik em "Browse..." para selecionar a unit do seu component (ZNDisplayTimerUltimate.pas), em seguida click "OK"



É chegado o momento ... vamos fazer um pequeno programa para testarmos nossa criação.




Testando o componente que criamos

Inicie uma nova aplicação, antes de qualquer coisa feche o projeto da package. No menu do Delphi: File ►Close All. Em seguida, File ► New ►Application.

Adicione o componente ZNDisplayTimerUltimate



Configure a propriedade fonte do ZNDisplayTimerUltimate para um tamanho maior e set sua propriedade “Enabled”, no Object Inspector para True.
e um BitBtn (palheta additional).



No Evento OnExecute do ZNDisplayTimerUltimate




digite .....


procedure TForm1.ZNDisplayTimerUltimate1Execute(Sender: TObject);
begin
ShowMessage('Bla!!!! ... Estação ZN ... Boladão')
end;


Adicione um SpinEdit (palheta Samples), no evento OnCreate do Form1 atribua valor para ele.

procedure TForm1.FormCreate(Sender: TObject);
begin
(*Vamos iniciar a aplicação com o Display desativado*)
ZNDisplayTimerUltimate1.EnabledTimer := False;
(*setando um valor inicial para o SpinEdit1*)
SpinEdit1.Value := 7;
end;


No evento OnClick do BitBtn1 vamos ativar o componente em tempo de execução.


procedure TForm1.BitBtn1Click(Sender: TObject);
begin
( * definindo um novo valor para o intervalo *)
ZNDisplayTimerUltimate1.ResetTimeValue := SpinEdit1.Value;

(*Controlando o ZNDisplay ...*)
ZNDisplayTimerUltimate1.EnabledTimer :=
not (ZNDisplayTimerUltimate1.EnabledTimer);
end;


Execute a aplicação e teste .....
Segue o código completo da aplicação exemplo.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ZNDisplayTimerUltimate, Spin;

type
TForm1 = class(TForm)
ZNDisplayTimerUltimate1: TZNDisplayTimerUltimate;
BitBtn1: TBitBtn;
SpinEdit1: TSpinEdit;
procedure ZNDisplayTimerUltimate1Execute(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ZNDisplayTimerUltimate1Execute(Sender: TObject);
begin
ShowMessage('Bla!!!! ... Estação ZN ... Boladão')
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
ZNDisplayTimerUltimate1.ResetTimeValue := SpinEdit1.Value;
ZNDisplayTimerUltimate1.EnabledTimer :=
not (ZNDisplayTimerUltimate1.EnabledTimer);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
(*Vamos iniciar a aplicação com o Display desativado*)
ZNDisplayTimerUltimate1.EnabledTimer := False;
(*setando um valor inicial para o SpinEdit1*)
SpinEdit1.Value := 7;
end;

end.


O Código completo do componente ...

unit ZNDisplayTimerUltimate;

interface

uses
SysUtils, Classes, Controls, StdCtrls, ExtCtrls;

type
TExecuteEvent = procedure(Sender: TObject) of object;
TZNDisplayTimerUltimate = class(TCustomLabel)
private
FResetTimeValue: Integer;
FCurrentTimeValue: Integer;
FOnExecute: TExecuteEvent;
procedure SetResetTimeValue(const Value: Integer);

{ Private declarations }
protected
FTimer: TTimer;

function GetEnabledTimer: Boolean; virtual;
function GetInterval: Integer; virtual;
procedure SetEnabledTimer(const Value: Boolean); virtual;
procedure SetInterval(const Value: Integer); virtual;

procedure UpdateClock(Sender: TObject); virtual;
procedure UpdateCurrentTime(const Multiplicador: Integer); virtual;
public
constructor Create(AOwner: TComponent); override;

published
property Align;
property Alignment;
property Color;
property Font;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Transparent;
property Visible;
property ResetTimeValue: Integer read FResetTimeValue write SetResetTimeValue;
property CurrentTimeValue: Integer read FCurrentTimeValue default 0;
property EnabledTimer: Boolean read GetEnabledTimer write SetEnabledTimer default False;
property Interval: Integer read GetInterval write SetInterval;
property OnExecute: TExecuteEvent read FOnExecute write FOnExecute;
end;

procedure Register;

implementation

uses
DateUtils;
procedure Register;
begin
RegisterComponents('EstacaoZn', [TZNDisplayTimerUltimate]);
end;

{ TZNDisplayTimerUltimate }


constructor TZNDisplayTimerUltimate.Create(AOwner: TComponent);
begin
(* evocando o método do ancestral *)
inherited Create(AOwner);

(* Instanciando o componente interno*)
FTimer := TTimer.Create(Self);

(* Configurando a Classe com valores default *)
FTimer.Name := 'ZnDisplayTimer';
FTimer.Enabled := False;
FCurrentTimeValue := 0;
FResetTimeValue := 5;
(*Ao evento onTimer atribuimos o método que possui
a principal funcionalidade do nosso componente*)
FTimer.OnTimer := UpdateClock;

end;

function TZNDisplayTimerUltimate.GetEnabledTimer: Boolean;
begin
Result := FTimer.Enabled;
end;

function TZNDisplayTimerUltimate.GetInterval: Integer;
begin
Result := FTimer.Interval;
end;

procedure TZNDisplayTimerUltimate.SetEnabledTimer(const Value: Boolean);
begin
FTimer.Enabled := Value;
end;

procedure TZNDisplayTimerUltimate.SetInterval(const Value: Integer);
begin
FTimer.Interval := Value;
end;

procedure TZNDisplayTimerUltimate.SetResetTimeValue(const Value: Integer);
begin
FResetTimeValue := Value;
end;

procedure TZNDisplayTimerUltimate.UpdateClock(Sender: TObject);
begin
UpdateCurrentTime(1);
Self.Caption := IntToStr(FCurrentTimeValue);

if FCurrentTimeValue = 1 then
if Assigned(FOnExecute) then FOnExecute(Self);
end;

procedure TZNDisplayTimerUltimate.UpdateCurrentTime(
const Multiplicador: Integer);
var
AuxSecond: Integer;
begin
AuxSecond := SecondOf(Time);
if ((AuxSecond * Multiplicador) mod FResetTimeValue = 0) then
FCurrentTimeValue := 1
else
FCurrentTimeValue := FCurrentTimeValue + 1;

end;

end.

Você pode pesquisar mais sobre o assunto em:
Downloads nos artigos do Bruno (Cod Gear):

Mini Book About Components' Creation: http://cc.borland.com/Item/24302


Apostila sobre Criação de Componentes Passo a Passo by Bruno Lichot:
Apostila sobre Criação de Componentes Passo a Passo com exemplos e código fonte inclusos.
Mostra como Criar Compoenentes Simples e Componantes DBWare para Banco de Dados.

e-mail: bruno.lichot@gmail.com
lista: nddv@yahoogrupos.com.br

Atenciosamente,

Bruno Lichot
CodeGear Team Brazil




Amigos, com o tempo curto ... foi o que deu pra fazer dessa vez ...
[]’s ...


Artigo completo (View Full Post)

 
BlogBlogs.Com.Br