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:
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.