win32asm绘制图形实例-模拟时钟小程序

 

clock

哈哈,这个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

汇编浮点指令(以前一直没接触浮点指令……)

浮点指令
第四节 浮点指令

对下面的指令先做一些说明:
st(i):代表浮点寄存器,所说的出栈、入栈操作都是对st(i)的影响
src,dst,dest,op等都是指指令的操作数,src表示源操作数,dst/dest表示目的操作数
mem8,mem16,mem32,mem64,mem80等表示是内存操作数,后面的数值表示该操作数的内存位数(8位为一字节)
x <- y 表示将y的值放入x,例st(0) <- st(0) – st(1)表示将st(0)-st(1)的值放入浮点寄存器st(0)

1.  数据传递和对常量的操作指令

指令格式 指令含义 执行的操作
FLD src 装入实数到st(0) st(0) <- src (mem32/mem64/mem80)
FILD src 装入整数到st(0) st(0) <- src (mem16/mem32/mem64)
FBLD src 装入BCD数到st(0) st(0) <- src (mem80)
FLDZ 将0.0装入st(0) st(0) <- 0.0
FLD1 将1.0装入st(0) st(0) <- 1.0
FLDPI 将pi装入st(0) st(0) <- ?(ie, pi)
FLDL2T 将log2(10)装入st(0) st(0) <- log2(10)
FLDL2E 将log2(e)装入st(0) st(0) <- log2(e)
FLDLG2 将log10(2)装入st(0) st(0) <- log10(2)
FLDLN2 将loge(2)装入st(0) st(0) <- loge(2)
FST dest 保存实数st(0)到dest dest <- st(0) (mem32/mem64)
FSTP dest dest <- st(0) (mem32/mem64/mem80);然后再执行一次出栈操作
FIST dest 将st(0)以整数保存到dest dest <- st(0) (mem32/mem64)
FISTP dest dest <- st(0) (mem16/mem32/mem64);然后再执行一次出栈操作
FBST dest 将st(0)以BCD保存到dest dest <- st(0) (mem80)
FBSTP dest dest<- st(0) (mem80);然后再执行一次出栈操作

2.比较指令

指令格式 指令含义 执行的操作
FCOM 实数比较 将标志位设置为 st(0) – st(1) 的结果标志位
FCOM op 实数比较 将标志位设置为 st(0) – op (mem32/mem64)的结果标志位
FICOM op 和整数比较 将Flags值设置为st(0)-op 的结果op (mem16/mem32)
FICOMP op 和整数比较 将st(0)和op比较 op(mem16/mem32)后;再执行一次出栈操作
FTST 零检测 将st(0)和0.0比较
FUCOM st(i) 比较st(0) 和st(i)                  [486]
FUCOMP st(i) 比较st(0) 和st(i),并且执行一次出栈操作
FUCOMPP st(i) 比较st(0) 和st(i),并且执行两次出栈操作
FXAM Examine: Eyeball st(0) (set condition codes)

3.运算指令

指令格式 指令含义 执行的操作
加法
FADD 加实数 st(0) <-st(0) + st(1)
FADD src st(0) <-st(0) + src (mem32/mem64)
FADD st(i),st st(i) <- st(i) + st(0)
FADDP st(i),st st(i) <- st(i) + st(0);然后执行一次出栈操作
FIADD src 加上一个整数 st(0) <-st(0) + src (mem16/mem32)
减法
FSUB 减去一个实数 st(0) <- st(0) – st(1)
FSUB src st(0) <-st(0) – src (reg/mem)
FSUB st(i),st st(i) <-st(i) – st(0)
FSUBP st(i),st st(i) <-st(i) – st(0),然后执行一次出栈操作
FSUBR st(i),st 用一个实数来减 st(0) <- st(i) – st(0)
FSUBRP st(i),st st(0) <- st(i) – st(0),然后执行一次出栈操作
FISUB src 减去一个整数 st(0) <- st(0) – src (mem16/mem32)
FISUBR src 用一个整数来减 st(0) <- src – st(0) (mem16/mem32)
乘法
FMUL 乘上一个实数 st(0) <- st(0) * st(1)
FMUL st(i) st(0) <- st(0) * st(i)
FMUL st(i),st st(i) <- st(0) * st(i)
FMULP st(i),st st(i) <- st(0) * st(i),然后执行一次出栈操作
FIMUL src 乘上一个整数 st(0) <- st(0) * src (mem16/mem32)
除法
FDIV 除以一个实数 st(0) <-st(0) /st(1)
FDIV st(i) st(0) <- st(0) /t(i)
FDIV st(i),st st(i) <-st(0) /st(i)
FDIVP st(i),st st(i) <-st(0) /st(i),然后执行一次出栈操作
FIDIV src 除以一个整数 st(0) <- st(0) /src (mem16/mem32)
FDIVR st(i),st 用实数除 st(0) <- st(i) /st(0)
FDIVRP st(i),st FDIVRP st(i),st
FIDIVR src 用整数除 st(0) <- src /st(0) (mem16/mem32)
FSQRT 平方根 st(0) <- sqrt st(0)
FSCALE 2的st(0)次方 ST(0) <- ST(0)*(2^ST(1))
FXTRACT Extract exponent: st(0) <-exponent of st(0); and gets pushed 

st(0) <-significand of st(0)

FPREM 取余数 st(0) <-st(0) MOD st(1)
FPREM1 取余数(IEEE),同FPREM,但是使用IEEE标准[486]
FRNDINT 取整(四舍五入) st(0) <- INT( st(0) ); depends on RC flag
FABS 求绝对值 st(0) <- ABS( st(0) ); removes sign
FCHS 改变符号位(求负数) st(0) <-st(0)
F2XM1 计算(2 ^ x)-1 st(0) <- (2 ^ st(0)) – 1
FYL2X 计算Y * log2(X) st(0)为Y;st(1)为X;将st(0)和st(1)变为st(0) * log2( st(1) )的值
FCOS 余弦函数Cos st(0) <- COS( st(0) )
FPTAN 正切函数tan st(0) <- TAN( st(0) )
FPATAN 反正切函数arctan st(0) <- ATAN( st(0) )
FSIN 正弦函数sin st(0) <- SIN( st(0) )
FSINCOS sincos函数 st(0) <-SIN( st(0) ),并且压入st(1) 

st(0) <- COS( st(0) )

FYL2XP1 计算Y * log2(X+1) st(0)为Y; st(1)为X; 将st(0)和st(1)变为st(0) * log2( st(1)+1 )的值
处理器控制指令
FINIT 初始化FPU
FSTSW AX 保存状态字的值到AX AX<- MSW
FSTSW dest 保存状态字的值到dest dest<-MSW (mem16)
FLDCW src 从src装入FPU的控制字 FPU CW <-src (mem16)
FSTCW dest 将FPU的控制字保存到dest dest<- FPU CW
FCLEX 清除异常
FSTENV dest 保存环境到内存地址dest处 保存状态字、控制字、标志字和异常指针的值
FLDENV src 从内存地址src处装入保存的环境
FSAVE dest 保存FPU的状态到dest处 94字节
FRSTOR src 从src处装入由FSAVE保存的FPU状态
FINCSTP 增加FPU的栈指针值 st(6) <-st(5); st(5) <-st(4),…,st(0) <-?
FDECSTP 减少FPU的栈指针值 st(0) <-st(1); st(1) <-st(2),…,st(7) <-?
FFREE st(i) 标志寄存器st(i)未被使用
FNOP 空操作,等同CPU的nop st(0) <-st(0)
WAIT/FWAIT 同步FPU与CPU:停止CPU的运行,直到FPU完成当前操作码
FXCH 交换指令,交换st(0)和st(1)的值 st(0) <-st(1) 

st(1) <- st(0)

来源

GetLocalTime窗口显示本地时间

 

getlocaltime

源码:

        .386
        .model flat,stdcall
        option casemap:none
       
include        windows.inc
include        user32.inc
include        kernel32.inc

includelib    user32.lib
includelib    kernel32.lib

        .data       
SelString    dw    0,0

        .data?
stTimeInfo    SYSTEMTIME    <>
szBuffer    db        1024 dup(?)
ddYear        dd        ?
ddMonth        dd        ?
ddDay        dd        ?
ddHour        dd        ?
ddMinute    dd        ?
ddSecond    dd        ?
ddMilliseconds    dd        ?

        .const
WeekString    db        ‘日一二三四五六’,0
szMsgCaption    db        ‘what is the time’,0

szInfo        db        ‘%u年%u月%u日’,0dh,0ah,0dh,0ah,’星期%s’,0dh,0ah,0dh,0ah,’%u时%u分%u秒%u毫秒’,0dh,0ah,0

        .code
start:
    invoke    GetLocalTime,offset stTimeInfo;获取本地时间
    movzx    eax,stTimeInfo.wYear
    mov    ddYear,eax
    movzx    eax,stTimeInfo.wMonth
    mov    ddMonth,eax
   
    ;星期
    movzx    eax,stTimeInfo.wDayOfWeek
   
    .if    eax==0
        mov ax,word ptr WeekString
        mov  SelString,ax
    .elseif    eax==1
        mov ax,word ptr WeekString+2
        mov SelString,ax
    .elseif    eax==2
        mov ax,word ptr WeekString+4
        mov SelString,ax
    .elseif eax==3
        mov ax,word ptr WeekString+6
        mov SelString,ax
    .elseif eax==4
        mov ax,word ptr WeekString+8
        mov SelString,ax
    .elseif eax==5
        mov ax,word ptr WeekString+10
        mov SelString,ax
    .elseif eax==6
        mov ax,word ptr WeekString+12
        mov SelString,ax
    .endif
   
    movzx    eax,stTimeInfo.wDay
    mov    ddDay,eax
    movzx     eax,stTimeInfo.wHour
    mov    ddHour,eax
    movzx    eax,stTimeInfo.wMinute
    mov    ddMinute,eax
    movzx    eax,stTimeInfo.wSecond
    mov    ddSecond,eax
    movzx    eax,stTimeInfo.wMilliseconds
    mov    ddMilliseconds,eax
    invoke    wsprintf,addr szBuffer,addr szInfo,ddYear,ddMonth,ddDay,offset SelString,ddHour,ddMinute,ddSecond,ddMilliseconds
    invoke    MessageBox,NULL,addr szBuffer,addr szMsgCaption,MB_OK
    invoke    ExitProcess,NULL
   
    end start

唉,发现自己的基础性的东西还是太不扎实了,悲催~~

关于messagebox

今天上午上数据库课,说到一些vfp里面的函数,其中一个是书上没有讲的,老师补充了下那就是messagebox这个函数了,
messagebox
题外话,这360~~捕获
想到了以前自己学习win32asm中的api函数messagebox,其实很多地方都有messagebox,都是这个api的封装,其实老师讲的也很不详细,google了下vfp中这个函数的用法

messagebox( ) 函数

显示一个用户自定义对话框。

语法

MESSAGEBOX(cMessageText [, nDialogBoxType [, cTitleBarText]])

参数
cMessageText

指定在对话框中显示的文本。在 cMessageText 中包含回车符 (CHR(13)) 可以使信息移到下一行显示。对话框的高度和宽度根据 cMessageText 适当增大,以包含全部信息。

nDialogBoxType

指定对话框中的按钮和图标、显示对话框时的默认按钮以及对话框的行为。
在下面的表中,对话框按钮值从 0 到 5 指定了对话框中显示的按钮。图标值 16、32、64 指定了对话框中的图标。默认值 0、256、512 指定对话框中哪个按钮为默认按钮。当显示对话框时选中此默认按钮。
当省略 nDialagBoxType 时,等同于指定 nDialagBoxType 值为0。

数值  对话框按钮
0 仅有“确定”按钮
1 “确定”和“取消”按钮
2 “放弃”、“重试”和“忽略”按钮
3 “是”、“否”和“取消”按钮
4 “是”、“否”按钮
5 “重试”和“取消”按钮

数值  图标
16 “停止”图标
32 问号
48 惊叹号
64 信息 (i) 图标

数值  默认按钮
0 第一个按钮
256 第二个按钮
512 第三个按钮

nDialogBoxType 可以是三个值的和从上面每个表中选一个值。例如,若 nDialogBoxType 为 290(2+32+256),则指定的对话框含有如下特征:

“放弃”、“重试”或“忽略”按钮。
消息框显示问号图标。
第二个按钮,“重试”为默认按钮。
cTitleBarText

指定对话框标题栏中的文本。若省略 cTitleBarText,标题栏中将显示“Microsoft Visual FoxPro”

返回值类型

数值型

说明

MESSAGEBOX( ) 的返回值标明选取了对话框中的哪个按钮。在含有取消按钮的对话框中,如果按下 ESC 键退出对话框,则与选取“取消”按钮一样,返回值 (2)。
注意本函数的最短缩写为 MESSAGEB( )。
下表列出了 MESSAGEBOX( ) 对应每个按钮的返回值。

返回值  按钮
1 确定
2 取消
3 放弃
4 重试
5 忽略
6 是
7 否

下面的示例中显示了一个用户自定义对话框。标题“record not found.would you like to search again?”显示在用户自定义对话框中,标题栏中显示“my application”。用户自定义对话框含有“是”和“否”按钮以及问号图标。第二个按钮 (no) 为默认按钮。当选取一个按钮时,显示所选的内容。

cmessagetitle = 'my application'
cmessagetext = 'record not found. would you like to search again?'
ndialogtype = 4 + 32 + 256
* 4 = yes and no buttons
* 32 = question mark icon
* 256 = second button is default

nanswer = messagebox(cmessagetext, ndialogtype, cmessagetitle)

do case
case nanswer = 6
wait window 'you chose yes'
case nanswer = 7
wait window 'you chose no'
endcase
那么现在跟windows的api函数对比下(摘自msdn)

MessageBox Function

Displays a modal dialog box that contains a system icon, a set of buttons, and a brief application-specific message, such as status or error information. The message box returns an integer value that indicates which button the user clicked.

Syntax

int WINAPI MessageBox(
  __in_opt  HWND hWnd,
  __in_opt  LPCTSTR lpText,
  __in_opt  LPCTSTR lpCaption,
  __in      UINT uType
);

Parameters

hWnd [in, optional]
HWND
A handle to the owner window of the message box to be created. If this parameter is NULL, the message box has no owner window.

lpText [in, optional]
LPCTSTR
The message to be displayed. If the string consists of more than one line, you can separate the lines using a carriage return and/or linefeed character between each line.

lpCaption [in, optional]
LPCTSTR
The dialog box title. If this parameter is NULL, the default title is Error.

uType [in]
UINT
The contents and behavior of the dialog box. This parameter can be a combination of flags from the following groups of flags.

格式里面就这四个参数啦,比较有内容的参数呢就是uint了,其中可以包含button和icon

这个是button

Value Meaning
MB_ABORTRETRYIGNORE
0x00000002L
The message box contains three push buttons: AbortRetry, and Ignore.
MB_CANCELTRYCONTINUE
0x00000006L
The message box contains three push buttons: CancelTry AgainContinue. Use this message box type instead of MB_ABORTRETRYIGNORE.
MB_HELP
0x00004000L
Adds a Help button to the message box. When the user clicks the Help button or presses F1, the system sends a WM_HELP message to the owner.
MB_OK
0x00000000L
The message box contains one push button: OK. This is the default.
MB_OKCANCEL
0x00000001L
The message box contains two push buttons: OK and Cancel.
MB_RETRYCANCEL
0x00000005L
The message box contains two push buttons: Retry and Cancel.
MB_YESNO
0x00000004L
The message box contains two push buttons: Yes and No.
MB_YESNOCANCEL
0x00000003L
The message box contains three push buttons: YesNo, and Cancel.

这个是icon

Value Meaning
MB_ICONEXCLAMATION
0x00000030L
An exclamation-point icon appears in the message box.
MB_ICONWARNING
0x00000030L
An exclamation-point icon appears in the message box.
MB_ICONINFORMATION
0x00000040L
An icon consisting of a lowercase letter i in a circle appears in the message box.
MB_ICONASTERISK
0x00000040L
An icon consisting of a lowercase letter i in a circle appears in the message box.
MB_ICONQUESTION
0x00000020L
A question-mark icon appears in the message box. The question-mark message icon is no longer recommended because it does not clearly represent a specific type of message and because the phrasing of a message as a question could apply to any message type. In addition, users can confuse the message symbol question mark with Help information. Therefore, do not use this question mark message symbol in your message boxes. The system continues to support its inclusion only for backward compatibility.
MB_ICONSTOP
0x00000010L
A stop-sign icon appears in the message box.
MB_ICONERROR
0x00000010L
A stop-sign icon appears in the message box.
MB_ICONHAND
0x00000010L
A stop-sign icon appears in the message box.

 

可以对比一下和vfp中那些数值代表的意义,和api中的这些“数值”,其实它们是表示的在内存中的位置

api的返回值是int型

Return code/value Description
IDABORT
3
The Abort button was selected.
IDCANCEL
2
The Cancel button was selected.
IDCONTINUE
11
The Continue button was selected.
IDIGNORE
5
The Ignore button was selected.
IDNO
7
The No button was selected.
IDOK
1
The OK button was selected.
IDRETRY
4
The Retry button was selected.
IDTRYAGAIN
10
The Try Again button was selected.
IDYES
6
The Yes button was selected.

好吧,还有更多详细解释请看msdn,在这里只是抛个砖,顺带思考一下api和一些高级语言中的封装的对比,当然菜菜我也分析不出啥,权当mark

一个高手的C++学习心得

1.把C++当成一门新的语言学习(和C没啥关系!真的。);
2.看《Thinking In C++》,不要看《C++变成死相》;
3.看《The C++ Programming Language》和《Inside The C++ Object Model》,不要因为他们很难而我们自己是初学者所以就不看;
4.不要被VC、BCB、BC、MC、TC等词汇所迷惑——他们都是集成开发环境,而我们要学的是一门语言;
5.不要放过任何一个看上去很简单的小编程问题——他们往往并不那么简单,或者可以引伸出很多知识点;
6.会用Visual C++,并不说明你会C++;
7.学class并不难,template、STL、generic programming也不过如此——难的是长期坚持实践和不遗余力的博览群书;
8.如果不是天才的话,想学编程就不要想玩游戏——你以为你做到了,其实你的C++水平并没有和你通关的能力一起变高——其实可以时刻记住:学C++是为了编游戏的;
9.看Visual C++的书,是学不了C++语言的;
10.浮躁的人容易说:XX语言不行了,应该学YY;——是你自己不行了吧!?
11.浮躁的人容易问:我到底该学什么;——别问,学就对了; 12.浮躁的人容易问:XX有钱途吗;——建议你去抢银行;
13.浮躁的人容易说:我要中文版!我英文不行!——不行?学呀!
14.浮躁的人容易问:XX和YY哪个好;——告诉你吧,都好——只要你学就行;
15.浮躁的人分两种:a)只观望而不学的人;b)只学而不坚持的人;
16.把时髦的技术挂在嘴边,还不如把过时的技术记在心里; 17.C++不仅仅是支持面向对象的程序设计语言;
18.学习编程最好的方法之一就是阅读源代码;
19.在任何时刻都不要认为自己手中的书已经足够了;
20.请阅读《The Standard C++ Bible》(中文版:标准C++宝典),掌握C++标准;
21.看得懂的书,请仔细看;看不懂的书,请硬着头皮看;
22.别指望看第一遍书就能记住和掌握什么——请看第二遍、第三遍;
23.请看《Effective C++》和《More Effective C++》以及《Exceptional C++》;
24.不要停留在集成开发环境的摇篮上,要学会控制集成开发环境,还要学会用命令行方式处理程序;
25.和别人一起讨论有意义的C++知识点,而不是争吵XX行不行或者YY与ZZ哪个好;
26.请看《程序设计实践》,并严格的按照其要求去做;
27.不要因为C和C++中有一些语法和关键字看上去相同,就认为它们的意义和作用完全一样;
28.C++绝不是所谓的C的“扩充”——如果C++一开始就起名叫Z语言,你一定不会把C和Z语言联系得那么紧密;
29.请不要认为学过XX语言再改学C++会有什么问题——你只不过又在学一门全新的语言而已;
30.读完了《Inside The C++ Object Model》以后再来认定自己是不是已经学会了C++;
31.学习编程的秘诀是:编程,编程,再编程;
32.请留意下列书籍:《C++面向对象高效编程(C++ Effective Object-Oriented Software Construction)》《面向对象软件构造(Object-Oriented Software Construction)》《设计模式(Design Patterns)》《The Art of Computer Programming》;
33.记住:面向对象技术不只是C++专有的;
34.请把书上的程序例子亲手输入到电脑上实践,即使配套光盘中有源代码;
35.把在书中看到的有意义的例子扩充;
36.请重视C++中的异常处理技术,并将其切实的运用到自己的程序中;
37.经常回顾自己以前写过的程序,并尝试重写,把自己学到的新知识运用进去;
38.不要漏掉书中任何一个练习题——请全部做完并记录下解题思路;
39.C++语言和C++的集成开发环境要同时学习和掌握;
40.既然决定了学C++,就请坚持学下去,因为学习程序设计语言的目的是掌握程序设计技术,而程序设计技术是跨语言的;
41.就让C++语言的各种平台和开发环境去激烈的竞争吧,我们要以学习C++语言本身为主;
42.当你写C++程序写到一半却发现自己用的方法很拙劣时,请不要马上停手;请尽快将余下的部分粗略的完成以保证这个设计的完整性,然后分析自己的错误并重新设计和编写(参见
43.别心急,设计C++的class确实不容易;自己程序中的class和自己的class设计水平是在不断的编程实践中完善和发展的;
44.决不要因为程序“很小”就不遵循某些你不熟练的规则——好习惯是培养出来的,而不是一次记住的;
45.每学到一个C++难点的时候,尝试着对别人讲解这个知识点并让他理解——你能讲清楚才说明你真的理解了;
46.记录下在和别人交流时发现的自己忽视或不理解的知识点; 47.请不断地对自己写的程序提出更高的要求,哪怕你的程序版本号会变成Version 100.XX;
48.保存好你写过的所有的程序——那是你最好的积累之一;
49.请不要做浮躁的人;
50.请热爱C++!
补充: 对c++学习的一点感想,希望对初学者能有些帮助
1.如果你以前从来没有接触过c++,那么选择的第一本c++教程就显得尤为重要,我认为你可以参照以下的标准进行选择: a.对标准c++进行讲解,毕竟c++比从前发生了很大的变化。 b.要求全面,但不要很深,这要有助于你对于c++有一个全面的认识,打好基础,并且易懂的教材还能加快学习的进度,让自己保持一种成就感。 c.要有完整的范例来讲解每一个知识点如何运用,请注意这里所说的完整,并不是一个个代码片断。因为由于你以前从未接触过用c++进行编程,完整的代码可以使你有一个整体的概念,并且能够很快去进行大量的实践,因为变编程是从模仿开始,完整的代码恰恰告诉你了一个完整的步骤。不必自己去揣测。 d.推荐:《c++ primer plus》
2.当你有了一定的基础以后,就要选择一些书来迅速提高自己。这类书的特点是不仅仅教你如何去运用,而且要叫你如何去思考,并且你读起来也不是那么轻松。它意味深远,并不是你读一遍就能掌握的。 推荐:《thinking in c++》《effective c++》《more effective c++》 《c++ programming language》…《c++ 沉思录》
3.接下来就是对第二步所介绍的书籍进行反复的阅读,并且进行实践。由于这些书一位深远,每个人基于自己的基础都会有不同的收获,例如如果你的基础还没有达到某一高度,那么你就对一些精深的技术视而不见,不信?你可以试试,看看当自己有了一定提高之后再来读从前的一本书,你会发现许多新的东西。
扬州明月湖2