程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 匯編語言 >> 匯編教程:位圖初步

匯編教程:位圖初步

編輯:匯編語言

在這一課,我們將學習怎樣在程序中使用位圖。 更准確地說,我們要學習的是怎樣在一個窗口的客戶區中顯示位圖。

理論

位圖就是存貯於電腦中的圖片。位圖文件有相當多的格式(譯者:如.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
...........

獲得一個設備文本(DC)句柄。你可以在響應WM_PAINT消息時通過API函數BeginPaint獲得。 如果在其它消息中則可以用API函數GetDC獲得。

創建這個DC的內存映像。這樣做的目的是建立一張“隱藏的畫紙”,把位圖 “畫”在上面,作緩沖之用。完成這項工作後,我們就通過一個函數把“畫紙”上的位圖復制 到真正的DC中。這就是在屏幕上快速顯示圖象的雙緩沖技術。(譯者:可以減少圖象抖動) 這張“畫紙”用API函數 CreateCompatibleDC 建立,下面是它的完型:

CreateCompatibleDC proto hdc:HDC

如果函數執行成功,將返回DC內存映像也即“畫紙”的句柄。

現在我們已經有了“畫紙”,可以把位圖畫在上面了。這可以通過API函數 SelectObject 完成, 其中第一個參數是“畫紙”的句柄,第二個參數則是位圖的句柄,下面是函數的完型:

SelectObject proto hdc:HDC, hGdiObject:DWORD

現在位圖已經畫在“畫紙”上了。下一步我們要把位圖復制到真正的DC中。 有很多API函數都能完成這項工作,例如 BitBlt 和 StretchBlt。 函數 BitBlt 僅僅將一個DC的內容簡單地復制到另一個DC中,而函數 StretchBlt 則能夠自動調整源DC復制內容的大小已適應目的DC的輸出區域大小,因此前者比後者速度更快。 在這裡我們只使用函數 BitBlt ,下面是它的完型:
  BitBlt 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)。該參數用以確定復制內容的顏色與輸出區域原來的顏色按哪種運算 方式處理。通常,只需要簡單地用復制內容把輸出區域覆蓋掉。

一切辦妥後,就用API函數 DeleteObject 釋放位圖對象,也就是把位圖“抹掉”。

大功告成! 現在再來回顧一下整個過程:首先,你需要把位圖定義在資源文件中。 然後,你需要在程序中載入位圖資源,並取得位圖句柄。隨後,你需要獲得位圖輸出區域的DC,以及創建這個DC的內存映像,並把位圖放進這個DC內存映像中。最後把位圖從DC內存映像復制到真正的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
;---------------------------------------------------------------------
; 資源定義
;---------------------------------------------------------------------
#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 把它釋放。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved