Ir para conteúdo
Fórum Script Brasil
  • 0

Executar Evento antes de Procedimento


Vivendo&Aprendendo

Pergunta

Olá pessoal

Tenho um procedimento que verifica as mensagens enviadas para o windows, nesse procedimento ele veifica se a tecla precionada for tab ele não deixa mudar de campo, se for enter ele muda o foco de campo:

Procedure TForm1.CMDialogKey(Var Msg: TWMKEY);
begin
  if ((ActiveControl is TDBEdit) or (ActiveControl is TEdit) or (ActiveControl is TDBComboBox) or (ActiveControl is TComboBox)
  or (ActiveControl is TDBLookupComboBox) or (ActiveControl is TDBMemo)) and (TEdit(ActiveControl).Focused) then
  begin
    if (Msg.Charcode = VK_TAB) then
      Msg.Result := 0
    else
      if (Msg.Charcode = VK_RETURN) then
      begin

        Msg.Result := -1;
        SelectNext(ActiveControl, True , True);
      end;
  end
  else
    inherited;
end;

Mas também tenho no meu edit um evento OnKeyDown que só por causa deste código acima ele não executa nada que está no KeyDown, KeyPress ou KeyUp dos componentes, e preciso saber no KeyDown do edit se a tecla for igual a enter ele fazer alguma coisa, mas não faz nada ele simplesmente ignora os eventos onkey.

Como posso fazer para que ele execute primeiro o evento do edit e depois ele faça a execução deste procedimento acima?

Alexandre

Link para o comentário
Compartilhar em outros sites

6 respostass a esta questão

Posts Recomendados

  • 0

Oi, Vivendo&Aprendendo!

No form principal coloque o componente TApplication

Como função privativa declare

type
  TFrmP000000 = class(TForm)
...
  private
      { Private declarations }
      procedure prvMudarComEnter(var Msg: TMsg; var Handled: Boolean);
...
end;
Na criação do form principal coloque
procedure TFrmP000000.FormCreate(Sender: TObject);
begin
...
   Application.OnMessage := prvMudarComEnter;
...
end;
No corpo do form principal escreva:
procedure TFrmP000000.prvMudarComEnter(var Msg: TMsg; var Handled: Boolean);
begin
   if not((Screen.ActiveControl is TCustomMemo) or
         (Screen.ActiveControl is TCustomGrid) or
         (Screen.ActiveForm.ClassName = 'TMessageForm')or
         (Screen.ActiveControl is Tbutton)) then
      if Msg.message = WM_KEYDOWN then
         case Msg.wParam of
            VK_RETURN, VK_DOWN: Screen.ActiveForm.Perform(WM_NextDlgCtl, 0, 0);
            VK_UP:              Screen.ActiveForm.Perform(WM_NextDlgCtl, 1, 0);
         end;
end;

Link para o comentário
Compartilhar em outros sites

  • 0
Mas também tenho no meu edit um evento OnKeyDown que só por causa deste código acima ele não executa nada que está no KeyDown, KeyPress ou KeyUp dos componentes, e preciso saber no KeyDown do edit se a tecla for igual a enter ele fazer alguma coisa, mas não faz nada ele simplesmente ignora os eventos onkey.

Vivendo&Aprendendo, você pode experimentar esta modificação:

Procedure TForm1.CMDialogKey(Var Msg: TWMKEY);
begin
  Msg.Result := -1;
  if ((ActiveControl is TDBEdit) or 
   (ActiveControl is TEdit) or 
   (ActiveControl is TDBComboBox) or 
   (ActiveControl is TComboBox) or 
   (ActiveControl is TDBLookupComboBox) or 
   (ActiveControl is TDBMemo)) and (TEdit(ActiveControl).Focused) then
  begin
    if (Msg.Charcode = VK_TAB) then
      Msg.Result := 0
    else
      if (Msg.Charcode = VK_RETURN) then
        SelectNext(ActiveControl, True , True);
  end;
end;

Observe que está sendo feito alguma coisa com o ENTER porque é o único momento em que você atribuia o valor -1 a Result. Se você souber porque deve fazer este tipo de atribuição, saberia que é a forma de você "dizer" para o sistema que você não processou o evento. Já quando você atribui o 0 (zero), você está dizendo que processou, e então, o sistema após a chamada ao seu procedimento não fará mais nada com ele.

Para todos os efeitos, apenas quando for pressionado VK_TAB, você deveria enganar o sistema informando que processou a tecla.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Olá Micheus...

ou eu não entendi o que você explicou ou você não entendeu o meu problema... :blush:

Eu coloquei o seu código no form, ele faz tudo beleza (o enter funciona como o tab e o tab não faz nada) exatamente o que eu preciso, mas em um dos meus edit's eu tenho o seguinte código no OnKeyDown:

If Key = VK_RETURN Then
    If Edit2.Text = '' Then
    begin
      Application.MessageBox('Campo não pode ser em branco!','Aviso',MB_ICONHAND+MB_OK);
      edit2.SetFocus;
    end;

E por causa deste código que você alterou e o que usava antes o delphi não "lê" nenhum evento OnKeyDown do meu form, componente, etc.

Porque isso?

Alexandre

Link para o comentário
Compartilhar em outros sites

  • 0
E por causa deste código que você alterou e o que usava antes o delphi não "lê" nenhum evento OnKeyDown do meu form, componente, etc.

Porque isso?

Vivendo&Aprendendo, o motivo é porque a alteração que sugeri resultou no mesmo efeito que o seu código.

No processo de manipulação da mensagem enviada pelo sistema para a aplicação, chega até o procedimento a mensagem (Msg) que nós processamos ou mesmo os métodos antecessores (em inherited). Quando para a tecla VK_TAB o seu (e o "meu") código atribui a Msg.Result o valor 0, e não fazemos nada mais, ao retornar ao procedimento que chamou este nosso procedimento entende que a mensagem foi tratada e não faz mais nada, ou seja, não executa seu procedimento padrão. Foi isso que tentei explicar quando falei dos valores para Result no post anterior.

Eu acabei por me precipitar ao citar a alteração, e não me dei conta que ficaria na mesma. Desculpe. :blush:

Mas, vamos tentar sanar este problema...

A proposta do colega Denis Courcy de usar o evento OnMessage do objeto Application tem como vantagem, aplicar-se a todos os forms - você não tem que duplicar o código em cada form.

Entretanto, para este caso, haverão alguns efeitos colaterais, sendo um deles baseado no que citei acima:

Ao "processarmos" a tecla ENTER, mas não informando ao método antecessor que fizemos isto (quando atribuirmos True ao parâmetro Handled), o foco será movido para o próximo controle pela chamada ao método Perform, mas será executado pelo procedimento padrão para a tecla pressionada e serão, gerados eventos como OnKeyPress, OnKeyDown e OnKeyUp. Só terá um porém:

Será processada o evento pelo componente que está com o foco, ou seja, o componente seguinte ao que teve teclado o ENTER. Assim, no exemplo em que testei, após o edit havia um botão que teve seu procedimento executado como se eu tivesse pressionado ele (OnClick). Quando o próximo componente era um TEdit, resultava em um Beep - que é o padrão quando se tecla ENTER em um TEdit.

Por outro lado, se atribuirmos True ao parâmetro Handled, informando que processamos a tecla, votaremos a estaca zero, pois os evento como OnKeyPress, OnKeyDown e OnKeyUp, não ocorrerão ao pressionar ENTER.

É só testar estas situações, para entender o que tentei explicar.

Mesmo assim, a sugestão é que você use esta última situação porque, além de ser mais genérica, o tipo de validação que você está fazendo é tem como lugar mais apropriado o evento OnExit do que o OnKeyDown. Sabe por quê? Porque usuário nem sempre usa só o teclado e ao usar o mouse para mover o foco, o seu processo de validação fica furado ao tratar apenas a tecla!!!

Voce só tem que cuidar, ao usar o evento OnExit, quando houver algo como um botão de cancelamento, pois ao clicar nele será gerado o evento OnExit e neste caso, você deverá testar se o tal botão é o controle ativo (ActiveControl).

Se optar por esta saída, segue procedimento para o evento OnMessage ajustado para ignorar a tecla TAB (que ficou faltando). Quanto a testar a classe do componente deve ser processado, fica o critério do que você acha que vai simplificar seu trabalho:

- se as que não devem (exemplo do colega Denis Courcy):

procedure TFrmP000000.prvMudarComEnter(var Msg: TMsg; var Handled: Boolean);
begin
   if not((Screen.ActiveControl is TCustomMemo) or
         (Screen.ActiveControl is TCustomGrid) or
         (Screen.ActiveControl is TButton)) then
      if Msg.message = WM_KEYDOWN then
         case Msg.wParam of
            VK_RETURN, 
            VK_DOWN:
                begin
                  Screen.ActiveForm.Perform(WM_NextDlgCtl, 0, 0);
                  Handled := True;
                end;
            VK_UP: Screen.ActiveForm.Perform(WM_NextDlgCtl, 1, 0);
            VK_TAB: Handled := True;
         end;
end;
- ou, se verificar as que devem ser processadas (exemplo abaixo):
procedure TForm1.CustomOnMessage(var Msg: TMsg; var Handled: Boolean);
begin
  if Msg.message = WM_KEYDOWN then
    if (Screen.ActiveControl is TCustomEdit) then
      case Msg.wParam of
        VK_RETURN :
          begin
            Screen.ActiveForm.Perform(WM_NEXTDLGCTL, 0, 0);
            Handled := True;
          end;
        VK_TAB : Handled := True;
      end;
end;
neste exemplo, usei a classe antecessora mais acima das classes TEdit, TMaskEdit, TDBEdit, TMemo e TDBMemo, que é TCustomEdit - antecessora de todas elas. Você descobre isto através do help, clicando em Hierarchy e achando as que são comuns aos componentes que lhe interessam verificar. o evento OnExit, ficaria assim:
procedure TForm1.Edit1Exit(Sender: TObject);
begin
  if ActiveControl <> btnSair then
    if Trim(TEdit(Sender).Text) = '' then
    begin
      Application.MessageBox('Campo não pode ser em branco!',
                             'Aviso',
                             MB_ICONHAND+MB_OK);
      TEdit(Sender).SetFocus;
    end;
end;

e ele está construído de modo genérico, para que seja atribuído ao evento de outros TEdits que tenham esta validação.

Abraços

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,2k
    • Posts
      651,9k
×
×
  • Criar Novo...