Fórum Problemas com o foco e Onkeydown #213715
12/02/2004
0
Salve Pessoal
Mais uma vez recorro à vocês para tentar solucionar este mistério:
Eu faço uso do evento onKeyDown, onde eu processo algumas teclas, como F6 inclui, F3 Procura, F7 Grava, para isto utilizo uma função que tem a seguinte construção:
Como podem notar pelos parametros da função estou utilizando o componente DBNavigator da Infopower.
O que esta acontecendo é que em muitos de meus forms eu tenho um PopUp onde acessou outros forms, ex: estou no form de clientes e quero inserir uma cidade, então clico com o botão direito e seleciono Cidades no menu popup,
quanto volto ao form de clientes ele ignora o pressionamento das teclas, e nem passa pelo evento OnKeyDowm, a chamada da função é assim:
Quando volta ao form não consigo enviar o foco para lugar algum, e quando pressiono enter aparece aquele popup do windows, Restaurar, Mover, tamanho.. etc..
Alguém já passou por isto??
Se alguém puder me ajudar desde já agradeço
Fausto
[b:433ea8c783]Editado(Beppe): Use o botão code, ao postar códigos.[/b:433ea8c783]
Mais uma vez recorro à vocês para tentar solucionar este mistério:
Eu faço uso do evento onKeyDown, onde eu processo algumas teclas, como F6 inclui, F3 Procura, F7 Grava, para isto utilizo uma função que tem a seguinte construção:
procedure EnterAsTab(Frm:TForm; Var Key:Word;const Nav:TwwDBNavigator); var Dummy : TMsg ; begin if (Key in [VK_F2..VK_F10]) then begin if (Key = VK_F2) and (Nav.Buttons.Items[6].Visible) then Nav.Buttons.Items[6].Click; // Editar if (Key = VK_F3) and (Nav.Buttons.Items[10].Visible) then Nav.Buttons.Items[10].Click; // Pesquisar if (Key = VK_F4) and (Nav.Buttons.Items[9].Visible) then Nav.Buttons.Items[9].Click; // Imprimir if (Key = VK_F5) and (Nav.Buttons.Items[11].Visible) then Nav.Buttons.Items[11].Click; // Filtrar if (Key = VK_F6) and (Nav.Buttons.Items[4].Visible) then Nav.Buttons.Items[4].Click; // Incluir if (Key = VK_F7) and (Nav.Buttons.Items[7].Visible) then Nav.Buttons.Items[7].Click; // Gravar if (Key = VK_F8) and (Nav.Buttons.Items[5].Visible) then Nav.Buttons.Items[5].Click; // Excluir if (Key = VK_F9) and (Nav.Buttons.Items[8].Visible) then Nav.Buttons.Items[8].Click; // Cancelar if (Key = VK_F10) and (Nav.Buttons.Items[12].Visible) then Nav.Buttons.Items[12].Click; // Sair end; if ((Key = VK_RETURN) and not (Frm.ActiveControl is TDBMemo)) then begin PeekMessage(Dummy, Frm.Handle, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) ; if not ((Frm.ActiveControl is TDBGrid) or (Frm.ActiveControl is TwwDBGrid)) then begin Frm.Perform(WM_NEXTDLGCTL, 0, 0); end; if (Frm.ActiveControl is TDBGrid) then begin with TDBGrid(Frm.ActiveControl) do begin if selectedIndex < (fieldcount -1) then selectedindex := selectedindex +1 else selectedindex := 0; end; end; end; if ((Key = VK_RETURN) and (Frm.ActiveControl is TDBMemo)) then Frm.Perform(WM_NEXTDLGCTL, 0, 0); end;
Como podem notar pelos parametros da função estou utilizando o componente DBNavigator da Infopower.
O que esta acontecendo é que em muitos de meus forms eu tenho um PopUp onde acessou outros forms, ex: estou no form de clientes e quero inserir uma cidade, então clico com o botão direito e seleciono Cidades no menu popup,
quanto volto ao form de clientes ele ignora o pressionamento das teclas, e nem passa pelo evento OnKeyDowm, a chamada da função é assim:
procedure TClienteForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin EnterAsTab(ClienteForm,Key,INavigator); end;
Quando volta ao form não consigo enviar o foco para lugar algum, e quando pressiono enter aparece aquele popup do windows, Restaurar, Mover, tamanho.. etc..
Alguém já passou por isto??
Se alguém puder me ajudar desde já agradeço
Fausto
[b:433ea8c783]Editado(Beppe): Use o botão code, ao postar códigos.[/b:433ea8c783]
Faustoalves
Curtir tópico
+ 0
Responder
Posts
12/02/2004
Fabio.hc
Achei esta dica, talvez te ajude: Mesmo vc não codificando o onexit este evento é executado.
[b:f799160805]Cuidados ao usar o OnExit (Parte I):[/b:f799160805]
É 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.
[b:f799160805]Cuidados ao usar o OnExit (Parte II):[/b:f799160805]
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, 0, 0);
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, 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.
[b:f799160805]Cuidados ao usar o OnExit (Parte I):[/b:f799160805]
É 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.
[b:f799160805]Cuidados ao usar o OnExit (Parte II):[/b:f799160805]
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, 0, 0);
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, 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.
Responder
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)