哈哈,这个icon是以前玩dota的时候里面一个物品叫做振奋宝石,顺便说一句我在网上淘了dota里面所有的图标还有音乐哦,嘿嘿,有需要的发邮件,鄙人定会慷慨相送哈~~
感谢ghoste同学的帮助差错,我得好好学习下程序的调试!唉,让我悲剧的基础,太不扎实了
这次代码问题主要在窗口过程那边,用windows自定义的DefWindowProc函数的时候下面忘记了ret!令人发指!!
好吧,错误记录下来了,下面是源码
;——————————————————————————–
;时钟程序
;win32asm绘制图形,非使用位图
;作者:阿拉丁 《琢石成器》第七章
;时间:2011.4.7
;——————————————————————————–
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include gdi32.inc
includelib gdi32.lib
ICO_MAIN equ 1000h
ID_TIMER equ 1
.data
dw180 dw 180
.data?
hInstance dd ?
hWinMain dd ?
dwCenterX dd ? ;圆心x
dwCenterY dd ? ;圆心y
dwRadius dd ? ;钟表盘半径
.const
szClassName db ‘clock’,0
;dw180 dw 180
.code
;计算时钟位置和大小等参数
_CalcClockParam proc
LOCAL @stRect:RECT
invoke GetClientRect,hWinMain,addr @stRect
mov eax,@stRect.right
sub eax,@stRect.left ;eax=宽度
mov ecx,@stRect.bottom
sub ecx,@stRect.top ;ecx=高度
;比较客户区的宽度和高度,用小的来做半径
.if ecx>eax ;宽度大于高度
mov edx,eax
sub ecx,eax ;宽度减去高度放到ecx
shr ecx,1 ;减去后的值右移一位,为什么????知道了,是除以二哈哈
mov dwCenterX,0
mov dwCenterY,ecx
.else ;高度大于宽度
mov edx,ecx
sub eax,ecx
shr eax,1
mov dwCenterX,eax
mov dwCenterY,0
.endif
shr edx,1 ;切圆的半径
mov dwRadius,edx
add dwCenterX,edx ;真正的圆心横坐标
add dwCenterY,edx ;真正的圆心纵坐标
ret
_CalcClockParam endp
;计算时钟某个角度对应的x坐标(角度_dwDegree是按逆时针旋转,初始角度为十二点时刻0度角)
;x=dwCenterX+sin(_dwDegree)*_dwRaius
;dw180 dw 180
_CalcX proc _dwDegree,_dwRadius
LOCAL @dwReturn
fild dwCenterX ;将dwCenterX放入浮点寄存器
fild _dwDegree ;角度放入浮点寄存器
fldpi ;将pi放入浮点寄存器
fmul ;角度*pi 【FMUL 乘上一个实数 st(0) <- st(0) * st(1)】
fild dw180
fdivp st(1),st ;角度*pi/180 【st(i) <-st(0) /st(i),然后执行一次出栈操作】
fsin ;sin(角度*pi/180)
fild _dwRadius
fmul ;半径*sin(角度*pi/180)
fadd ;dwCenterX+半径*sin(角度*pi/180)
fistp @dwReturn ;FISTP dest dest <- st(0) (mem16/mem32/mem64);然后再执行一次出栈操作
mov eax,@dwReturn
ret
_CalcX endp
;计算时钟某个角度对应的y坐标(角度_dwDegree是按逆时针旋转,初始角度为十二点时刻0度角)
;y=dwCentery-cos(_dwDegree)*_dwRaius
_CalcY proc _dwDegree,_dwRadius
LOCAL @dwReturn
fild dwCenterY
fild _dwDegree
fldpi
fmul
fild dw180
fdivp st(1),st
fcos
fild _dwRadius
fmul
fsubp st(1),st
fistp @dwReturn
mov eax,@dwReturn
ret
_CalcY endp
;按照_dwDegreeInc的步进角度,画_dwRadius为半径的小圆点
_DrawDot proc _hDC,_dwDegreeInc,_dwRadius
LOCAL @dwNowDegree,@dwR
LOCAL @dwX,@dwY
mov @dwNowDegree,0
mov eax,dwRadius
sub eax,10
mov @dwR,eax;这他妈才是真正的钟表盘半径,我了个去~~~烦恼了半天
.while @dwNowDegree<=360
finit;FINIT 初始化FPU
;计算小圆点的圆心坐标
invoke _CalcX,@dwNowDegree,@dwR
mov @dwX,eax
invoke _CalcY,@dwNowDegree,@dwR
mov @dwY,eax
mov eax,@dwX;画点
mov ebx,eax
mov ecx,@dwY
mov edx,ecx
sub eax,_dwRadius
add ebx,_dwRadius
sub ecx,_dwRadius
add edx,_dwRadius
invoke Ellipse,_hDC,eax,ecx,ebx,edx;画一个与(x1,y1),(x2,y2)相切的椭圆
mov eax,_dwDegreeInc
add @dwNowDegree,eax
.endw
ret
_DrawDot endp
;画_dwDegree角度的线条,半径=时钟半径-参数_dwRadiusAdjust
_DrawLine proc _hDC,_dwDegree,_dwRadiusAdjust
LOCAL @dwR
LOCAL @dwX1,@dwY1,@dwX2,@dwY2
mov eax,dwRadius
sub eax,_dwRadiusAdjust
mov @dwR,eax
;计算线条两端的坐标
invoke _CalcX,_dwDegree,@dwR
mov @dwX1,eax
invoke _CalcY,_dwDegree,@dwR
mov @dwY1,eax
add _dwDegree,180
invoke _CalcX,_dwDegree,10 ;这里指针的圆心那边要出点头才好看,所以角度+180,然后半径10
mov @dwX2,eax
invoke _CalcY,_dwDegree,10
mov @dwY2,eax
invoke MoveToEx,_hDC,@dwX1,@dwY1,NULL ;设置当前点的位置
invoke LineTo,_hDC,@dwX2,@dwY2
ret
_DrawLine endp
_ShowTime proc _hWnd,_hDC
LOCAL @stTime:SYSTEMTIME
pushad
invoke GetLocalTime,addr @stTime
invoke _CalcClockParam
;画时钟圆周上的点
invoke GetStockObject,BLACK_BRUSH
invoke SelectObject,_hDC,eax
invoke _DrawDot,_hDC,360/12,3 ;12个大点
invoke _DrawDot,_hDC,360/60,1 ;60个小点
;画时钟指针
;秒针
invoke CreatePen,PS_SOLID,1,0
invoke SelectObject,_hDC,eax
invoke DeleteObject,eax
movzx eax,@stTime.wSecond
mov ecx,360/60
mul ecx ;秒针角度即秒数*360/60,结果总放在eax中
invoke _DrawLine,_hDC,eax,15
;——————————————————————————–
invoke CreatePen,PS_SOLID,2,0
invoke SelectObject,_hDC,eax
invoke DeleteObject,eax
movzx eax,@stTime.wMinute
mov ecx,360/60
mu
l ecx ;分针度数
invoke _DrawLine,_hDC,eax,20
;——————————————————————————–
invoke CreatePen,PS_SOLID,3,0
invoke SelectObject,_hDC,eax
invoke DeleteObject,eax
movzx eax,@stTime.wHour
.if eax >= 12
sub eax,12
.endif
mov ecx,360/12
mul ecx
movzx ecx,@stTime.wMinute
shr ecx,1
add eax,ecx ;时针小时所在的度数+分针代表的度数(0~30)
invoke _DrawLine,_hDC,eax,30
;——————————————————————————–
invoke GetStockObject,NULL_PEN
invoke SelectObject,_hDC,eax
invoke DeleteObject,eax
popad
ret
_ShowTime endp
_ProcWinMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam
LOCAL @stPS:PAINTSTRUCT
mov eax,uMsg
.if eax==WM_TIMER
invoke InvalidateRect,hWnd,NULL,TRUE
.elseif eax==WM_PAINT
invoke BeginPaint,hWnd,addr @stPS
invoke _ShowTime,hWnd,eax
invoke EndPaint,hWnd,addr @stPS
.elseif eax == WM_CREATE
invoke SetTimer,hWnd,ID_TIMER,1000,NULL
.elseif eax==WM_CLOSE
invoke KillTimer,hWnd,ID_TIMER
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
_ProcWinMain endp
_WinMain proc
LOCAL @stWndClass:WNDCLASSEX
LOCAL @stMsg:MSG
invoke GetModuleHandle,NULL
mov hInstance,eax
;注册窗口类
invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
invoke LoadIcon,hInstance,ICO_MAIN
mov @stWndClass.hIcon,eax
mov @stWndClass.hIconSm,eax
invoke LoadCursor,0,IDC_ARROW
mov @stWndClass.hCursor,eax
push hInstance
pop @stWndClass.hInstance
mov @stWndClass.cbSize,sizeof WNDCLASSEX
mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW
mov @stWndClass.lpfnWndProc,offset _ProcWinMain
mov @stWndClass.hbrBackground,COLOR_WINDOW+1
mov @stWndClass.lpszClassName,offset szClassName
invoke RegisterClassEx,addr @stWndClass
;建立显示窗口
invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szClassName,WS_OVERLAPPEDWINDOW,100,100,250,270,NULL,NULL,hInstance,NULL
mov hWinMain,eax
invoke ShowWindow,hWinMain,SW_SHOWNORMAL
invoke UpdateWindow,hWinMain
.while TRUE
invoke GetMessage,addr @stMsg,NULL,0,0
.break .if eax==0
invoke TranslateMessage,addr @stMsg
invoke DispatchMessage,addr @stMsg
.endw
ret
_WinMain endp
start:
call _WinMain
invoke ExitProcess,NULL
end start