效果图:

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;win32汇编使用GDI+入门教程之六
;我们一点点来学,在本教程里,我们尝试画出圆形和椭圆形。主要使用的是GdipDrawEllipseI函数和GdipFillEllipseI函数
;GdipDrawEllipseI有5个参数,相当于下面这样
;GdipDrawEllipseI(画布,画笔,圆所在正方形的左上角X坐标,圆所在左上角的Y坐标,宽度,高度)
;而GdipFillEllipseI则把画笔换成画刷
;画需要画室,需要画布,需要画笔,填充则需要画刷,就像刷子。
;以下代码在64位的win7系统编译通过,直接复制进RadAsm可编译运行;
;注意注释部分在编译时可以删除,不然容易出错。重要部分加备注。
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff FirstWindow.asm
; Link /subsystem:windows FirstWindow.obj
.386
.model flat, stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
include gdiplus.inc
includelib gdiplus.lib
includelib user32.lib
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; GdiplusStartupInput结构在gdiplus头文件里面没有定义,这里我们自已定义
GdiplusStartupInput STRUCT
GdiplusVersion DWORD ? ; 设置为1
DebugEventCallback DWORD ? ; 调试回调,通常为NULL
SuppressBackgroundThread DWORD ? ; 是否抑制后台线程
SuppressExternalCodecs DWORD ? ; 是否抑制外部编解码器
GdiplusStartupInput ENDS
; ==============================================
; 数据段
; ==============================================
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
gdiplusToken dd ? ;实例变量,每个实例的意思相当于浏览器里打开的每个页面,这里相当于画室
pGraphics dd ? ;画布变量,有画布,才能在上面写或画或涂
.data
ClassName db "GdiplusShapesDemo",0
AppName db "WIN32汇编下使用GDI+ 绘制椭圆形",0
UnitPixel equ 2 ;设为2就是单位参数是像素,而不是英寸或其它什么的标准
.code
; ==============================================
; 窗口过程
; ==============================================
WndProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
local @ps:PAINTSTRUCT
local @hdc:HDC
local @startupInput:GdiplusStartupInput
local @pPen:DWORD ;画笔变量
local @pBrush:DWORD ;画刷变量
.if uMsg == WM_CREATE
; 初始化GDI+
mov @startupInput.GdiplusVersion, 1
mov @startupInput.DebugEventCallback, NULL
mov @startupInput.SuppressBackgroundThread, FALSE
mov @startupInput.SuppressExternalCodecs, FALSE
invoke GdiplusStartup, addr gdiplusToken, addr @startupInput, NULL
.elseif uMsg == WM_PAINT
invoke BeginPaint, hWnd, addr @ps
mov @hdc, eax
invoke GdipCreateFromHDC, @hdc, addr pGraphics ;在设备上,即屏幕上创建画布
invoke GdipCreatePen1, 0FFFF00FFh, 2, UnitPixel, addr @pPen ;创建粉色画笔
invoke GdipDrawEllipseI, pGraphics, @pPen, 60, 50, 80, 80 ;后面2个参数是宽和高的值,宽和高相等就是正圆形了
invoke GdipDrawEllipseI, pGraphics, @pPen, 200, 50, 100, 70
invoke GdipCreateSolidFill, 0FFFFA500h, addr @pBrush ; 创建橙色画刷
invoke GdipFillEllipseI, pGraphics, @pBrush, 60, 200, 80, 80
invoke GdipFillEllipseI, pGraphics, @pBrush, 200, 200, 100, 70
invoke GdipDeletePen, @pPen ;删除画笔
invoke GdipDeleteBrush, @pBrush ;删除画刷
invoke GdipDeleteGraphics, pGraphics ;删除画布
invoke EndPaint, hWnd, addr @ps
.elseif uMsg == WM_DESTROY
; 清理资源
invoke GdiplusShutdown, gdiplusToken ;删除实例
invoke PostQuitMessage, 0
.else
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.endif
xor eax, eax
ret
WndProc endp
; ==============================================
; 主程序入口
; ==============================================
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
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,100,100,400,600, NULL,NULL,hInst, NULL
mov hwnd,eax
invoke ShowWindow, hwnd,CmdShow
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
end start