Sábado, Novembro 20, 2004

Fechando um menu quando o mouse não está sobre ele

Hoje recebi esta pergunta de um leitor:

Ao colocar um ícone na bandeja do Windows, ao dar um clique com o botão da direita no ícone, aparece um menu de opções. Como fazer este menu desaparecer se o mouse sair de dentro do perímetro dele?

Esta não é tão simples de se fazer, pois não temos controle sobre a janela do menu. A maneira que imaginei é colocar um TTimer e verificar a janela abaixo do Mouse. Se for o menu, continuamos com ele ativo. Se não for, fechamos o menu. Para isso, definimos uma variável FEntrou na parte privada da Form, que irá controlar se o mouse já entrou no menu (ao ativar o menu, o mouse deve estar sobre a bandeja do Windows):

private

FEntrou : Boolean;

Colocamos um TTimer na Form, configurando a propriedade Interval para 100, de maneira a verificar a posição a cada 100 ms e, no evento OnTimer, colocamos o seguinte:


procedure TForm1.Timer1Timer(Sender: TObject);
var
PosMenu: TPoint;
Wnd: HWND;
ClassName: Array [0..80] of Char;
begin
// Pega posição do Mouse
GetCursorPos(PosMenu);
// Pega a janela sob o mouse
Wnd := WindowFromPoint(PosMenu);
if Wnd <> 0 then begin
// Achou janela - pega o nome da classe;
GetClassname(Wnd, Classname, 80 );
if FEntrou and (String(ClassName) <> '#32768') then begin
// Se já entrou no menu e a janela é diferente da do menu
// (ClassName é diferente de #32768)
// Fecha o menu
EndMenu;
Timer1.Enabled := False;
FEntrou := False;
end
else if (not FEntrou) and (String(ClassName) = '#32768') then
// Ainda não entrou, mas a janela é a do menu,
// configura FEntrou para True
FEntrou := True;
end;
end;

Devemos deixar a propriedade Active para False, para que o evento não seja chamado quando o programa iniciar. Precisamos apenas ativar o Timer no evento OnPopup do PopuMenu:


procedure TForm1.PopupMenu1Popup(Sender: TObject);
begin
Timer1.Enabled := True;
end;
Assim, nosso menu é fechado quando o mouse estiver fora dele.

6 Comentários:

At 2:28 PM, Blogger Marco disse...

Muito obrigado pela Dica. Vou testá-la hoje. Marco Aurélio.

 
At 2:52 PM, Blogger Marco disse...

Teste a tua Dica e ela é sensacional. Funcionou legal. Só fiquei com algumas dúvidas sobre o código:
________________________________________________________

GetClassname(Wnd, Classname, 80 );
if FEntrou and (String(ClassName) <> '#32768') then
begin
EndMenu;
________________________________________________________

Não achei no Help do Delphi as delcarações: GetClassname e EndMenu, e gostaria de saber o que são eles e o significado do código #32768.

Obrigado!!!
Marco Aurélio

 
At 10:05 AM, Blogger Bruno disse...

Quando uma janela é criada no Windows, é dada a ela um nome de classe. GetClassName é uma função da API do Windows que recupera o nome da classe (não tem nada a ver com o nome da classe do Delphi).
No caso, 32768 é o nome da classe das janelas de diálogo padrão do Windows, e das janelas de menu. O que estou fazendo aqui é pegando o nome da classe da janela e verificando se ele é 32768. Se for, é o menu, que estou querendo.

 
At 4:21 PM, Anonymous Anônimo disse...

Por gentileza, como faria para que após um determinado tempo todas as janelas fecharem forçadamente?

 
At 12:20 PM, Anonymous Anônimo disse...

Como fazer para pegar o posição click do mouse fora do form???

 
At 1:49 PM, Blogger Bruno disse...

Para pegar fora do Form, você pode usar a função da API SetCapture, que captura as mensagens do Mouse

 

Postar um comentário

<< Home