表盘

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 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

给老罗的代码瘦身。:)

 

posted @ 2013-12-08 19:21  乾卦  阅读(313)  评论(0编辑  收藏  举报