A Aldeia Numaboa ancestral ainda está disponível para visitação. É a versão mais antiga da Aldeia que eu não quis simplesmente descartar depois de mais de 10 milhões de pageviews. Como diz a Sirley, nossa cozinheira e filósofa de plantão: "Misericórdia, ai que dó!"

Se você tiver curiosidade, o endereço é numaboa.net.br.

Leia mais...

Informática Numaboa - Tutoriais e Programação

Janela Numaboíssima (masm)

Qui

16

Abr

2009


00:00

(2 votos, média 5.00 de 5) 


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.

gerenteMensagem proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM LOCAL mCM:HDC LOCAL mCMMem:HDC LOCAL retang:RECT LOCAL ps:PAINTSTRUCT .IF uMsg == WM_CREATE invoke LoadBitmap, mInstancia, BitmapID mov mBitmap, eax invoke CreateCompatibleDC, NULL mov mCMMem, eax invoke SelectObject, mCMMem, mBitmap invoke GetWindowRect, hWnd, ADDR retang invoke grafiti, mCMMem, retang.right, retang.bottom invoke SetWindowRgn, hWnd, eax, TRUE invoke DeleteDC, mCMMem .ELSEIF uMsg == WM_PAINT invoke BeginPaint, hWnd, ADDR ps invoke GetWindowRect, hWnd, ADDR retang mov mCM, eax invoke CreateCompatibleDC, NULL mov mCMMem, eax invoke SelectObject, mCMMem, hBitmap invoke EndPaint, hWnd, ADDR ps ...

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:

BOOL BitBlt( HDC hdcDest, // manipulador do contexto modelo destino int nXDest, // coordenada x do canto superior esquerdo do retângulo destino int nYDest, // coordenada y do canto superior esquerdo do retângulo destino int nWidth, // largura do retângulo destino int nHeight, // altura do retângulo destino HDC hdcSrc, // manipulador do contexto modelo fonte int nXSrc, // coordenada x do canto superior esquerdo do retângulo fonte int nYSrc, // coordenada y do canto superior esquerdo do retângulo fonte DWORD dwRop // código da operação para combinação de cores ); .ELSEIF uMsg == WM_PAINT invoke BeginPaint, hWnd, ADDR retang invoke GetWindowRect, hWnd, ADDR ps mov mCM, eax invoke CreateCompatibleDC, NULL mov mCMMem, eax invoke SelectObject, mCMMem, hBitmap invoke BitBlt, mCM, 0, 0, retang.right, retang.bottom, mCMMem, 0, 0, SRCCOPY invoke DeleteDC, mCMMem invoke EndPaint, hWnd, ADDR ps ...

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:

LRESULT SendMessage( HWND hWnd, // manipulador da janela destino UINT Msg, // mensagem a ser enviada WPARAM wParam, primeiro parâmetro da mensagem LPARAM lParam // segundo parâmetro da mensagem );

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:

WM_NCLBUTTONDOWN nHittest = (INT) wParam; // valor do hit-test pts = MAKEPOINTS(lParam); // posição do cursor );

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 wink

A posição do cursor não é importante, pois não dependemos dela. Podemos simplesmente informar o valor 0 (coordenadas 0,0 da janela).

.ELSEIF uMsg == WM_LBUTTONDOWN invoke SendMessage, hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0 ...

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:

gerenteJanela proc mInst:DWORD, mInstAnt:DWORD, linhaCmd:DWORD, Mostra:DWORD ... mov ej.style, CS_HREDRAW or CS_VREDRAW or CS_DBLCLKS ... invoke CreateWindowEx, NULL, ADDR NomeClasse, ADDR TituloJanela, WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, largBitmap, altBitmap, NULL, NULL, mInst, NULL ... gerenteJanela endp

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:

.ELSEIF uMsg == WM_LBUTTONDBLCLK invoke SendMessage, hWnd, WM_DESTROY, NULL, NULL ...

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:

.ELSEIF uMsg == WM_DESTROY invoke DeleteObject, mBitmap invoke PostQuitMessage, NULL ...

É isso aí, moçada. A novela chegou ao fim. Compilem o executável e bom divertimento biggrin

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.

Вадим Логофет Sberbankкерамическое покрытиеооо полигон одессаалександр лобановскийкп газетакупить электрическийооо отзывы

Informações adicionais