Iczelion’s tutorial N°25 |
||
Data |
by "Death_Reaver" |
|
03/06/2005 |
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.