Neste artigo iremos simular um componente TDateTimePicker para o Firemonkey, já que a ferramenta atual não apresenta tal componente. O método pode sair um pouco da visão do que tratamos de simples, mas pode ser tratado como uma boa alternativa para que possamos agradar nossos usuários.

Em primeiro momento, quando me deparei com a falta do TDateTimePicker no Firemonkey logo fui correndo ver se o TEdit apresentava a propriedade de MaskEdit e novamente fiquei frustrado. Mas as decepções ainda não acabaram, pois nem a edição de máscara do field no ClientDataSet funciona no TEdit. Não querendo desistir do Firemonkey, consegui desenvolver a solução abaixo e resolvi compartilhar com os estudiosos de Firemonkey.

A solução envolve a junção de quatro componentes: TGroupBox, TEdit, TLabel e TButton. Assim, vamos então adicionar ao nosso formulário os componentes abaixo e mudar as seguintes propriedades:

TGroupBox (Qde = 1):
Name: GrpHora;
Height: 49;
Width: 129;

TEdit (Qde = 3): //adicionar dentro do GrpHora;
Name: EdtHora | EdtMinuto | EdtSegundo;
Font | Size: 11;
Height: 22;
KeyBoardType: vktNumberPad //somente números;
TextAlign: taCenter;
Width: 30;

Tlabel (Qde = 2): //adicionar dentro do GrpHora;
AutoSize: True;
Font | Size: 11;
Height: 19;
Text: “:” //não incluir as aspas;
TextAlign: taLeading;
VertTextAlign: taCenter;

TButton(Qde = 1): //adicionar dentro do GrpHora;
Font | Size: 11;
Font | Style | FsBold: True;
Height: 22;
Text: “OK”//não incluir as aspas;
TextAlign: TaCenter;
Width: 33;

Todos esses componentes deverão ser ajustados conforme configuração da figura abaixo:

 Simulação de Componente de Hora

Figura 1: Simulação de Componente de Hora

A máscara de Interface com o usuário está feita, agora vamos aos códigos para conexão com o banco de dados. Para não perder o foco, vou considerar um banco de dados qualquer que tendo sua conexão feita e intermediada por um componente TClientDataSet (CDSHora) possui um field (Coluna) denominado ‘HORA’. Vamos linkar um componente TDataSource a este ClientDataSet e o denominaremos de DSHORA. Todos esses componentes estarão presentes em um DataModule denominado ‘DM’.

Nas declarações públicas do formulário, vamos criar uma variável TDateTime denominada “Hora” e uma procedure de Mudança de Hora (Mudanca_de_Hora). Esta procedure tem o objetivo de atualizar a variável hora, toda vez que os valores dos Edits forem alterados.

Listagem 1: Declaração de variáveis


public
    { Public declarations }
    var
    Hora: TDateTime;
   procedure Mudanca_da_Hora;

Implementando, então, a procedure:

Listagem 2: Implementação o método Mudanca_da_Hora


procedure TFrm1.Mudanca_da_Hora;
var
hh, mm, ss: string;
begin
  if EdtHora.Text = '' then
  begin
    hh := '00';
  end
  else
  begin
    hh := EdtHora.Text;
  end;

  if EdtMinuto.Text = '' then
  begin
    mm := '00';
  end
  else
  begin
    mm := EdtMinuto.Text;
  end;

  if EdtSegundo.Text = '' then
  begin
    ss := '00';
  end
  else
  begin
    ss := EdtSegundo.Text;
  end;

  Hora := StrToTime(concat(hh, ':', mm, ':', ss));
end;

Para que essa mudança de hora ocorra, devemos chamar a procedure no evento OnChange dos 3 componentes TEdit (EdtHora | EdtMinuto | EdtSegundo):

Listagem 3: Evento OnChange dos edits


procedure TFrm1.EdtHoraChange(Sender: TObject);
begin
  Mudanca_da_Hora;
end;
procedure TFrm1.EdtMinutoChange(Sender: TObject);
begin
  Mudanca_da_Hora;
end;
procedure TFrm1.EdtSegundoChange(Sender: TObject);
begin
  Mudanca_da_Hora;
end;

Nota: Você pode, também, ao invés de implementar as 3 procedures com o mesmo código, apenas implementar a procedure no evento OnChange de EdtHora e direcionar os eventos OnChange de EdtMinuto e EdtSegundo para o evento OnChange de EdtHora. Fica a seu critério.

Para que o usuário não precise ficar apertando TAB para passar de um Edit para o outro, achei mais interessante que seja clicado “ENTER” para cumprimento de tal tarefa. Assim sendo...

No Evento OnKeyDown de EdtHora vamos colocar o seguinte procedimento:

Listagem 4: Evento OnKeyDown do EdtHora


  if Key = VK_RETURN then
  begin
    EdtMinuto.SetFocus; //chamando EdtMinuto ao clicar Enter;
    inherited;
  end;

No Evento OnKeyDown de EdtMinuto vamos colocar o seguinte procedimento:

Listagem 5: Evento OnKeyDown do EdtMinuto


if Key = VK_RETURN then
  begin
    EdtSegundo.SetFocus; //chamando EdtSegundo ao clicar Enter;
    inherited;
  end;

No Evento OnKeyDown de EdtSegundo vamos colocar o seguinte procedimento:

Listagem 6: Evento OnKeyDown do EdtSegundo


if Key = VK_RETURN then
  begin
    BtnPost.SetFocus; //chamando BtnPost ao clicar Enter;
    inherited;
  end;

Agora, vamos trabalhar com o Banco de Dados sem precisar lidar com LiveBindings.

Primeiramente, vamos declarar as variáveis na sessão Public do Formulário:

Listagem 7: Declaração de variáveis para hora


Public
//declaração de variáveis
var
Hour, Min, Sec, MSec : Word;

Após o comando insert de sua aplicação coloque o seguinte código:

Listagem 8: Definindo valor inicial para os campos


   DecodeTime(Time,Hour, Min, Sec, MSec);
    EdtHora.Text    := FormatFloat('00', Hour);
    EdtMinuto.Text  := FormatFloat('00', Min);
    EdtSegundo.Text := FormatFloat('00', Sec);
  

E agora, insira o seguinte código após o procedimento de edição (Edit):

Listagem 9: Zerandos os valores da hora ao editar o registro


if (DM.CDSHORA.FieldByName('HORA').IsNull) then
    begin
      EdtHora.Text    := '00';
      EdtMinuto.Text  := '00';
      EdtSegundo.Text := '00';
    end
    else
    begin
      DecodeTime(DM.CDSHORA.FieldByName('HORA_INICIAL').AsDateTime, Hour, Min, Sec, MSec);
      EdtHora.Text    := FormatFloat('00', Hour);
      EdtMinuto.Text  := FormatFloat('00', Min);
      EdtSegundo.Text := FormatFloat('00', Sec);
    end; 

Vamos interpretar o que acabamos de fazer. Primeiro, verificamos qual o modo que vamos trabalhar. Se estiver em modo de inserção, vai aparecer como sugestão de hora para o usuário, exatamente, a hora que ele resolveu inserir o registro. Se estiver em modo de edição, o sistema verifica se existe algo gravado no campo HORA. Se sim, o sistema resgata esse registro, senão, mostra a hora ’00:00:00’.

E por último, vamos fazer a implementação do botão BTnPost que tem a função de lançar o valor da variável Hora para o Field HORA do banco de dados. No evento Onclick do Botão:

Listagem 10: Evento OnClick do botão para salvar


procedure TFrm1.BtnPostClick(Sender: TObject);
begin
  DM.CDSCONFIG.FieldByName('HORA_INICIAL').AsDateTime := Hora;
end;

Desta forma é possível utilizar uma interface que certamente irá agradar o cliente, enquanto aguardamos, é claro, que a Embarcadero desenvolva um componente TDateTime.

Espero que tenham gostado. Um abraço e até o próximo artigo.