terça-feira, 16 de junho de 2009

Cuidados ao usar se usar o onexit

{É comum fazermos uso do evento OnExit quando queremos validar o conteúdo de um Edit. E essa pode ser uma boa prática quando necessitamos verificar o que foi digitado apenas quando o usuário terminar de fazer a entrada de dados, como, por exemplo, um Edit que vai receber o CPF ou CNPJ. Ao colocarmos um código qualquer no evento OnExit ele sempre será executado quando o usuário sair do Edit, o que acontece quando ele pressiona a tecla TAB, clica com o mouse em um outro Edit ou pressiona um botão OK, por exemplo.

No entanto, existem algumas situações especiais em que o evento OnExit não é gerado. Quer um exemplo? Você está no Edit e, ao invés de clicar no botão OK, você pressiona as teclas ALT + O (considerando que o botão OK tem a tecla O como atalho). É como se você tivesse pressionado o botão OK, porém, sem perder o foco que está no Edit. Só mais um exemplo: Os botões do tipo SpeedButton não recebem foco, então, mesmo que clique com o mouse sobre um SpeedButton, o foco continuará no Edit e, conseqüentemente, o evento OnExit não será gerado.

E a solução?

A solução para esse pequeno inconveniente é simples. Basta você colocar o seguinte código no evento OnClick do botão.}

procedure TForm1.Button1Click(Sender: TObject);
begin
ActiveControl := nil;
...
end;

{Com isso você força a saída de qualquer Edit ou outro componente que esteja com o foco, gerando assim o evento OnExit.

Suponhamos que você possua 2 Edits em um formulário. Supondo também que você queira dar alguma informação ao usuário da aplicação logo depois que ele sair do Edit1 você faz:}


procedure TForm1.Edit1Exit(Sender: TObject);
begin
MessageDlg('Mensagem...', mtInformation, [mbOk], 0);
end; {A princípio está tudo ok, ou melhor, parece estar tudo ok.

Se você altera o foco para o outro Edit através do pressionamento da tecla TAB, tudo bem. Mas experimente alterar o foco clicando com o mouse sobre o Edit2. Neste segundo caso a mensagem será exibida normalmente. Mas ao fechar o dialogo onde aparece a mensagem, o foco simplesmente se perde. Para setar o foco no Edit2 é necessário clicar novamente sobre ele.

Isso poderia não ser problema nenhum até que seu usuário experimente esta situação. Nada que ele digitar será acatado.

Mas existe uma maneira fácil de resolver o problema. Basta você cancelar o foco e forçar uma reentrada no componente Edit2. Como fazer isso? Veja o código:}


procedure TForm1.Edit1Exit(Sender: TObject);
begin
MessageDlg('Mensagem...', mtInformation, [mbOk], 0);
// cancela o foco e força novamente a entrada
ActiveControl := nil;
PostMessage(Edit2.Handle, WM_SETFOCUS, 0, 0);
Edit2.SetFocus;
end; {Porém, você nunca terá certeza se o usuário clicou no Edit2. Então temos que criar uma rotina genérica que leva o foco para qualquer outro controle:}


procedure TForm1.Edit1Exit(Sender: TObject);
var
Ctrl: TWinControl;
begin
MessageDlg('Mensagem...', mtInformation, [mbOk], 0);
// cancela o foco e força novamente a entrada
Ctrl := ActiveControl;
ActiveControl := nil;
PostMessage(TWinControl(Ctrl).Handle, WM_SETFOCUS, 0, 0);
TWinControl(Ctrl).SetFocus;
end; {Observe que antes de cancelar o foco com ActiveControl := nil, salvamos qual é o controle que detém o foco fazendo Ctrl := ActiveControl.

Depois enviamos uma mensagem ao controle que detinha o foco, forçando-o a receber o foco novamente.}

Nenhum comentário:

Postar um comentário