A maneira mais comum de mover uma janela é arrastá-la pela barra de título. Continue lendo para descobrir como você pode fornecer recursos de arrastar para Delphi formulários sem uma barra de título, para que o usuário possa mover um formulário clicando em qualquer lugar na área do cliente.
Por exemplo, considere o caso de um Aplicação do Windows que não possui uma barra de título, como podemos mover essa janela? De fato, é possível criar janelas com uma barra de título fora do padrão e até formas não retangulares. Nesse caso, como o Windows poderia saber onde estão as bordas e os cantos da janela?
A mensagem do Windows WM_NCHitTest
o Sistema operacional Windows é fortemente baseado em manipulação de mensagens. Por exemplo, quando você clica em uma janela ou em um controle, o Windows envia uma mensagem wm_LButtonDown, com informações adicionais sobre onde está o cursor do mouse e quais teclas de controle estão atualmente pressionado. Soa familiar? Sim, isso nada mais é do que um evento OnMouseDown no Delphi.
Da mesma forma, o Windows envia uma mensagem wm_NCHitTest sempre que um evento do mouse ocorre, ou seja, quando o cursor se move ou quando um botão do mouse é pressionado ou solto.
Código para entrada
Se conseguirmos fazer com que o Windows pense que o usuário está arrastando (clicou) na barra de título em vez da área do cliente, o usuário pode arrastar a janela clicando na área do cliente. A maneira mais fácil de fazer isso é "enganar" o Windows, pensando que você está realmente clicando na barra de título de um formulário. Aqui está o que você deve fazer:
1. Insira a seguinte linha na seção "Declarações privadas" do formulário (declaração do procedimento de tratamento de mensagens):
procedimento WMNCHitTest (var Msg: TWMNCHitTest); mensagem WM_NCHitTest;
2. Adicione o seguinte código na seção "implementação" da unidade do seu formulário (onde Form1 é o nome do formulário assumido):
procedimento TForm1.WMNCHitTest (var Msg: TWMNCHitTest);
início
herdado;
E se Msg. Resultado = htClient então Msg. Resultado: = htCaption;
fim;
A primeira linha de código no manipulador de mensagens chama o método herdado para obter o tratamento padrão da mensagem wm_NCHitTest. A parte If do procedimento intercepta e altera o comportamento da sua janela. É o que realmente acontece: quando o sistema operacional envia uma mensagem wm_NCHitTest para a janela, juntamente com as coordenadas do mouse, a janela retorna um código que indica qual parte de si foi atingido. A informação importante, para nossa tarefa, está no valor da Msg. Campo de resultado. Neste ponto, temos a oportunidade de modificar o resultado da mensagem.
É isso que fazemos: se o usuário clicou na área do cliente do formulário, fazemos o Windows pensar que o usuário clicou na barra de título. Dentro Object Pascal "words": se o valor de retorno da mensagem for HTCLIENT, simplesmente o alteramos para HTCAPTION.
Não há mais eventos de mouse
Ao alterar o comportamento padrão de nossos formulários, removemos a capacidade do Windows de notificá-lo quando o mouse estiver sobre a área do cliente. Um efeito colateral desse truque é que seu formulário não gerará mais eventos para mouse mensagens.
Janela sem legenda
Se você deseja uma janela sem borda sem legenda semelhante a uma barra de ferramentas flutuante, defina a Legenda do formulário como uma sequência vazia, desative todos os BorderIcons e defina o BorderStyle como bsNone.
Um formulário pode ser alterado de várias maneiras, aplicando código personalizado no método CreateParams.
Mais truques do WM_NCHitTest
Se você olhar com mais cuidado a mensagem wm_NCHitTest, verá que o valor de retorno da função indica a posição do ponto ativo do cursor. Isso nos permite brincar um pouco mais com a mensagem para criar resultados estranhos.
O seguinte fragmento de código impedirá que os usuários fechem seus formulários clicando no botão Fechar.
E se Msg. Resultado = htClose então Msg. Resultado: = htNowhere;
Se o usuário estiver tentando mover o formulário clicando na barra de legenda e arrastando, o código substituirá o resultado da mensagem por um resultado que indique que o usuário clicou na área do cliente. Isso evita que o usuário mova a janela com o mouse (ao contrário do que estávamos fazendo no início do artigo).
E se Msg. Resultado = htCaption então Msg. Resultado: = htClient;
Tendo componentes em um formulário
Na maioria dos casos, teremos alguns componentes em um formulário. Digamos, por exemplo, que um objeto do Painel esteja em um formulário. Se a propriedade Align de um painel estiver definida como alClient, o Painel preencherá toda a área do cliente, de modo que seja impossível selecionar o formulário pai clicando nele. O código acima não funcionará - por quê? É porque o mouse está sempre se movendo sobre o componente Painel, não no formulário.
Para mover nosso formulário arrastando um painel, precisamos adicionar algumas linhas de código no procedimento de evento OnMouseDown para o componente Panel:
procedimento TForm1.Panel1MouseDown
(Remetente: TObject; Botão: TMouseButton;
Shift: TShiftState; X, Y: Inteiro);
início
ReleaseCapture;
SendMessage (Form1.Handle, WM_SYSCOMMAND, 61458, 0);
fim;
Nota: Esse código não funcionará com controles que não são de janela, como Componentes TLabel.