Iczelion’s tutorial N°25
Bitmaps

Data

by "Death_Reaver"

 

03/06/2005

UIC's Home Page

Published by Quequero

Tutti gli uomini sono uguali davanti a Dio…

Danke!

Ma appena si gira, sono cazzi tuoi!

....

Home page (se presente):NADA

E-mail: [email protected]

Nick, UIN, canale IRC/EFnet frequentato

....

Difficoltà

( )NewBies (*)Intermedio ( )Avanzato ( )Master

 

 

Introduzione

Continua la traduzione dei tutorial di Iczelion

 

Tools usati

ALLEGATO (codice sorgente + eseguibile già compilato)

MASM32 v. 8 sp1 (nella sezione tools)

RadAsm (IDE perfetto per programmare in asm)

 

Notizie sul programma

In questo tutorial, impareremo ad usare bitmap nel nostro programma. Ad essere precisi, impareremo a mostrare una bitmap nella client-area della nostra finestra.

 

Essay

Teoria

Le bitmap possono essere considerate come foto nel computer. Ci sono molti tipi di foto usati dal computer ma Windows supporta di standard solo le Windows Bitmap Graphic Files (.bmp).Le bitmap trattate in questo tutorial saranno proprio windows bitmap graphic files. La via più facile per usare una bitmap è di usarla come risorsa. Ci sono due metodi per farlo.

1)La si può inserire nel resource script(.rc) così:

 

#define IDB_MYBITMAP 100

IDB_MYBITMAP BITMAP "c:\immagini\esempio.bmp"

 

Questo metodo utilizza una costante per definire una bitmap. La prima riga crea una costante chiamata IDB_MYBITMAP che ha il valore 100. Useremo questo nome per "passare" la bitmap al programma. La riga successiva dichiara una risorsa di tipo BITMAP. Dice al resource-compiler dove trovare il file bmp.

 

2)L'altro metodo usa un nome per rappresentare la bitmap

 

MyBitMap BITMAP "c:\immagini\esempio.bmp"

 

Con questo metodo passi la bitmap al programma tramite la stringa "MyBitMap" invece di un valore.

Entrambi i metodi vanno bene finché sai che metodo stai usando.

Adesso che abbiamo messo la bitmap nel file di risorse possiamo andare avanti mostrandola nella client area della nostra finestra.

 

1)    Chiamiamo LoadBitmap per prendere l'handle della bitmap. LoadBitmap ha il seguente prototipo:

 

LoadBitmap proto hInstance:HINSTANCE,lpBitmapName:LPSTR

 

Questa funzione restituisce l'handle della bitmap. hInstance è l'instance-handel del tuo programma. lpBitmapName è un puntatore alla stringa che contiene il nome della bitmap(nel caso del secondo metodo). Se stai usando una costante per definire la bitmap, puoi metterne il valore qui. (nell'esempio sotto sarà 100).

Un piccolo esempio in ordine:

 

Primo metodo:

 

.386

.model flat, stdcall

................

.const

IDB_MYBITMAP    equ 100

...............

.data?

hInstance  dd ?

..............

.code

.............

    invoke GetModuleHandle,NULL

    mov hInstance,eax

............

    invoke LoadBitmap,hInstance,IDB_MYBITMAP

...........

 

Secondo Metodo:

 

.386

.model flat, stdcall

................

.data

BitmapName  db "MyBitMap",0

...............

.data?

hInstance  dd ?

..............

.code

.............

    invoke GetModuleHandle,NULL

    mov hInstance,eax

............

    invoke LoadBitmap,hInstance,addr BitmapName

...........

 

2) Ottenere l'handle del Device Context (DC). Lo si può ottenere chiamando BeginPaint in risposta a WM_PAINT o chiamando GetDC dovunque.

 

3) Creare un device context in memoria che abbia gli stessi attributi del device context appena ottenuto. L'idea è di creare una specie di superficie invisibile dove possiamo disegnare la nostra bitmap. Quando abbiamo finito questa operazione, basta copiare il contenuto della superficie invisibile nell'attuale device context con una funzione. Questo è un esempio della tecnica a "doppio buffer" usata per mostrare velocemente le immagini sullo schermo. Si puo creare questa superfice invisibile chiamando CreateCompatibleDC.

CreateConpatibleDC proto hdc:HDC

 

Se la chiamata riesce, restituisce in eax l'handle del memory device context. hdc è l'handle del device context del quale vuoi che sia compatibile.

 

4) Adesso che abbiamo la nostra superficie invisibile, possiamo disegnare inserendo la bitmap dentro al mDC(memory device context). Questo si può fare chiamando

SelectObject con l'handle del mDC come primo parametro e l'handle della bitmap come secondo. SelectObject ha il seguente prototipo:

 

SelectObject proto hdc:HDC, hGdiObject:DWORD

 

5) Ora la bitmap è disegnate nel mDC. Quello che rimane da fare è copiarlo nell'attuale device context, ossia il vero device context. Ci sono tante funzioni che ci permettono di farlo come BitBlt e StretchBlt. BitBlt copia semplicemente il contenuto di un DC a un altro e per questo è veloce, mentre, StretchBlt può estendere o comprimere la bitmap per riempire l'area di output. Qui useremo BitBlt:

 

BitBlt proto hdcDest:DWORD, nxDest:DWORD, nyDest:DWORD, nWidth:DWORD, nHeight:DWORD, hdcSrc:DWORD, nxSrc:DWORD, nySrc:DWORD, dwROP:DWORD

 

hdcDest è l'handle del DC di destinazione

nxDest,nyDest sono le coordinate dell'angolo superiore sinistro della zna di destinazione

nWidth,nHeight sono la larghezza e l'altezza della zona di destinazione

hdcSource è l'handle del DC da copiare

nxSrc,nySrc sono le coordinate del''angolo superiore sinistro da cui iniziare a copiare

dwROP è il codice di "rasterizzazione" (acronimo ROP) che decide come combinare i dati della bitmap con il colore già esistente nella zona di destinazione per

 

ottenere il risultato finale. La maggior parte delle volte si vuole sovrascrivere il colore esistente con uno nuovo.

6) Quando hai finito con la bitmap, cancellala con una chaimata a DeleteObject.

 

Finito! Per ricapitolare: hai bisogno di mettere la bitmap nel resource script. Quindi la carichi con LoadBitmap. Otterrai l'handle della bitmap. Dopo prendi l'handle del DC dell'area dove vuoi disegnare. Quindi crei un device context in memoria compatibile con il device context precedentemente ottenuto. Metti la bitmap nel mDC ottenuto e copi il contenuto del mDC nel DC reale.

Esempio:

 

.386

.model flat,stdcall

option casemap:none

include \masm32\include\windows.inc

include \masm32\include\user32.inc

include \masm32\include\kernel32.inc

include \masm32\include\gdi32.inc

includelib \masm32\lib\user32.lib

includelib \masm32\lib\kernel32.lib

includelib \masm32\lib\gdi32.lib

 

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

IDB_MAIN   equ 1

 

.data

ClassName db "SimpleWin32ASMBitmapClass",0

AppName  db "Win32ASM Simple Bitmap Example",0

 

.data?

hInstance HINSTANCE ?

CommandLine LPSTR ?

hBitmap dd ?

 

.code

start:

 invoke GetModuleHandle, NULL

 mov    hInstance,eax

 invoke GetCommandLine

 mov    CommandLine,eax

 invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT

 invoke ExitProcess,eax

 

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD

 LOCAL wc:WNDCLASSEX

 LOCAL msg:MSG

 LOCAL hwnd:HWND

 mov   wc.cbSize,SIZEOF WNDCLASSEX

 mov   wc.style, CS_HREDRAW or CS_VREDRAW

 mov   wc.lpfnWndProc, OFFSET WndProc

 mov   wc.cbClsExtra,NULL

 mov   wc.cbWndExtra,NULL

 push  hInstance

 pop   wc.hInstance

 mov   wc.hbrBackground,COLOR_WINDOW+1

 mov   wc.lpszMenuName,NULL

 mov   wc.lpszClassName,OFFSET ClassName

 invoke LoadIcon,NULL,IDI_APPLICATION

 mov   wc.hIcon,eax

 mov   wc.hIconSm,eax

 invoke LoadCursor,NULL,IDC_ARROW

 mov   wc.hCursor,eax

 invoke RegisterClassEx, addr wc

 INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\

           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\

           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\

           hInst,NULL

 mov   hwnd,eax

 invoke ShowWindow, hwnd,SW_SHOWNORMAL

 invoke UpdateWindow, hwnd

 .while TRUE

  invoke GetMessage, ADDR msg,NULL,0,0

  .break .if (!eax)

  invoke TranslateMessage, ADDR msg

  invoke DispatchMessage, ADDR msg

 .endw

 mov     eax,msg.wParam

 ret

WinMain endp

 

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

   LOCAL ps:PAINTSTRUCT

   LOCAL hdc:HDC

   LOCAL hMemDC:HDC

   LOCAL rect:RECT

   .if uMsg==WM_CREATE

      invoke LoadBitmap,hInstance,IDB_MAIN

      mov hBitmap,eax

   .elseif uMsg==WM_PAINT

      invoke BeginPaint,hWnd,addr ps

      mov    hdc,eax

      invoke CreateCompatibleDC,hdc

      mov    hMemDC,eax

      invoke SelectObject,hMemDC,hBitmap

      invoke GetClientRect,hWnd,addr rect

      invoke BitBlt,hdc,0,0,rect.right,rect.bottom,hMemDC,0,0,SRCCOPY

      invoke DeleteDC,hMemDC

      invoke EndPaint,hWnd,addr ps

 .elseif uMsg==WM_DESTROY

  invoke DeleteObject,hBitmap

  invoke PostQuitMessage,NULL

 .ELSE

  invoke DefWindowProc,hWnd,uMsg,wParam,lParam

  ret

 .ENDIF

 xor eax,eax

 ret

WndProc endp

end start

 

;---------------------------------------------------------------------

;                            Il resource script

;---------------------------------------------------------------------

#define IDB_MAIN 1

IDB_MAIN BITMAP "tweety78.bmp"

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

                                                           

 

 

 

 

 

 

 

 

 

 

Analisi:

Non c'è molto da analizzare in questo tutorial ;)

#define IDB_MAIN 1

IDB_MAIN BITMAP "tweety78.bmp"

 

 

 

Definiamo una costante chiamata IDB_MAIN con valore 1.Usiamo questo valore come ID della bitmap. Il file incluso nelle risorse è "tweety78.bmp" che stà nella stessa cartella del resource script.

 

.if uMsg==WM_CREATE

      invoke LoadBitmap,hInstance,IDB_MAIN

      mov hBitmap,eax

 

 

 

 

In risposta a WM_CREATE chiamiamo LoadBitmap per caricare la bitmap dalle risorse, passandogli l'ID della bitmap come secondo parametro. Otterremo l'handle della bitmap. Adesso che la bitmap è caricata, possiamo disegnarla nella client-area della nostra finestra.

 

.elseif uMsg==WM_PAINT

      invoke BeginPaint,hWnd,addr ps

      mov    hdc,eax

      invoke CreateCompatibleDC,hdc

      mov    hMemDC,eax

      invoke SelectObject,hMemDC,hBitmap

      invoke GetClientRect,hWnd,addr rect

      invoke BitBlt,hdc,0,0,rect.right,rect.bottom,hMemDC,0,0,SRCCOPY

      invoke DeleteDC,hMemDC

      invoke EndPaint,hWnd,addr ps

 

 

 

 

 

 

 

 

 

 

 

Abbiamo scelto di disegnare la bitmap in risposta a WM_PAINT. Prima chiamiamo BeginPaint per ottenere l'handle del DC. Quindi creiamo un DC compatibile in memoria con CreateCompatibleDC. Dopo mettiamo la bitmap nel DC in memoria con SelectObject. Determiniamo le dimensioni della client area con GetClientRect.

Possiamo ora mostrare la bitmap nella client-area chiamando BitBlt che copia la bitmap dal mDC al DC reale. Quando abbiamo finito di disegnare, non abbiamo più bisogno del mDC e quindi lo cancelliamo con DeleteDC. Terminiamo la sezione di disegno con EndPaint.

 

.elseif uMsg==WM_DESTROY

  invoke DeleteObject,hBitmap

  invoke PostQuitMessage,NULL

 

 

 

 

Quando non avremo più bisogno della bitmap, la cancelliamo con DeleteObject.

 

                                                      DEATH_REAVER

Note finali

Saluto tutti i compagni di cracking e coding

Disclaimer

Vorrei ricordare che il software va comprato e  non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento è stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete (‘cazzo centra? Sto a programma!), infatti tale documento aiuta a comprendere lo sforzo che ogni sviluppatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.

Reversiamo al solo scopo informativo e per migliorare la nostra conoscenza del linguaggio Assembly