Tutorial 24: Windows Hooks | Tutorial 25: Simple Bitmap | Tutorial 26: Splash Screen |
In this tutorial, we will learn how to use bitmap in our program. To be exact, we will learn how to display a bitmap in the client area of our window.
Download the example.
Bitmaps can be thought of as pictures stored in computer. There are many picture formats used with computers but Windows only natively supports Windows Bitmap Graphics files (.bmp). The bitmaps I'll refer to in this tutorial are Windows bitmap graphics files. The easiest way to use a bitmap is to use it as a resource. There are two ways to do that. You can include the bitmap in the resource definition file (.rc) as follows:
#define IDB_MYBITMAP 100
IDB_MYBITMAP bitmap "c:\project\example.bmp"
This method uses a constant to represent the bitmap. The first line just creates a constant named IDB_MYBITMAP which has the value of 100. We will use this label to refer to the bitmap in the program. The next line declares a bitmap resource. It tells the resource compiler where to find the actual bmp file.
MyBitMap bitmap "c:\project\example.bmp"
This method requires that you refer to the bitmap in your program by the string "MyBitMap" instead of a value.
Either method works fine as long as you know which method you're using.
Now that we put the bitmap in the resource file, we can go on with the steps in displaying it in the client area of our window.
LoadBitmap PROTO hInstance:HINSTANCE, lpBitmapName:LPSTR
First Method:
.386
.model flat, stdcall
................
.const
IDB_MYBITMAP equ 100
...............
.data?
hInstance dd ?
..............
.code
.............
invoke GetModuleHandle,NULL
mov hInstance,eax
............
invoke LoadBitmap,hInstance,IDB_MYBITMAP
...........
Second Method:
.386
.model flat, stdcall
................
.data
BitmapName db "MyBitMap",0
...............
.data?
hInstance dd ?
..............
.code
.............
invoke GetModuleHandle,NULL
mov hInstance,eax
............
invoke LoadBitmap,hInstance,ADDR BitmapName
...........
CreateCompatibleDC PROTO hdc:HDC
If this function succeeds, it returns the handle of the memory device context in eax. hdc is the handle to the device context that you want the memory DC to be compatible with.
SelectObject PROTO hdc:HDC, hGdiObject:DWORD
BitBlt PROTO hdcDest:DWORD, nxDest:DWORD, nyDest:DWORD, \
nWidth:DWORD, nHeight:DWORD, \
hdcSrc:DWORD, nxSrc:DWORD, \
nySrc:DWORD, dwROP:DWORD
When you're done with the bitmap, delete it with DeleteObject API call.
That's it! To recapitulate, you need to put the bitmap into the resource scipt. Then load it from the resource with LoadBitmap. You'll get the bitmap handle. Next you obtain the handle to the device context of the area you want to paint the bitmap on. Then you create a memory device context that is compatible with the device context you just obtained. Select the bitmap into the memory DC then copy the content of the memory DC to the real DC.
.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
;-----------------------------------------------------------------------
; The resource script
;-----------------------------------------------------------------------
#define IDB_MAIN 1
IDB_MAIN BITMAP "tweety78.bmp"
There is not much to analyze in this tutorial ;)
#define IDB_MAIN 1
IDB_MAIN BITMAP "tweety78.bmp"
Define a constant named IDB_MAIN, assign 1 as its value. And then use that constant as the bitmap resource identifier. The bitmap file to be included in the resource is "tweety78.bmp" which resides in the same folder as the resource script.
.IF uMsg==WM_CREATE
invoke LoadBitmap,hInstance,IDB_MAIN
mov hBitmap,eax
In response to WM_CREATE, we call LoadBitmap to load the bitmap from the resource, passing the bitmap's resource identifier as the second parameter to the API. We get the handle to the bitmap when the function returns.
Now that the bitmap is loaded, we can paint it in the client area of our main window.
.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
We choose to paint the bitmap in response to WM_PAINT message. We first call BeginPaint to obtain the handle to the device context. Then we create a compatible memory DC with CreateCompatibleDC. Next select the bitmap into the memory DC with SelectObject. Determine the dimension of the client area with GetClientRect. Now we can display the bitmap in the client area by calling BitBlt which copies the bitmap from the memory DC to the real DC. When the painting is done, we have no further need for the memory DC so we delete it with DeleteDC. End painting session with EndPaint.
.ELSEIF uMsg==WM_DESTROY
invoke DeleteObject,hBitmap
invoke PostQuitMessage,NULL
When we don't need the bitmap anymore, we delete it with
DeleteObject
Tutorial 24: Windows Hooks | Overview | Tutorial 26: Splash Screen |