Componentes - resolvendo problemas com o onexit

Top  Previous  Next

// Cuidados ao 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.

 

Dando continuidade aos problemas enfrentados quando se usa o evento OnExit, 

vamos ver outro caso onde pode acontecer um pequeno problema:

 

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 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, 00);

  Edit2.SetFocus;

end;

 

{ Porém, você nunca terá certeza se o usuário clicou foi 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, 00);

  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.

  }