Criando Componentes com Eventos Programados – Parte II
Criando o Componente TMoveLabel
Nesta segunda parte, construiremos nosso próprio componente com a funcionalidade de poder ser movido em Run-Time.
1º Passo:
Precisamos criar uma nova “Package” ou abrir uma já existente, porque no RAD2007 nós não podemos mais instalar um componente a partir de um simples arquivo .pas, esse arquivo precisa está contido é um pacote (package). Siga as etapas mostradas na(s) figura(s) abaixo:
(File > New > Package - Delphi for Win32)
O nome sugerido pelo Delphi para sua Package será Package1, (claro que, como bons programadores que somos) iremos mudar para um nome mais amigável, por exemplo, PackMyComponents. Salve a nova Package.
2º Passo:
Herdaremos nosso componente do TLabel nativo do Delphi e o chamaremos de TMoveLabel (Poderíamos criar tais funcionalidades para praticamente todos os componentes da VCL que sejam visuais).
Como vimos na Introdução, os eventos manipulados para tais funcionalidades são: OnMouseMove, OnMouseUp e OnMouseDown, então, criaremos três métodos que os representarão e “setaremos”, no Construtor do novo componente fazemos um “link” para que o nosso novo componente receba nos seus eventos o código necessário para atingir as funcionalidades desejadas, ou seja, quando o componente for colocado na tela, seja estaticamente ou em tempo de execução, tais funcionalidades já estarão encapsuladas nele. Difícil? Você vai ver que não.
Vamos lá...
Com o Projeto da nossa Package (PackMyComponents) aberto, crie um Novo componente:
(Menu Component > New VCL Component)
Escolha o componente que deseja estender a herança (No nosso exemplo, TLabel). Clique em NEXT.
Em “Class Name”, defina o nome da Classe do seu novo componente, neste exemplo chamaremos de TMoveLabel.
Na opção “Palette Page”, indique em qual Paleta de componentes este nosso componente será instalado, por padrão, o Delphi indica a Samples (mais poderia ser Standart, Additional ou qualquer outra), porem vamos criar uma nova Pagina onde ficará todos os componentes que nós criarmos. Vamos pedir que o Delphi crie uma pagina chamada MyComponents (este nome fica a cargo do programador, o nome MyComponents é só uma sugestão e será usado para este exemplo).
Na opção “Unit Name”, indique onde será salva esta unit de criação do componente, escolha um diretório a sua escolha e chame a Unit de MoveLabel.pas.
Clique em NEXT
Neste formulário indique se vamos criar essa Unit desvinculada da Package ou não. Marcando a opção “Add Unit to PackMyComponents.dproj project”, você além de esta criando a Unit de criação do componente, está automaticamente vinculando-a a Package existente. Essa é a melhor opção para o exemplo. Clique em Finish.
Se nós instalarmos o componente neste momento, ele será de funcionamento idêntico ao TLabel.
Agora vem o “1º Pulo do gato...”
Como os Eventos OnMouseMove, OnMouseDown e OnMouseUp são os responsáveis pela nova funcionalidade do nosso componente, então, criaremos 03 métodos que os representaram, chamaremos de MouseMove, MouseDown e MouseUp respectivamente e no Constructor associaremos nossos métodos, aos eventos “oficiais” do Componente. Veja...
Criando os Métodos
Como vamos atribuir os métodos aos respectivos eventos do componente, precisamos criá-los com os mesmo parâmetro.
A assinatura dos métodos serão na seção Public.
procedure MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
Sem esquecer o constructor do nosso componente
constructor create(AOWner: TComponent); override;
Deixando a Unit com o seguinte código:
unit MoveLabel;
interface
uses
SysUtils, Classes, Controls, StdCtrls, Windows;
type
TMoveLabel = class(TLabel)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
procedure MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
constructor create(AOWner: TComponent); override;
var
Capturing: Boolean;
MouseDownSpot: TPoint;
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('PackMyComponents', [TMoveLabel]);
end;
{ TMoveLabel }
constructor TMoveLabel.create(AOWner: TComponent);
begin
inherited create(AOWner);
TMoveLabel(Self).OnMouseMove := MouseMove;
TMoveLabel(Self).OnMouseDown := MouseDown;
TMoveLabel(Self).OnMouseUp := MouseUp;
end;
procedure TMoveLabel.MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Capturing := true;
MouseDownSpot.X := X;
MouseDownSpot.Y := Y;
end;
procedure TMoveLabel.MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if Capturing then //Se a ordem for “Pode Mover” o Componente então
begin
TMoveLabel(Sender).Left := TMoveLabel(Sender).Left- (MouseDownSpot.x-x);
TMoveLabel(Sender).Top := TMoveLabel(Sender).Top - (MouseDownSpot.y-y);
end;
end;
procedure TMoveLabel.MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if TMoveLabel(Sender).Capturing then begin
ReleaseCapture;
TMoveLabel(Sender).Capturing := false;
TMoveLabel(Sender).Left := TMoveLabel(Sender).Left - (MouseDownSpot.x -x);
TMoveLabel(Sender).Top := TMoveLabel(Sender).Top - (MouseDownSpot.y - y);
end;
end;
end.
Agora vem o 2º “Pulo do Gato...”
Implementaremos nossos métodos como se estivéssemos programando no próprio evento do componente.
Deixando a Unit da seguinte forma:
unit MoveLabel;
interface
uses
SysUtils, Classes, Controls, StdCtrls, Windows;
type
TMoveLabel = class(TLabel)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
procedure MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
constructor create(AOWner: TComponent); override;
var
Capturing: Boolean;
MouseDownSpot: TPoint;
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('PackMyComponents', [TMoveLabel]);
end;
{ TMoveLabel }
constructor TMoveLabel.create(AOWner: TComponent);
begin
end;
procedure TMoveLabel.MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Capturing := true;
MouseDownSpot.X := X;
MouseDownSpot.Y := Y;
end;
procedure TMoveLabel.MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if Capturing then //Se a ordem for “Pode Mover” o Componente então
begin
TMoveLabel(Sender).Left := TMoveLabel(Sender).Left- (MouseDownSpot.x-x);
TMoveLabel(Sender).Top := TMoveLabel(Sender).Top - (MouseDownSpot.y-y);
end;
end;
procedure TMoveLabel.MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if TMoveLabel(Sender).Capturing then begin
ReleaseCapture;
TMoveLabel(Sender).Capturing := false;
TMoveLabel(Sender).Left := TMoveLabel(Sender).Left - (MouseDownSpot.x -x);
TMoveLabel(Sender).Top := TMoveLabel(Sender).Top - (MouseDownSpot.y - y);
end;
end;
end.
Se fizermos um comparativo com o código anterior, veremos que a diferença de codificação se restringe praticamente a nomenclaturas. Uma exceção é quando usamos:
TMoveLabel(Sender) – Na programação anterior, usamos o nome do próprio componente, no nosso exemplo acima: lblDinamico. Mas isso acontece porque programamos todos os componentes um a um, então temos o nome de cada um. Como faremos as funcionalidades de forma encapsulada, a referencia ao objeto é dinâmica, portanto, utilizaremos o objeto “Sender” (que é o própria instancia do componente) e usamos o cast “TMoveLabel”, para termos acesso a seus métodos e propriedades encapsulados.
Para finalizar vamos ao 3º e ultimo “Pulo do Gato” para este artigo.
Já programamos nossos métodos como se tivéssemos programando o próprio evento do componente, só falta fazer o link entre os eventos e os nossos métodos, ou seja, vamos atribuir ao evento os métodos que criamos, e isso explica o porquê de criarmos os métodos com os mesmos parâmetros do evento. E isso vai ocorrer no construtor. Veja:
constructor TMoveLabel.create(AOWner: TComponent);
begin
inherited create(AOWner);
{Atribuindo os métodos criados aos respectivos eventos}
TMoveLabel(Self).OnMouseMove := MouseMove;
TMoveLabel(Self).OnMouseDown := MouseDown;
TMoveLabel(Self).OnMouseUp := MouseUp;
end;
Um forte Abraço e até o próximo artigo, onde vamos finalizar a "Trilogia" mostrando como Instalar seu Componente TMoveLabel