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