;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 使用 nmake 或下列命令进行编译和链接: ; ml /c /coff Clock.asm ; rc Clock.rc ; Link /subsystem:windows Clock.obj Clock.res ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .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 .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 ;ecx/2 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 ;如果Y>X add dwCenterX,edx ;原点X=半径=Min{宽度:高度}/2 add dwCenterY,edx ;原点Y=|高度-宽度|/2+X ret _CalcClockParam endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 计算时钟圆周上某个角度对应的 X 坐标 ; X = 圆心X + Sin(角度) * 半径 ;弧度的定义:弧长等于圆半径长的弧所对的圆心角为1弧度,弧度没有单位。 ;即弧度=弧长/半径=l/r,因此,若弧度=π,弧长=πr=圆周的一半, ;此时恰好为一个半圆,圆心角180,也就是说π=180,1°=π/180 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _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 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 按照 _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 ;真正的刻度圆半径=dwRadius-10 .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 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _ShowTime proc _hWnd,_hDC local @stTime:SYSTEMTIME pushad invoke _CalcClockParam ;******************************************************************** ; 画时钟圆周上的点 ;******************************************************************** invoke GetStockObject,BLACK_BRUSH invoke SelectObject,_hDC,eax invoke _DrawDot,_hDC,360/12,3 ;画12个大圆点 invoke _DrawDot,_hDC,360/60,1 ;画60个小圆点 popad ret _ShowTime endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _ProcWinMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam local @stPS:PAINTSTRUCT mov eax,uMsg .if eax == WM_PAINT invoke BeginPaint,hWnd,addr @stPS invoke _ShowTime,hWnd,eax invoke EndPaint,hWnd,addr @stPS .elseif eax == WM_CLOSE 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
给老罗的代码瘦身。:)