测试运行环境:Window7
编译软件:MASMPlus
程序设计来源:Win32汇编语言程序设计
其他说明: 简单的一个时钟,不含资源文件图标代码以及素材
示例图:
1.png
代码部分:
.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?
hInstance dd ?
hWinMain dd ?
dwCenterX dd ? ;圆心X
dwCenterY dd ? ;圆心Y
dwRadius dd ? ;半径
.const
szClassName db 'Clock',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 计算时钟的位置,大小等参数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.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
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坐标
; X = 圆心X + Sin(角度) * 半径
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_dwPara180 dw 180
_CalcX proc _dwDegree,_dwRadius
local @dwReturn
fild dwCenterX
fild _dwDegree
fldpi
fmul ;角度*PI
fild _dwPara180
fdivp st(1),st ;角度*PI/180
fsin ;Sin(角度*PI/180)
fild _dwRadius
fmul ;半径*Sin(角度*PI/180)
fadd ;x+半径*Sin(角度*PI/180)
fistp @dwReturn
mov eax,@dwReturn
ret
_CalcX endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 计算时钟圆周上某个角度对应的 Y坐标
; Y = 圆心Y - Cos(角度) * 半径
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_CalcY proc _dwDegree,_dwRadius
local @dwReturn
fild dwCenterY
fild _dwDegree
fldpi
fmul
fild _dwPara180
fdivp st(1),st
fcos
fild _dwRadius
fmul
fsubp st(1),st
fistp @dwReturn
mov eax,@dwReturn
ret
_CalcY endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 计算小圆点的圆心坐标
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_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
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
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
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
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
mul ecx ;分针度数 = 分 * 360/60
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
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