位圖(Bitmap, .bmp)是 Windows 原生支援的影像格式。在視窗程式中顯示位圖,核心流程是:載入資源 → 取得裝置內容 (DC) → 建立相容記憶體 DC → 選入位圖 → BitBlt/StretchBlt 複製到螢幕 DC → 釋放資源。本文詳細說明每個步驟對應的 API、參數與完整範例。
資源腳本 (.rc) 中定義位圖有兩種方式:
; 方式一:整數 ID
#define IDB_MYBITMAP 100
IDB_MYBITMAP BITMAP "c:\project\example.bmp"
; 方式二:字串名稱
MyBitMap BITMAP "c:\project\example.bmp"
編譯後,位圖嵌入 EXE 資源區。程式中以 LoadBitmap 載入:
LoadBitmap proto hInstance:HINSTANCE, lpBitmapName:LPSTR
; 返回位圖控制代碼 (HBITMAP)
invoke LoadBitmap, hInstance, IDB_MYBITMAP(或直接傳數值 100)。invoke LoadBitmap, hInstance, addr BitmapName(BitmapName db "MyBitMap",0)。BeginPaint(hwnd, &ps) 取得客戶區 DC,繪圖結束需 EndPaint。GetDC(hwnd) 取得 DC,用畢需 ReleaseDC。CreateCompatibleDC proto hdc:HDC
; 返回記憶體 DC 控制代碼,作為「隱藏畫布」
SelectObject proto hdc:HDC, hGdiObject:DWORD
; 將位圖選入記憶體 DC,返回先前被替換的 GDI 物件控制代碼(繪圖結束需選回)
流程:
hdc = BeginPaint(...)hMemDC = CreateCompatibleDC(hdc)hOldBmp = SelectObject(hMemDC, hBitmap)BitBlt proto hdcDest:DWORD, nxDest:DWORD, nyDest:DWORD, nWidth:DWORD, nHeight:DWORD, \
hdcSrc:DWORD, nxSrc:DWORD, nySrc:DWORD, dwROP:DWORD
StretchBlt proto hdcDest:DWORD, nxDest:DWORD, nyDest:DWORD, nWidth:DWORD, nHeight:DWORD, \
hdcSrc:DWORD, nxSrc:DWORD, nySrc:DWORD, nWidthSrc:DWORD, nHeightSrc:DWORD, dwROP:DWORD
dwROP:光柵操作碼,常用 SRCCOPY(直接覆蓋)。SelectObject(hMemDC, hOldBmp) ; 還原記憶體 DC 原狀
DeleteDC(hMemDC) ; 刪除記憶體 DC
EndPaint(hwnd, &ps) ; 釋放螢幕 DC
DeleteObject(hBitmap) ; 程式結束時釋放位圖物件
.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
; 資源定義 (在 .rc 檔中)
#define IDB_MAIN 1
IDB_MAIN BITMAP "tweety78.bmp"
hBitmap 供後續繪圖使用。GetClientRect 取得客戶區尺寸,BitBlt 將記憶體 DC 內容完整複製到螢幕 DC。StretchBlt 實作位圖縮放、平鋪、鏡像。TransparentBlt(需 msimg32.lib)實現透明色繪製。BitBlt 呈現。Win32 位圖顯示的核心是 DC 機制與 BitBlt/StretchBlt。掌握資源載入、雙緩衝流程、資源釋放時機,即可在組合語言中實作高效能的 2D 圖形輸出。下一步可探索 GDI+、Direct2D 或 Direct3D 以獲得硬體加速與更豐富的繪圖功能。