oicìliS © - Assembly para Iniciantes
(ver 1.0 de 22.01.02)

USANDO RECURSOS

 

Somos felizes possuidores de uma classe janela, o que nos permite criar janelas com a nossa grife. A janela que produzimos no tutorial anterior estava peladinha da silva, faltavam muitos recursos que costumam acompanhar as janelas.

O presente tutorial tem justamente este propósito: discutir os RECURSOS. Como exemplo, vamos colocar um bitmap numa janela.

 

PROJETO BITMAP NA JANELA

 

Como sempre, nosso primeiro passo é planejar nosso programa:

  1. O que são recursos
  2. Como criar arquivos de recursos
  3. Criar o arquivo de recursos que contenha o gráfico
  4. Criar o código fonte do programa teste.
  5. O código fonte completo (download do tutorial completo)
  6. NumaBoa com Recursos
1. O que são recursos

 

Recursos são dados binários que um compilador de recursos ou o programador adiciona ao arquivo executável de um aplicativo. Recursos podem ser do tipo padrão ou do tipo definido. Os dados de um recurso padrão descrevem ícones, cursores, menus, caixas de diálogo, gráficos do tipo .bmp e .emf, fontes, tabelas de teclas de atalho, tabela de mensagens, tabela de strings ou versão. Um recurso definido pelo aplicativo, também chamado de recurso personalizado (custom resource), contém quaisquer dados requeridos por um aplicativo específico.

Os recursos são descritos em arquivos texto próprios, chamados arquivos de recurso, geralmente com a extensão .rc. Estes arquivos precisam ser compilados (no menu do MASM [Project / Compile Resource File]) e depois são combinados com o arquivo de código fonte durante o estágio de link. O produto final é um arquivo executável que contém instruções e recursos.

 

2. Como criar arquivos de recursos

 

Podemos usar qualquer editor de texto para escrever arquivos de recursos. O texto é composto por frases que descrevem a aparência e os atributos dos recursos desejados para um determinado programa. Os recursos possuem uma linguagem própria, a Resource Script Language. Conhecendo um mínimo desta linguagem é o suficiente para podermos trabalhar (o help do Resource Workshop da Borland é uma referência muito boa).

Existem editores de recursos que facilitam muito o trabalho por oferecerem uma plataforma de trabalho visual. Editores de recursos geralmente estão incluídos nos pacotes de compiladores como Visual C++, Borland C++, etc.

Você pode usar o excelente Resource Builder, da SiComponents, o ResourceStudio da Symantec (encontrei a versão 1.0 para download no site do hutch) ou o tradicionalíssimo Resource Workshop da Borland (a versão 4.5 de 1994 funciona muito bem!).

 

3. Criar o arquivo de recursos

 

Use o programa gráfico da sua preferência para criar um gráfico ou escolha um da sua preferência. Salve-o ou transfira-o para o diretório de trabalho deste tutorial. O arquivo de recursos deve ficar no mesmo diretório do arquivo de código fonte. O gráfico que preparei para este tutorial recebeu o nome de "bits.bmp" e é o que se vê abaixo:

 

Gráfico em formato bmp (bits.bmp)
Bits

 

A diretiva para indicar um recurso bitmap é a seguinte:

IDentificador BITMAP [tipo de carregamento] [opção de memória] NomeDoArquivo

  • Identificador é o ID do recurso, indicado por um número. O ID será usado quando quisermos usar este recurso no programa (Obrigatório).
  • BITMAP é uma palavra chave para indicar o tipo de recurso (Obrigatório).
  • Tipo de carregamento é opcional. Indica se queremos que o bitmap seja previamente carregado (PRELOAD) ou apenas seja carregado quando solicitado (LOADONCALL). O default é LOADONCALL.
  • Opção de memória indica como o recurso deve ser carregado na memória. Pode ser descartável para livrar espaço de memória (DISCARDABLE), ficar fixo num endereço de memória (FIXED), ser modificado após o carregamento (IMPURE), pode ser deslocado na memória (MOVEABLE), precisa permanecer na memória (NONDISCARDABLE), não é modificado após o carregamento (PURE). O default é MOVEABLE e DISCARDABLE.
  • NomeDoArquivo é o nome do bitmap

Podemos resumir nosso arquivo RSRC.RC numa linha que contenha apenas o ID, a palavra chave BITMAP e o nome do arquivo. O restante deixamos como default. Abra um editor de texto (pode ser o GUN do MASM que você encontra em [Tools / TheGUN Text Editor]) e digite a linha abaixo:

760 BITMAP "bits.bmp"

 

Você pode usar qualquer número para o ID, contanto que não seja o mesmo usado por outro recurso. Salve o arquivo com o nome de "RSRC.RC" no mesmo diretório onde estará o código fonte do nosso programa teste. Por enquanto é só.

 

4. Criar o programa teste

 

Vamos criar uma janela que conterá o bitmap do recurso, portanto podemos partir do modelo "Janelinha NumaBoa" que criamos no tutorial anterior.

 

4.a. O modelo

 

.386

.MODEL FLAT,STDCALL

option casemap:none

 

include \masm32\include\windows.inc

include \masm32\include\kernel32.inc

include \masm32\include\user32.inc

 

includelib \masm32\lib\kernel32.lib

includelib \masm32\lib\user32.lib

 

gerenteJanela proto :DWORD, :DWORD, :DWORD, :DWORD

 

.DATA?

mInstancia DWORD ?

linhaComando DWORD ?

 

.DATA

NomeClasse db "JanelaNua",0

TituloJanela db "Janelinha NumaBoa",0

 

.CODE

inicio:

invoke GetModuleHandle, NULL

mov mInstancia, eax

invoke GetCommandLine

mov linhaComando, eax

invoke gerenteJanela, mInstancia, NULL, linhaComando, SW_SHOWDEFAULT

invoke ExitProcess,0

 

gerenteJanela proc mInst:DWORD, mInstAnt:DWORD, linhaCmd:DWORD, Mostra:DWORD

LOCAL ej:WNDCLASSEX

LOCAL mJanela:HWND

LOCAL malote:MSG

 

mov ej.cbSize, SIZEOF WNDCLASSEX

mov ej.style, CS_HREDRAW or CS_VREDRAW

mov ej.lpfnWndProc, OFFSET gerenteMensagem

mov ej.cbClsExtra, NULL

mov ej.cbWndExtra, NULL

push mInst

pop ej.hInstance

invoke LoadIcon, NULL, IDI_WINLOGO

mov ej.hIcon, eax

mov ej.hIconSm, eax

invoke LoadCursor, NULL, IDC_ARROW

mov ej.hCursor, eax

mov ej.hbrBackground, COLOR_WINDOW+1

mov ej.lpszMenuName, NULL

mov ej.lpszClassName, OFFSET NomeClasse

invoke RegisterClassEx, ADDR ej

invoke CreateWindowEx, NULL, ADDR NomeClasse, ADDR TituloJanela,

WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, NULL, NULL, mInst, NULL

mov mJanela,eax

invoke ShowWindow, mJanela, SW_SHOWNORMAL

invoke UpdateWindow, mJanela

.WHILE TRUE

invoke GetMessage, ADDR malote, NULL, 0, 0

.BREAK .IF (eax < 1)

invoke TranslateMessage, ADDR malote

invoke DispatchMessage, ADDR malote

.ENDW

mov eax, malote.wParam

ret

gerenteJanela endp

 

gerenteMensagem proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

.IF uMsg == WM_CREATE

 

.ELSEIF uMsg == WM_SIZE

 

.ELSEIF uMsg == WM_PAINT

 

.ELSEIF uMsg == WM_COMMAND

 

.ELSEIF uMsg == WM_CLOSE

 

.ELSEIF uMsg==WM_DESTROY

invoke PostQuitMessage, NULL

xor eax,eax

ret

.ENDIF

invoke DefWindowProc, hWnd, uMsg, wParam, lParam

ret

gerenteMensagem endp

 

end inicio

 

Vamos mudar o título da janela para "NumaBoa com Recursos" só para identificá-la melhor:

.DATA

NomeClasse db "JanelaNua",0

TituloJanela db "NumaBoa com Recursos",0

 

4.a. A área do bitmap

 

Como queremos que o gráfico seja mostrado assim que a janela aparecer na tela, precisamos gerenciar a mensagem WM_CREATE que é enviada ao gerenteMensagem assim que a janela é criada. Primeiramente vamos criar uma área dentro da janela principal onde o bitmap deve ser mostrado. Essa área especial nada mais é que um controle, ou seja, uma janela especial. Já sabemos que, para criar uma janela/controle, precisamos de uma classe registrada que servirá como modelo. No Windows existem classes predefinidas para controles: BUTTON, COMBOBOX, EDIT, LISTBOX, SCROLLBAR e STATIC. Usaremos a STATIC porque não esperamos adicionar nenhuma funcionalidade ao nosso bitmap. A primeira provicência, então, é inicializar uma variável com o nome da classe na seção .DATA:

.DATA

NomeClasse db "JanelaNua",0

TituloJanela db "Janelinha NumaBoa",0

ClasseAreaBMP db "STATIC",0

 

Recapitulando a função CreateWindowEx temos:

HWND CreateWindowEx(

DWORD dwExStyle, // estilo especial de janela

LPCTSTR lpClassName, // ponteiro para a classe registrada

LPCTSTR lpWindowName, // pointeiro para o nome da janela: NULL

DWORD dwStyle, // estilo da janela

int x, // posição horizontal da janela

int y, // posição vertical da janela

int nWidth, // largura da janela

int nHeight, // altura da janela

HWND hWndParent, // manipulador da janela-mãe ou proprietário da janela

HMENU hMenu, // manipulador do menu ou identificador da janela-filha

HINSTANCE hInstance, // manipulador da instância do aplicativo

LPVOID lpParam // ponteiro para dados de criação da janela

);

  • dwExStyle: não usaremos um estilo especial - NULL.
  • lpClassName: o nome da classe está na variável ClasseAreaBMP - seu endereço será ADDR ClasseAreaBMP.
  • lpWindowName: a janela não precisa de título - usaremos NULL.
  • dwStyle: a composição do estilo será "Estilo Janela (WS) Filha" + "Estilo Janela (WS) Visível" + "Controle Estático (SS) com Bitmap" que é indicado com WS_CHILD or WS_VISIBLE or SS_BITMAP.
  • x e y: a posição horizontal e vertical do canto superior esquerdo da janela do controle dentro da janela-mãe - indicamos ambos como 20 pixels.
  • nWidth e nHeight: a largura e a altura da janela em pixels - indicamos temporariamente como 10. O porque do temporário será explicado logo adiante (4.4. Preparando a pintura).
  • hWndParent: o manipulador da janela-mãe - no nosso exemplo é o parâmetro hWnd do procedimento gerenteMensagem.
  • hMenu: não existe menu no controle, portanto NULL.
  • hInstance: o manipulador do módulo, mInstancia.
  • lpParam: não há dados na criação da janela - NULL

Tudo em riba para podermos incluir a chamada à função que criará o controle com a área que deve conter o bitmap:

gerenteMensagem proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

.IF uMsg == WM_CREATE

invoke CreateWindowEx, NULL, ADDR ClasseAreaBMP, NULL,

WS_CHILD or WS_VISIBLE or SS_BITMAP, 20, 20, 10, 10, hWnd, NULL,

mInstancia, NULL

...

.ELSEIF ...

 

A função CreateWindowEx retorna o valor do manipulador da janela em EAX. Precisaremos deste valor logo adiante, portanto, criaremos uma variável local e a inicializamos com o valor de retorno:

gerenteMensagem proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

LOCAL mAreaBMP: DWORD

 

.IF uMsg == WM_CREATE

invoke CreateWindowEx, NULL, ADDR AreaBitmap, NULL,

WS_CHILD or WS_VISIBLE or SS_BITMAP, 20, 20, 10, 10, hWnd, NULL,

mInstancia, NULL

mov mAreaBMP, eax

...

.ELSEIF ...

 

4.b. Localizando o bitmap

 

Nosso bitmap está nos recursos e tem o identificador 760. Agora precisamos obter um manipulador para o bitmap para que possamos acessá-lo. Usamos a função LoadBitmap:

HBITMAP LoadBitmap(

HINSTANCE hInstance, // manipulador da instância do aplicativo

LPCTSTR lpBitmapName // endereço do nome do recurso bitmap

);

 

Da mesma forma que acima, precisamos de uma variável local que receba o manipulador:

gerenteMensagem proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

LOCAL mAreaBMP: DWORD

LOCAL mBMP: DWORD

 

.IF uMsg == WM_CREATE

invoke CreateWindowEx, NULL, ADDR AreaBitmap, NULL,

WS_CHILD or WS_VISIBLE or SS_BITMAP, 20, 20, 10, 10, hWnd, NULL,

mInstancia, NULL

mov mAreaBMP, eax

 

invoke LoadBitmap, mInstancia, 760

mov mBMP, eax

...

.ELSEIF ...

 

4.c. Pintando o bitmap

 

O sistema possui um "pintor" de plantão que pode ser acionado sempre que necessário. Basta enviar uma mensagem com os dados necessários para que ele possa trabalhar. A função SendMessage envia a mensagem especificada para uma ou mais janelas. Esta função chama o gerente de mensagens do(s) destinatário(s) e não retorna enquanto o pedido não for integralmente realizado.

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

);

  • hWnd: nossa janela destino é a janela do controle com a área que foi preparada para receber o bitmap - mAreaBMP
  • Msg: a mensagem é dirigida a um controle estático (STatic control Message), ou seja, do tipo STM_ alguma coisa. As mensagens que existem são STM_GETICON, STM_SETICON, STM_GETIMAGE e STM_SETIMAGE. Obviamente é da STM_SETIMAGE que estamos precisando.
  • wParam: o primeiro parâmetro de uma mensagem do tipo STM_SETIMAGE refere-se ao tipo de imagem e pode ser IMAGE_BITMAP, IMAGE_CURSOR, IMAGE_ENHMETAFILE e IMAGE_ICON. O tipo da nossa imagem é IMAGE_BITMAP.
  • lParam: o segundo parâmetro da mensagem STM_SETIMAGE refere-se ao manipulador da imagem. No nosso caso, mBMP.

Vamos enviar nossa mensagem com:

gerenteMensagem proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

LOCAL mAreaBMP: DWORD

LOCAL mBMP: DWORD

 

.IF uMsg == WM_CREATE

invoke CreateWindowEx, NULL, ADDR AreaBitmap, NULL,

WS_CHILD or WS_VISIBLE or SS_BITMAP, 20, 20, 10, 10, hWnd, NULL,

mInstancia, NULL

mov mAreaBMP, eax

 

invoke LoadBitmap, mInstancia, 760

mov mBMP, eax

 

invoke SendMessage, mAreaBMP, STM_SETIMAGE, IMAGE_BITMAP, mBMP

.ELSEIF ...

 

Você ainda se lembra de que dimensionamos nosso controle para ter 10 x 10 pixels? Nosso gráfico tem 255 x 185 pixels. Vai faltar pixel para abrigar o gráfico inteiro - problema do "pintor" de plantão. Como enviamos as coordenadas da posição do controle estático, o "pintor" vai transferindo a sequência de pixels que ele encontrar nos recursos e "estica" o controle para fazer espaço para o gráfico. Tão simples assim... mas precisamos saber disso para que o gráfico não avance sobre outros controles desformatando nosso layout.

 

5. O código fonte completo

 

Para o código fonte completo, além do arquivo de recursos e o bitmap do exemplo, faça o download do Tutorial Recursos (tutNB04.zip 75 Kb).

 

6. NumaBoa com Recursos
A obra de arte ;-)
Janela NumaBoa

ATÉLOGO

 

O resumo do atélogo:

  1. O que são recursos: arquivos de recursos com dados de menus, ícones, gráficos, etc
  2. Como criar arquivos de recursos: sintaxe e programas de edição
  3. Criar o arquivo de recursos: programando um script de recursos
  4. O programa teste: criando a janela que irá conter um bitmap do recurso
  5. Controles: janelas especiais com classes predefinidas
  6. Localizando o bitmap: como obter um manipulador para o bitmap
  7. "Pintando" o bitmap: enviando uma mensagem para convocar o "pintor" de plantão
  8. O código fonte completo: faça o download do tutorial e estude offline

| AAAA | Página Inicial | Mapa do Site | Novidades | Busca | Indique esta página | Mestre da Teia | Voltar |
| Localizador || @ Info NumaBoa > oicìliS > Assembly > Usando Recursos
Créditos: vovó Vicki

webdesign sobMedida by vickiSoft - /informatica/oiciliS/assembler/tutRecursos/recursos.php (22.01.02) versão 1.0 de 28.01.02
Licença Creative Commons 1998-2006 Aldeia NumaBoa
Exceto onde especificamente declarado, todo material deste site é disponibilizado de acordo com a Licença Creative Commons.