Delphi: Componentes em Runtime

Olá a todos!

Tenho aulas de Delphi na faculdade esse semestre. É, meu passado me persegue! Pensei que nunca mais faria um “:=” na vida.

Um grande desafio que enfrentamos é a criação de componentes em runtime. Se o usuário quer entrar com 20 valores, devemos criar 20 textboxs para inserção dos valores, por exemplo.

Talvez não seja a maneira mais correta, mas É um jeito de trabalhar. Toda vez temos que gerar a função de novo, uma para cada tipo de componente.

Até que eu tive uma quarta feira sossegada a tarde.

Primeiro criei uma função que gerava TextBoxs no formulário. Tive algumas dificuldades, mas consegui. Me foi muito útil na prova da Matéria.

Antes de qualquer pensamento de “o diego colou”, a prova era com consulta ao material individual. Eu apenas me preparei para a guerra ;).

Dai, neste belo sábado, pensei em colar a função aqui, talvez tenha mais gente por ai com o mesmo problema. Mas passar algo tão “travado” não me deixou feliz.

Estudei um pouco sobre a “reflexão” do delphi (nesse universo com o belo nome de RunTime Type Information) e consegui deixar a função mais genérica: Agora crio qualquer tipo de componente!

Ainda estou com uma dificuldade, para o RTTI funcionar corretamente, é preciso “registrar” com antecedência as classes que você usará (TEdit, TButton, etc). Não consegui deixar isso automático.

Fica ai o código, se alguém melhorar e quiser compartilhar, será de grande utilidade para a comunidade, em minha opinião.

Função principal de criação (1/2)

function  CriarComponentes
            (

              //numero de linhas e de colunas da matriz
              pLinhas, pColunas : integer;
              //posição inicial (em px) da esquerda e topo do frm
              pEsquerda, pTopo  : integer;
              //se o componente estará desabilitado ou não
              pEnabled          : Boolean;
              //qual o controle pai
              pControlePai      : TWinControl;
              //tipo de controle
              pTypeControl      : String

            ) : Tar ;
  var
    i,j,esquerdaAux: integer;
    ArrayControl : TAr;         //o retorno
    control : TClass;           //classe base para criação
  begin

    //defino o tamanho do array
    SetLength(ArrayControl,pLinhas, pColunas);

    //guardamos a posição inicial da esquerda
    esquerdaAux := pEsquerda;

    //registramos as classes para poder criá-las depois (procedure auxiliar)
    RegistrarClasses();

    control := GetClass(pTypeControl);

    if control = nil then
    begin
      ShowMessage('Classe não registrada! Verificar "RegistrarClasses". Interrompendo processo.');
      Exit;
    end;

    for i := 0 to pLinhas - 1 do
    begin
      for j := 0 to pColunas - 1 do
      begin

        //cria o controle. Usamos o control, que agora é a classe que queremos
        ArrayControl[i,j]         := TWinControl(TControlClass(control).Create(pControlePai));
        ArrayControl[i,j].Parent  := pControlePai;
        ArrayControl[i,j].Left    := pEsquerda;
        ArrayControl[i,j].Top     := pTopo;
        ArrayControl[i,j].Enabled := pEnabled;
        ArrayControl[i,j].Width   := 25;
        ArrayControl[i,j].Height  := 25;
        //descomente se quiser dar um nome ao componente...
        //ArrayControl[i,j].Name    := 'Component'+ IntToStr(i+1+j);

        //vou 'mudando de coluna'
        Inc(pEsquerda, 30);

      end;

      //volto para a primeira coluna
      pEsquerda := esquerdaAux;
      //'mudo' de linha
      Inc(pTopo,30);
    end;

    //retorno o array de TWinControl
    Result := ArrayControl;

  end;

Função auxiliar para registrar classes (2/2)

procedure RegistrarClasses();
begin

  //para usar o GetClass, é necessário "Registrar" as classes.
  //se precisar alguma outra, coloque aqui.
  RegisterClasses([TButton, TEdit, TGroupBox]);

end;

Exemplo de uso:

Coloque um botão no form e no evento de clique coloque:

procedure TForm1.Button1Click(Sender: TObject);
begin
  MA := CriarComponentes(2,1,35,35,true,GroupBox1,TEdit.ClassName);
end;

Considerações importantes

Perceba que a função retorna “TAr”. Esse é um tipo que eu defini no formulário, para poder retornar matrizes na função.

Ele retorna a matriz para que você tenha acesso a todos os componentes num ponto concentrado.  As declarações ficam assim:

unit uPrincipal;

interface

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

type
  //ESSE TIPO PRECISA SER REGISTRADO PARA RETORNAR UMA MATRIZ NUMA FUNÇÃO.
  TAr = array of array of TWinControl;
  TForm1 = class(TForm)
  ........
  ........
  var
  Form1: TForm1;
  //declaro de forma global para ter acesso
  MA   : TAr;

Isso me permite acessar o componente criado via a matriz (MA[0,0].Propriedade, por exemplo).

Lembre-se de colocar a procedure e a function no mesmo form, a criação depende do registro.

Bom, espero que seja útil ;)

Abraços e até a próxima!

3 pensamentos sobre “Delphi: Componentes em Runtime

  1. hehe delphi é pra roubar todo nosso tempo mesmo …
    pensar que me recusava aprender pascal, tai um aplicativo dependendo de outro .. aff

    abraço …

Deixe um comentário