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) 


Inserindo o bitmap no contexto modelo de memória

Agora é necessário inserir o objeto bitmap que contém o gráfico da nossa janela no contexto de dispositivo de memória para que possamos utilizá-lo como modelo de pintura. A função SelectObject faz o trabalho:

HGDIOBJ SelectObject( HDC hdc, // manipulador do contexto modelo HGDIOBJ hgdiobj // manipulador do objeto ); gerenteMensagem proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM LOCAL mCMMem:HDC .IF uMsg == WM_CREATE invoke LoadBitmap, mInstancia, BitmapID

mov mBitmap, eax invoke CreateCompatibleDC, NULL mov mCMMem, eax invoke SelectObject, mCMMem, mBitmap invoke ReleaseDC, hWnd, mCM

... gerenteMensagem endp ...

Obtendo as coordenadas da área da janela

As coordenadas de tela do canto superior esquerdo e inferior direito da janela servem de referência para definir a área retangular total da janela. Chamando a função GetWindowRect obtemos os quatro valores que serão armazenados numa estrutura do tipo RECT.

BOOL GetWindowRect( HWND hWnd, // manipulador da janela LPRECT lpRect // endereço da estrutura para as coordenadas da janela );

De posse destas coordenadas, vamos chamar a função grafiti. Esta é uma função própria (não é da API do Windows), cheia de emoções wink

gerenteMensagem proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM LOCAL mCMMem:HDC LOCAL retang:RECT .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 ... gerenteMensagem endp ...

Criando a Região Gráfica

Agora vamos entrar no "filé" do projeto. Todas as condições necessárias para podermos pintar nossa janela estão preparadas. Agora pegue a lata de tinta e dá-lhe pintura! Para efetuar este serviço, vamos criar uma função própria, a grafiti.

Declarando uma função própria

A função grafiti precisa de três parâmetros para trabalhar, todos do tipo DWORD: o manipulador do contexto de dispositivo de memória, a altura e a largura da janela. Vamos escrever seu protótipo, seu cabeçalho e seu final:

.386 .. gerenteJanela proto :DWORD, :DWORD, :DWORD, :DWORD grafiti proto :DWORD, :DWORD, :DWORD

... grafiti proc USES ESI EDI EBX _mModelo:HDC, _largura:DWORD, _altura:DWORD grafiti endp
A palavra-chave USES

Esta declaração do procedimento contém uma novidade: foi incluída a palavra-chave USES.

Quando você programa para Win32, é preciso conhecer algumas regras importantes. Uma dessas regras é que o Windows usa ESI, EDI, EBP e EBX internamente e não espera que os valores destes registradores sejam alterados. Portanto, lembre-se da primeira regra: se você usar qualquer um destes quatro registradores numa função callback, não esqueça de restaurar seus valores originais antes de devolver o controle ao Windows. Uma função callback é uma função sua que é chamada pelo Windows. Isto não significa que você não possa utilizar estes quatro registradores. Apenas certifique-se de que seus valores sejam restaurados antes de devolver o controle ao Windows.

O MASM possui uma palavra-chave opcional que pode ser usada com PROC. Esta palavra-chave faz com que o assembler gere código para "pushar" para a pilha o valor dos registradores que devem ser preservados (e que serão alterados no procedimento) e para reavê-los da pilha com pop quando o procedimento retorna. USES aceita uma lista de registradores separados por um espaço.

Identificando a cor transparente

Partimos do princípio de que o primeiro pixel (o das coordenadas 0,0) tenha a cor que queremos transparente. O que precisamos é identificar todos os pixels que tenham uma cor diferente da cor que deve ficar transparente e fazer uma cópia dos mesmos. Ficando no exemplo acima, seria como se usássemos nosso bitmap original e fizéssemos apenas a cópia dos pixels diferentes de preto:

Pixels Originais Cópia dos Pixels
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 

Para obter a cópia desejada, vamos analisar todos os pixels do bitmap percorrendo todas as linhas, coluna a coluna. O registrador EDI mostrará o número da coluna e o ESI o número da linha. Para usá-los no nosso procedimento, a primeira providência será zerá-los com XOR. O valor da cor transparente, em RGB (red, green, blue), ficará na variável local corT.

A função GetPixel, da gdi.lib, obtém o valor RGB (red, green, blue) do pixel especificado pelas coordenadas.

COLORREF GetPixel( HDC hdc, // manipulador do contexto modelo int XPos, // coordenada x do pixel int nYPos // coordenada y do pixel ); .386 ... include \masm32\include\user32.inc include \masm32\include\gdi32.inc ... includelib \masm32\lib\user32.lib includelib \masm32\lib\gdi32.lib ... grafiti proc USES ESI EDI EBX _mModelo:HDC, _largura:DWORD, _altura:DWORD LOCAL corT:DWORD xor edi, edi xor esi, esi invoke GetPixel, _mModelo, 0, 0 mov corT, eax grafiti endp
Verificando cada pixel

Com a ajuda de rótulos, vamos fazer primeiro um loop para percorrer todos os pixels do bitmap e comparar a cor do pixel atual com a cor transparente.

grafiti proc USES ESI EDI EBX _mModelo:HDC, _largura:DWORD, _altura:DWORD LOCAL corT: DWORD xor edi, edi ; zera o registrador edi xor esi, esi ; zera o registrador esi invoke GetPixel, _mModelo, 0, 0 ; obtém a cor do primeiro pixel mov corT, eax ; inicializa corT com a cor da transparência _olhaPix: invoke GetPixel, _mModelo, edi, esi ; obtém a cor do pixel atual cmp eax, corT ; compara a cor atual com a transparente _proxPix: inc edi ; incrementa a coluna cmp edi, _largura ; compara a coluna com a largura do bitmap jbe _olhaPix ; se for menor ou igual, olha o próximo pixel ; se for maior... xor edi, edi ; zera o contador de colunas (coluna 0) inc esi ; passa para a próxima linha cmp esi, _altura ; compara a linha com a altura do bitmap jb _olhaPix ; se for menor, olha o próximo pixel _retorna: ; termina o processo grafiti endp

Informações adicionais