Acredito que um grande desafio para cada sistema que vamos desenvolver é cumprir as metas de prazos estabelecidos e muitas vezes acabamos perdendo tempo desenvolvendo telas que já criamos em outros sistemas, mas que temos que recria-las. Agora imagine podermos ter prontos determinados "pedaços" de telas para reutilizarmos em qualquer sistema? É ai que entra o componente TFrame.

Este componente pode ser encontrado em FILE > NEW > Frame.

O HELP do delphi chama ele de "TFrame is a container for components; it can be nested within forms or other frames" ou seja é um "container de componentes que pode ser usado em um ou vários form's".

Vamos para a prática. Imagine uma tela de cadastro de clientes onde é necessário cadastrar o rua, número, complemento, bairro, cidade etc..., assim:

Layout da tela de cadastro
Figura 1. Layout da tela de cadastro

Pense comigo, quando criamos telas para cadastro de fornecedores, vendedores ou outra tela que envolva cadastro de uma entidade não precisamos sempre colocar os mesmos campos de endereço? Bom para facilitar nosso trabalho e otimizar o desenvolvimento é que vamos criar um frame para endereços onde vamos conseguir inserir em qualquer form de nosso projeto ou Grupo de projetos.

Siga os passos:

  1. File > New > Frame (Insira um novo Frame, altere a propriedade NAME para FrameEndereco e salve);
  2. Após insira edit's e label's deixando ele como na figura abaixo;
  3. Se tudo estiver ok, basta abrir o form no qual você deseja inserir o frame e clicar na PALETE STANDARD EM FRAMES, selecione o frame pelo nome que você salvou e será inserido automaticamente no form.
Aparência do frame criado
Figura 2. Aparência do frame criado

Uma vez inserido o Frame no form, sempre que precisar acessar um valor dentro do frame é necessário primeiro indicar o nome do frame, exemplo:


FrameEndereco1.edtRua.Text:='Rua Caipos';
Listagem 1. Referenciando elementos do frame (primeira forma)

ou, se preferir,


with FrameEndereco1 do begin
edtRua.Text:='Rua Caipos';
edtNumero.Text:='111'
end;
Listagem 2. Referenciando elementos do frame (segunda forma)

E assim por diante.

Observação: O que for alterado no Frame se replicará em todas as telas em que ele estiver inserido.

Mas vamos imaginar algo mais complexo, imagine um ComboBox onde você precisa inserir, e excluir valores genéricos para tabelas genéricas, neste exemplo vou utilizar classes já criadas em artigos anteriores, Listas Encadeadas e Framework em Delphi. Vamos ao exemplo: Imagine um Combobox onde, em RUN TIME , seja necessário em um Form salvar e excluir o nome de cidades e em outro form o salvar e excluir o nome de vendedores. Mãos a obra então.

Siga os passos:

  1. File > New > Frame(Insira um novo Frame, altere a propriedade NAME para FrameComboGenerics e salve);
  2. Após, insira UtilComboBox(Ler artigo) e label's deixando ele como na figura abaixo;
Frame com Combobox de valores dinnâmicos
Figura 3. Frame com Combobox de valores dinâmicos

Muto bem, agora vamos criar alguns métodos.


unit ComboGenericsFrame;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, UtilComboBox, UtilSqlSuid, UtilList;
type
  TFrameComboGenerics = class(TFrame)
    edtCombo: TUtilComboBox;
    LbTitulo: TLabel;
    procedure edtComboKeyPress(Sender: TObject; var Key: Char);
    procedure edtComboChange(Sender: TObject);
    procedure edtComboContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure edtComboCloseUp(Sender: TObject);
    procedure edtComboClick(Sender: TObject);
  private
    { Private declarations }
             Table, Field:string;
    	ValueId:integer;
    	DataBase:TDataModule;
  public
    { Public declarations }
   //variáveis publicas que serão utilizadas para criar a 
   //lista de dados e o componente de conexão com o banco de dados
    QSql:TUtilSqlSuid;
    QList:TUtilList;
    procedure CreateCombo(Table_,Field_:string;ValueId_:Integer);
    //create para setar o nome da tabela a ser usada, o Campo de 
    //pesquisa e o Id do registro quando houver
    procedure SetTitulo(msgTitulo:string);
    procedure SaveCombo;
    //Salvar o registro inserido
    procedure LoadCombo;
    //Carregar os valores da tabela setada no CreateCombo
    procedure SetValue(IdValue:Integer);
    //Setar como default no Combo o registro que possuir o IdValue inserido
    function  GetIdValue:Integer;
    //Capturar o id do registro selecionado no combo
    procedure ReposicionaLabel;
  end;
Listagem 3. Código do frame criado

Muito bem, uma vez criado os métodos vamos desenvolvê-los, como abaixo:


{ TFrameComboGenerics }

procedure TFrameComboGenerics.CreateCombo(Table_, Field_: string;
  ValueId_: Integer);
begin
  Table  :=Table_;
  Field  :=Field_;
  ValueId:=ValueId_;
end;


procedure TFrameComboGenerics.edtComboKeyPress(Sender: TObject; var Key: Char);
begin
  if Key=#13 then begin
    if edtCombo.Items.IndexOf(edtCombo.Text)=-1 then begin
      SaveCombo;
   //   LbMensagem.Caption:='';
  //    LbMensagem.Caption:='Registro SALVO';
      Sleep(200);
   //   LbMensagem.Caption:='...';
   //   LbMensagem.Repaint;
    end;
  end;
end;


function TFrameComboGenerics.GetIdValue: Integer;
var QValue:TUtilSqlSuid;
begin
  //buscar o ID da string selecionada
  QValue:=TUtilSqlSuid.Create(Table, Field, 0);
  QValue.CreateOpenQuery('Select * from '+Table+' Where '+field+ ' = '''+edtCombo.Text+'''');
  Result:=QValue.GetIntegerField('Id'+Table);
  QValue.free;
end;

procedure TFrameComboGenerics.LoadCombo;
begin
   [atráves de uma lista encadeada estamos carregando o combobox]
   QSql:=TUtilSqlSuid.Create(Table, Field, ValueId);
   QSql.OpenSimpleQuery;
   Qsql.first;
   QList:=TUtilList.Create;
   while not Qsql.Eof do begin
    QList.Add(QSql.GetStringField(Field));
    QSql.next;
   end;
[Colocamos a lista com todos os dados da tabel para dentro do ComboBox]
   edtCombo.UtilList:=QList;
   QSql.Free;
end;


procedure TFrameComboGenerics.ReposicionaLabel;
begin
//  LbMensagem.Left:=LbTitulo.Width+5;
end;

procedure TFrameComboGenerics.SaveCombo;
begin
  //Atra´ves do estanciamento da classe estamos salvando o registro inserido, claro
  //que seria legal criar um regra para verificar duplicidade
  QSql:=TUtilSqlSuid.Create(Table, Field, ValueId);
  QSql.OpenSimpleQuery;
  QSql.ClearList;
  QSql.AddStringField(Field,''+UpperCase(edtCombo.Text)+'');
  QSql.ExecuteInsert ;
  QSql.Free;
end;

procedure TFrameComboGenerics.SetTitulo(msgTitulo: string);
begin
  //Alterar o caption do Label
  LbTitulo.Caption:=msgTitulo;
  LbTitulo.Repaint;
end;


procedure TFrameComboGenerics.SetValue( IdValue: Integer);
var QValue:TUtilSqlSuid;
begin
  //Busca através do ID o valor String Correspondente
  QValue:=TUtilSqlSuid.Create(Table, 'Id'+Table, IdValue);
  QValue.OpenQuery;
  edtCombo.ItemIndex:=edtCombo.Items.IndexOf(QValue.GetStringField(Field));
  QValue.free;
end;

end.
Listagem 4. Desenvolvimento dos métodos do frame criado

Feito isso é só inserir no formulário e setar os métodos necessários assim:


FrameComboLocal.CreateCombo('reg_LocalChale','Nome',0);
//Estou aqui informando o nome da tabela e qual campo desejo que 
popule o combobox
FrameComboLocal.LoadCombo;
//Realizando o LoadCombo para carregar os dados
FrameComboLocal.SetValue(QSql.GetIntegerField('IdLocal'));
//Seto um registro default com o ID que puxo do banco
Listagem 5. Utilizando o frame
Resultado final
Figura 4. Resultado final

Com isso podemos inserir este frame em vários forms, trocando os parâmetros do create.