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


返回上一頁