?? clock.asm
字號:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming >
; by 羅云彬, http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Clock.asm
; 時鐘例子:使用 GDI 函數繪畫指針
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令進行編譯和鏈接:
; ml /c /coff Clock.asm
; rc Clock.rc
; Link /subsystem:windows Clock.obj Clock.res
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定義
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include Gdi32.inc
includelib Gdi32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定義
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
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
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 按照 _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
;********************************************************************
; 計算小圓點的圓心坐標
;********************************************************************
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
;********************************************************************
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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -