Netwide Assembler (NASM) >> Assembly (x86) >> Win32 API >> Painting
Set Pixel
參考資訊:
1. nasm
2. masm32
屏幕的最小顯示單位是像素,像素由紅色(Red)、綠色(Green)、藍色(Blue)、Alpha等四個顏色組成,因此,在呼叫CreateWindow()時,傳入的解析度,如:300x300,代表該視窗(有效區域)的X軸有300個像素,而Y軸則是有300個像素,這個300x300像素的區域是可以用來繪製任何東西,WM_PAINT是處理視窗重新繪畫的事件,繪畫的相關處理都需要在這個事件完成,比較特別的是,Windows視窗將繪圖的許多東西抽象化,最基本的需求是:一個DC(Device Context)和一個BITMAP,DC可以想像成是一個畫台,而BITMAP則是一片畫布(Buffer),DC有了Buffer就可以畫上任何東西並將其顯示在視窗上
main.asm
[bits 32] global _start extern _sprintf extern _SetPixel@16 extern _EndPaint@8 extern _SetTimer@16 extern _KillTimer@8 extern _BeginPaint@8 extern _ExitProcess@4 extern _GetMessageA@16 extern _MessageBoxA@16 extern _SetScrollPos@16 extern _DestroyWindow@4 extern _SetScrollRange@20 extern _SetWindowTextA@8 extern _SetWindowLongA@12 extern _CallWindowProcA@20 extern _GetCommandLineA@0 extern _CreateWindowExA@48 extern _PostQuitMessage@4 extern _GetModuleHandleA@4 extern _DispatchMessageA@4 %define ARG1 8h %define ARG2 0ch %define ARG3 10h %define ARG4 14h %define sprintf _sprintf %define SetPixel _SetPixel@16 %define EndPaint _EndPaint@8 %define SetTimer _SetTimer@16 %define KillTimer _KillTimer@8 %define BeginPaint _BeginPaint@8 %define GetMessage _GetMessageA@16 %define MessageBox _MessageBoxA@16 %define ExitProcess _ExitProcess@4 %define SetScrollPos _SetScrollPos@16 %define DestroyWindow _DestroyWindow@4 %define SetScrollRange _SetScrollRange@20 %define SetWindowText _SetWindowTextA@8 %define SetWindowLong _SetWindowLongA@12 %define CallWindowProc _CallWindowProcA@20 %define GetCommandLine _GetCommandLineA@0 %define CreateWindowEx _CreateWindowExA@48 %define PostQuitMessage _PostQuitMessage@4 %define GetModuleHandle _GetModuleHandleA@4 %define DispatchMessage _DispatchMessageA@4 struc RECT .left: resd 1 .top: resd 1 .right: resd 1 .bottom: resd 1 .SIZE: endstruc struc PAINTSTRUCT .hdc: resd 1 .fErase: resd 1 .rcPaint: resb RECT.SIZE .fRestore: resd 1 .fIncUpdate: resd 1 .rgbReserved: resb 32 .SIZE: endstruc struc POINT .x: resd 1 .y: resd 1 .SIZE: endstruc struc MSG .hwnd: resd 1 .message: resd 1 .wParam: resd 1 .lParam: resd 1 .time: resd 1 .pt: resb POINT.SIZE .SIZE: endstruc WM_PAINT equ 0fh SB_LINEUP equ 0 SB_LINELEFT equ 0 SB_LINEDOWN equ 1 SB_LINERIGHT equ 1 SB_PAGEUP equ 2 SB_PAGELEFT equ 2 SB_PAGEDOWN equ 3 SB_PAGERIGHT equ 3 SB_VERT equ 1 GWL_WNDPROC equ -4 SW_SHOWNORMAL equ 1h WC_DIALOG equ 8002h WM_VSCROLL equ 115h WM_TIMER equ 113h WM_MOUSEMOVE equ 200h WM_SYSKEYDOWN equ 104h WM_KEYDOWN equ 100h WM_DESTROY equ 2h WM_CLOSE equ 10h WS_VSCROLL equ 200000h WS_OVERLAPPED equ 0h WS_CAPTION equ 0c00000h WS_SYSMENU equ 80000h WS_THICKFRAME equ 40000h WS_MINIMIZEBOX equ 20000h WS_MAXIMIZEBOX equ 10000h WS_VISIBLE equ 10000000h WS_EX_LEFT equ 00000000h WS_OVERLAPPEDWINDOW equ WS_OVERLAPPED | \ WS_CAPTION | \ WS_SYSMENU | \ WS_THICKFRAME | \ WS_MINIMIZEBOX | \ WS_MAXIMIZEBOX section .drectve info _entry db "/entry:start " _gdi32 db "/defaultlib:c:\\masm32\\lib\\gdi32.lib " _user32 db "/defaultlib:c:\\masm32\\lib\\user32.lib " _msvcrt db "/defaultlib:c:\\masm32\\lib\\msvcrt.lib " _kernel32 db "/defaultlib:c:\\masm32\\lib\\kernel32.lib " segment .data hWin dd 0 szCaption db "main",0 hInstance dd 0 defWndProc dd 0 CommandLine dd 0 hdc dd 0 x dd 0 y dd 0 msg istruc MSG at .hwnd, dd 0 at .message, dd 0 at .wParam, dd 0 at .lParam, dd 0 at .time, dd 0 at .pt, dd 0, 0 iend ps istruc PAINTSTRUCT at .hdc, dd 0 at .fErase, dd 0 at .rcPaint, dd 0, 0, 0, 0 at .fRestore, dd 0 at .fIncUpdate, dd 0 at .rgbReserved, db 0 iend segment .text WndProc: push ebp mov ebp, esp cmp dword [ebp + ARG2], WM_PAINT je .handle_paint cmp dword [ebp + ARG2], WM_CLOSE je .handle_close cmp dword [ebp + ARG2], WM_DESTROY je .handle_destroy jmp .handle_default .handle_paint: push ps push dword [ebp + ARG1] call BeginPaint mov [hdc], eax xor eax, eax mov [y], eax .ylp: xor eax, eax mov [x], eax .xlp: push 0ffh push dword [x] push dword [y] push dword [hdc] call SetPixel inc dword [x] cmp dword [x], 100 jb .xlp inc dword [y] cmp dword [y], 100 jb .ylp push ps push dword [ebp + ARG1] call EndPaint xor eax, eax jmp .finish .handle_close: push dword [ebp + ARG1] call DestroyWindow xor eax, eax jmp .finish .handle_destroy: push 0 call PostQuitMessage xor eax, eax jmp .finish .handle_default: push dword [ebp + ARG4] push dword [ebp + ARG3] push dword [ebp + ARG2] push dword [ebp + ARG1] push dword [defWndProc] call CallWindowProc .finish: leave ret 16 WinMain: push ebp mov ebp, esp push 0 push 0 push 0 push 0 push 300 push 300 push 0 push 0 push WS_OVERLAPPEDWINDOW | WS_VISIBLE push szCaption push WC_DIALOG push WS_EX_LEFT call CreateWindowEx mov [hWin], eax push WndProc push GWL_WNDPROC push dword [hWin] call SetWindowLong mov [defWndProc], eax .loop: push 0 push 0 push 0 push msg call GetMessage cmp eax, 0 je .exit push msg call DispatchMessage jmp .loop .exit: mov eax, [msg + MSG.wParam] leave ret 16 _start: push 0 call GetModuleHandle mov [hInstance], eax call GetCommandLine mov [CommandLine], eax push SW_SHOWNORMAL push dword [CommandLine] push 0 push dword [hInstance] call WinMain push eax call ExitProcess
Line 168~196:處理繪畫事件
Line 169~172:取得視窗的DC,該DC已經有Buffer可以使用,因此,可以直接在上面繪製任何東西
Line 174~190:透過SetPixel()畫出一個正方形,顏色是紅色
Line 192~194:結束繪製
Makefile
export WINEPREFIX=/home/user/.wine_amd64 TARGET=main MYWINE=box86 wine NASM32=/home/user/.wine_amd64/drive_c/nasm MASM32=/home/user/.wine_amd64/drive_c/masm32 all: ${MYWINE} ${NASM32}/bin/nasm.exe -fwin32 ${TARGET}.asm ${MYWINE} ${MASM32}/bin/link.exe /SUBSYSTEM:WINDOWS /MERGE:.rdata=.text ${TARGET}.obj run: ${MYWINE} ${TARGET}.exe clean: rm -rf ${TARGET}.exe ${TARGET}.obj
編譯、執行
$ make $ make run