位图就是存贮于电脑中的图片。位图文件有相当多的格式(译者:如.BMP.JPG.GIF.PIC 等)但Windows仅 支持 Windows Bitmap Graphics 格式,即BMP文件。 本课所指的位图也是BMP文件。 使用位图最简单的方法就是把它定义在资源文件(.rc)中。 定义的方法有两种。第一种方法是把它定义为整数宏,具体如下:
#define IDB_MYBITMAP 100 IDB_MYBITMAP BITMAP "c:\project\example.bmp"
第一行我们定义了一个值为100的整数宏。 第二行我们把这个整数宏指向所要定义的位图,
这样,编译器就能知道位图所在的路径。
另一种方法是给它起一个名字,也就是把它定义为字符串,具体如下:
MyBitMap BITMAP "c:\project\example.bmp"
两种方法效果是一样的。
选择哪一种方法,视乎在程序中你喜欢用整数宏还是用字符串来指向位图。
现在我们已经把位图定义在资源文件中,下一步就是把它显示在窗口的客户区上。
在程序中,我们使用API函数 LoadBitmap 取得位图句柄。 下面是 LoadBitmap 函数的 完型:
LoadBitmap proto hInstance:HINSTANCE, lpBitmapName:LPSTR
该函数返回一个位图句柄。函数有两个参数,其中 hInstance 是程序句柄。 lpBitmapName 是位图名字的指针(适用于第二种定义方法)。如果你使用了第一种 定义方法,你可以填入指向位图的值或整数宏 (对应上例这个值就是100,整数宏是IDB_MYBITMAP)。下面是简单的例子:
第一种方法:
.386
.MODEL FLAT, STDCALL
................
.CONST
IDB_MYBITMAP EQU 100
...............
.DATA?
HINSTANCE DD ?
..............
.CODE
.............
INVOKE GETMODULEHANDLE,NULL
MOV HINSTANCE,EAX
............
INVOKE LOADBITMAP,HINSTANCE,IDB_MYBITMAP
...........
第二种方法:
.386
.MODEL FLAT, STDCALL
................
.DATA
BITMAPNAME DB "MYBITMAP",0
...............
.DATA?
HINSTANCE DD ?
..............
.CODE
.............
INVOKE GETMODULEHANDLE,NULL
MOV HINSTANCE,EAX
............
INVOKE LOADBITMAP,HINSTANCE,ADDR BITMAPNAME
...........
reateCompatibleDC proto hdc:HDC
如果函数执行成功,将返回DC内存映像也即“画纸”的句柄。
electObject proto hdc:HDC, hGdiObject:DWORD
itBlt proto hdcDest:DWORD, nxDest:DWORD, nyDest:DWORD, nWidth:DWORD, nHeight:DWORD, hdcSrc:DWORD, nxSrc:DWORD, nySrc:DWORD, dwROP:DWORD
hdcDest 目的DC的句柄。
nxDest, nyDest 目的DC输出区域的左上角坐标。
nWidth, nHeight 目的DC输出区域的长和宽。
hdcSrc 源DC的句柄。
nxSrc, nySrc 源DC中所要复制区域的左上角坐标。
dwROP 屏面运算码(ROP)。该参数用以确定复制内容的颜色与输出区域原来的颜色按哪种运算
方式处理。通常,只需要简单地用复制内容把输出区域覆盖掉。
.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
;---------------------------------------------------------------------
; 资源定义
;---------------------------------------------------------------------
#define IDB_MAIN 1
IDB_MAIN BITMAP "tweety78.bmp"
#define IDB_MAIN 1 IDB_MAIN BITMAP "tweety78.bmp"
定义整数宏IDB_MAIN的值为1,然后把它指向一个与资源文件处于相同目录文件名为“tweety.bmp"的位图。
.if uMsg==WM_CREATE
invoke LoadBitmap,hInstance,IDB_MAIN
mov hBitmap,eax
在处理 WM_CREATE 消息时, 我们通过API函数 LoadBitmap 载入位图资源,并通过函数
返回值取得位图句柄。
然后,我们就可以把位图画在窗口客户区上。
.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
在本例中,我们选用在响应WM_PAINT消息时画出位图。首先我们通过API函数l BeginPaint 获得窗口客户区的DC句柄。 接着我们通过API函数 CreateCompatibleDC 创建该DC 的内存映像,并通过API函数 SelectObject 把位图放进内存映像中。下一步,我们通过API函数 GetClientRect 取得窗口客户区的大小。最后,我们通过API函数 BitBlt 把位图从DC内存映像复制到真正的客户区DC中。 完成显示工作后,我们通过API函数 DeleteDC 释放DC内存映像,并用API函数 EndPaint 释放客户区DC, 结束画图工作。
.ELSEIF UMSG==WM_DESTROY
INVOKE DELETEOBJECT,HBITMAP
INVOKE POSTQUITMESSAGE,NULL
当我们不再需要位图时,通过API函数 DeleteObject 把它释放。