Informática Numaboa - Tutoriais e Programação
Janela Numaboíssima (masm)
Qui 16 Abr 2009 00:00 |
- Detalhes
- Categoria: Assembly Numaboa (antigo oiciliS)
- Atualização: Domingo, 21 Junho 2009 18:46
- Autor: vovó Vicki
- Acessos: 11438
Pintando a janela com a máscara
Assim que uma janela é criada, ato contínuo ela começa a ser pintada. Precisamos monitorar a pintura para garantir que nosso bitmap "transparentado", obtido a duras penas, seja utilizado como máscara da nossa janela. A primeira providência é iniciar um sessão de pintura com BeginPaint e declarar uma variável local para receber o manipulador do contexto de dispositivo obtido e uma do tipo PAINTSTRUCT para receber as informações sobre a pintura. Depois precisamos obter a área retangular da janela com a função GetWindowRect e criar um contexto de dispositivo compatível com CreateCompatibleDC (se tiver dúvidas, veja novamente no tutorial "Pintando Texto"). Em seguida selecionamos o bitmap com SelectObject.
Lembre-se de que todo BeginPaint precisa terminar com um EndPaint para liberar o contexto de dispositivo para outras operações.
Transferindo blocos de bits
Agora é só transferir as "cores dos pixels" para a área retangular da nossa janela e tchan, tchan, tchan, tchan... vestimos nossa janela com a máscara desejada. A função responsável pela transferência dos blocos de bits referentes às cores dos pixels é a BitBlt (BIT-BLock Transfer) que exige um caminhão de parâmetros:
Como último parâmetro da função BitBlt usamos o código SRCCOPY (source copy - cópia da fonte), indicando que queremos uma simples cópia. Eliminamos mCMMem porque sempre é bom livrar um pouco de memória e... NOSSA JANELA ESTÁ PRONTA!!!
Compile o arquivo de recursos, compile e linke o código fonte. Divirta-se com o executável. É aí que aparecem alguns "senões": a janela não oferece nenhuma possibilidade visível de ser fechada e a janela não pode ser arrastada. Por enquanto, nos testes, é preciso usar Alt+F4 para fechá-la.
Permitindo o arraste da janela
O arraste da janela é efetuado mantendo o botão esquerdo do mouse pressionado enquanto se arrasta a janela. Pressionar um botão do mouse começa sempre com "abaixar", ou seja, BUTTON DOWN. Cada vez que o botão esquerdo do mouse é "abaixado", a janela recebe uma mensagem WM_LBUTTONDOWN (o L vem de LEFT, esquerdo). Vamos caçar esta mensagem e reenviá-la com os nossos parâmetros:
A mensagem WM_NCLBUTTONDOWN é enviada quando o usuário pressiona o botão esquerdo do mouse com o cursor FORA da área cliente da janela. Como estamos trabalhando com a área total da janela, o cursor está sempre fora da área cliente, portanto... vamos capturar a mensagem de "botão abaixado" e corrigí-la para "fora da área cliente". Para isto, precisamos conhecer melhor a mensagem WM_NCLBUTTONDOWN:
O hit-test (teste do ponto clicado) é um valor retornado pela DefWindowProc (o gerente de mensagens padrão do Windows) como resultado do processamento de uma mensagem WM_NCHITTEST. Esta mensagem é enviada para uma janela quando o cursor se movimenta ou quando um botão do mouse é pressionado ou solto. Nós não interceptamos esta mensagem, portanto ela entrou no processamento padrão do DefWindowProc. Dos diversos valores de retorno do processamento de uma mensagem WM_NCHITTEST, aquele que nos interessa é o HTCAPTION. Este valor indica que o clique ocorreu na barra de título da janela, ou seja, a única área da janela que permite o arrasto. Vamos "enganar" o sistema e informar que todo e qualquer clique ocorre na barra de título
A posição do cursor não é importante, pois não dependemos dela. Podemos simplesmente informar o valor 0 (coordenadas 0,0 da janela).
Fechando a janela com um duplo clique
Já que estamos interceptando mensagens do mouse, vamos associar um duplo-clique do botão esquerdo do mouse com o fechamento da janela. Mas, para que a janela aceite cliques duplos, é preciso dar-lhe esta característica ao definirmos sua classe:
Com a janela preparada, podemos interceptar a mensagem WM_LBUTTONDBLCLK (Left BUTTON DouBLe CLicK - duplo clique do botão esquerdo) e trocá-la pela mensagem WM_DESTROY, que não precisa de parâmetros específicos e fecha o aplicativo:
Serviço de faxina
Quando escrevemos um código fonte, sempre é aconselhável fazer uma revisão final para verificar se existem variáveis definidas e não inicializadas/usadas, se criamos algum objeto que não é eliminado automaticamente pelo sistema após o seu uso ou se iniciamos um processo que necessita de fechamento. É o caso do BeginPaint que precisa do EndPaint correspondente e do contexto de dispositivo que precisa ser liberado para o uso geral. Destes nós já cuidamos.
Um objeto Bitmap também precisa ser eliminado, portanto, ponha na sua lista de faxina: após um LoadBitmap SEMPRE precisa existir um DeleteObject para o(s) bitmap(s) carregado(s). Se não fizermos esta "limpeza" antes de encerrarmos o aplicativo, vai sobrar lixo e, geralmente, dos grandes.
Nós usamos a função LoadBitmap quando interceptamos a mensagem WM_CREATE e o manipulador do bitmap foi armazenado em mBitmap. Enquanto o aplicativo estiver rodando, precisamos deste bitmap para fazer a pintura da máscara da janela (interceptando WM_PAINT), portanto, não podemos eliminá-lo durante a execução. Só nos resta a alternativa de usar a DeleteObject na saída do programa, ou seja, quando interceptamos a mensagem WM_DESTROY:
É isso aí, moçada. A novela chegou ao fim. Compilem o executável e bom divertimento
Download
Tutorial para download
Este tutorial, juntamente com o código fonte, imagens e o executável está na seção de Downloads / Tutoriais / Assembly Numaboa, mas você também pode baixá-lo aqui.
Fontes
Este tutorial se baseia no exemplo "CUSTOM WINDOWS SHAPE" escrito por mob (também conhecido como drcmda), incluído no pacote MASM32 do hutch.
- << Anterior
- Próximo